aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pretyping/evarutil.ml97
-rw-r--r--pretyping/evarutil.mli6
-rw-r--r--pretyping/evd.ml2
-rw-r--r--pretyping/evd.mli2
-rw-r--r--test-suite/success/evars.v40
5 files changed, 94 insertions, 53 deletions
diff --git a/pretyping/evarutil.ml b/pretyping/evarutil.ml
index ab3e655a1..cb64fcb56 100644
--- a/pretyping/evarutil.ml
+++ b/pretyping/evarutil.ml
@@ -139,7 +139,7 @@ let new_untyped_evar =
* functional operations on evar sets *
*------------------------------------*)
-let new_evar_instance sign evd typ ?(src=(dummy_loc,InternalHole)) ?(filter=None) instance =
+let new_evar_instance sign evd typ ?(src=(dummy_loc,InternalHole)) ?filter instance =
let instance =
match filter with
| None -> instance
@@ -148,7 +148,7 @@ let new_evar_instance sign evd typ ?(src=(dummy_loc,InternalHole)) ?(filter=None
(let ctxt = named_context_of_val sign in
list_distinct (ids_of_named_context ctxt));
let newevk = new_untyped_evar() in
- let evd = evar_declare sign newevk typ ~src:src ~filter:filter evd in
+ let evd = evar_declare sign newevk typ ~src:src ?filter evd in
(evd,mkEvar (newevk,Array.of_list instance))
(* Knowing that [Gamma |- ev : T] and that [ev] is applied to [args],
@@ -234,13 +234,13 @@ let push_rel_context_to_named_context env typ =
(* [new_evar] declares a new existential in an env env with type typ *)
(* Converting the env into the sign of the evar to define *)
-let new_evar evd env ?(src=(dummy_loc,InternalHole)) ?(filter=None) typ =
+let new_evar evd env ?(src=(dummy_loc,InternalHole)) ?filter typ =
let sign,typ',instance = push_rel_context_to_named_context env typ in
- new_evar_instance sign evd typ' ~src:src ~filter:filter instance
+ new_evar_instance sign evd typ' ~src:src ?filter instance
(* The same using side-effect *)
-let e_new_evar evdref env ?(src=(dummy_loc,InternalHole)) ?(filter=None) ty =
- let (evd',ev) = new_evar !evdref env ~src:src ~filter:filter ty in
+let e_new_evar evdref env ?(src=(dummy_loc,InternalHole)) ?filter ty =
+ let (evd',ev) = new_evar !evdref env ~src:src ?filter ty in
evdref := evd';
ev
@@ -339,31 +339,32 @@ let is_defined_equation env evd (ev,inst) rhs =
* making the z1..zm unavailable.
*)
-let shrink_context env' subst ty =
- let named_sign' = List.rev (named_context env') in
- let rel_sign' = rel_context env' in
+let shrink_context env subst ty =
+ let rev_named_sign = List.rev (named_context env) in
+ let rel_sign = rel_context env in
(* We merge the contexts (optimization) *)
- let rec shrink_rel i subst rel_subst rel_sign' =
- match subst,rel_sign' with
- | (id,c)::subst,_::rel_sign' when c = mkRel i ->
- shrink_rel (i-1) subst (mkVar id::rel_subst) rel_sign'
+ let rec shrink_rel i subst rel_subst rev_rel_sign =
+ match subst,rev_rel_sign with
+ | (id,c)::subst,_::rev_rel_sign when c = mkRel i ->
+ shrink_rel (i-1) subst (mkVar id::rel_subst) rev_rel_sign
| _ ->
- substl_rel_context rel_subst (List.rev rel_sign'), substl rel_subst ty
+ substl_rel_context rel_subst (List.rev rev_rel_sign),
+ substl rel_subst ty
in
- let rec shrink_named subst named_subst named_sign' =
- match subst,named_sign' with
- | (id,c)::subst,(id',b',t')::named_sign' when c = mkVar id' ->
- shrink_named subst ((id',mkVar id)::named_subst) named_sign'
+ let rec shrink_named subst named_subst rev_named_sign =
+ match subst,rev_named_sign with
+ | (id,c)::subst,(id',b',t')::rev_named_sign when c = mkVar id' ->
+ shrink_named subst ((id',mkVar id)::named_subst) rev_named_sign
| _::_, [] ->
- let nrel = List.length rel_sign' in
- let rel_sign', ty = shrink_rel nrel subst [] (List.rev rel_sign') in
- [], map_rel_context (replace_vars named_subst) rel_sign',
+ let nrel = List.length rel_sign in
+ let rel_sign, ty = shrink_rel nrel subst [] (List.rev rel_sign) in
+ [], map_rel_context (replace_vars named_subst) rel_sign,
replace_vars named_subst ty
| _ ->
- map_named_context (replace_vars named_subst) (List.rev named_sign'),
- rel_sign', ty
+ map_named_context (replace_vars named_subst) (List.rev rev_named_sign),
+ rel_sign, ty
in
- shrink_named subst [] named_sign'
+ shrink_named subst [] rev_named_sign
let extend_evar env evdref k (evk1,args1) c =
let ty = Retyping.get_type_of env (evars_of !evdref) c in
@@ -383,8 +384,7 @@ let extend_evar env evdref k (evk1,args1) c =
let rel_filter = list_map_i (fun i _ -> i > nb_to_hide) 1 rel_sign' in
let named_filter1 = List.map (fun _ -> true) (named_context (evar_env evi1)) in
let named_filter2 = List.map (fun _ -> false) named_sign' in
- let filter = named_filter1@named_filter2@rel_filter in
- let filter = if List.for_all (fun x -> x) filter then None else Some filter in
+ let filter = rel_filter@named_filter2@named_filter1 in
let evar1' = e_new_evar evdref extenv ~filter:filter ty in
let evk1',args1'_in_env = destEvar evar1' in
let args1'_in_extenv = Array.map (lift k) (overwrite_first args1'_in_env args1) in
@@ -405,7 +405,7 @@ let restrict_upon_filter evd evi evk p args =
let newfilter,newargs = subfilter p filter args in
if newfilter <> filter then
let (evd,newev) = new_evar evd (evar_env evi) ~src:(evar_source evk evd)
- ~filter:(Some newfilter) evi.evar_concl in
+ ~filter:newfilter evi.evar_concl in
let evd = Evd.evar_define evk newev evd in
evd,fst (destEvar newev),newargs
else
@@ -436,7 +436,7 @@ let do_restrict_hyps evd evk filter =
if oldb then List.hd filter::l,List.tl filter else (false::l,filter))
oldfilter ([],List.rev filter) in
let evd,nc = new_evar evd env ~src:(evar_source evk evd)
- ~filter:(Some filter) evi.evar_concl in
+ ~filter:filter evi.evar_concl in
let evd = Evd.evar_define evk nc evd in
let evk',_ = destEvar nc in
evd,evk'
@@ -627,15 +627,15 @@ let rec do_projection_effects define_fun env t evd = function
let evd = do_projection_effects define_fun env t evd p in
let ty = Retyping.get_type_of env (evars_of evd) t in
let ty = whd_betadeltaiota env (evars_of evd) ty in
- if not (isSort ty) & isEvar evi.evar_concl then
+ if not (isSort ty) then
(* Don't try to instantiate if a sort because if evar_concl is an
evar it may commit to a univ level which is not the right
one (however, regarding coercions, because t is obtained by
unif, we know that no coercion can be inserted) *)
let subst = make_pure_subst evi argsv in
let ty' = replace_vars subst evi.evar_concl in
- let evd = define_fun env (destEvar ty') ty evd in
- evd
+ let ty' = whd_evar (evars_of evd) ty' in
+ if isEvar ty' then define_fun env (destEvar ty') ty evd else evd
else
evd
@@ -661,19 +661,20 @@ type projectibility_status =
| CannotOccur
| Projectible of projectibility_kind
-let invert_subst env sigma subst t =
+let invert_subst env k sigma subst_in_env t_in_env_extended_with_k_binders =
let effects = ref [] in
let rec aux k t =
let t = whd_evar sigma t in
match kind_of_term t with
| Rel i when i>k ->
- project_with_effects env sigma effects (mkRel (i-k)) subst
+ project_with_effects env sigma effects (mkRel (i-k)) subst_in_env
| Var id ->
- project_with_effects env sigma effects t subst
+ project_with_effects env sigma effects t subst_in_env
| _ ->
map_constr_with_binders succ aux k t in
try
- let c = aux 0 t in Projectible (UniqueProjection (c,!effects))
+ let c = aux k t_in_env_extended_with_k_binders in
+ Projectible (UniqueProjection (c,!effects))
with
| NotUnique -> Projectible NoUniqueProjection
| Not_found -> CannotOccur
@@ -704,7 +705,7 @@ let solve_evar_evar_l2r f env evd (evk1,args1) (evk2,args2) t =
let evi2 = Evd.find (evars_of evd) evk2 in
let subst2 = make_projectable_subst (evars_of evd) evi2 args2 in
let proj1 =
- array_map_to_list (invert_subst env (evars_of evd) subst2) args1 in
+ array_map_to_list (invert_subst env 0 (evars_of evd) subst2) args1 in
let filter1 = List.map filter_of_projection proj1 in
try
(* Instantiate ev2 with (a restriction of) ev1 if uniquely projectable *)
@@ -724,6 +725,15 @@ let solve_evar_evar f env evd ev1 ev2 =
with CannotProject filter2 ->
postpone_evar_evar env evd filter1 ev1 filter2 ev2
+let add_evar_constraint env evd (evk,argsv) rhs =
+ let evi = Evd.find (evars_of evd) evk in
+ let evd,evk,args =
+ restrict_upon_filter evd evi evk
+ (fun a -> not (isRel a || isVar a) || dependent a rhs)
+ (Array.to_list argsv) in
+ let evar = mkEvar (evk,Array.of_list args) in
+ Evd.add_conv_pb (Reduction.CONV,env,evar,rhs) evd
+
(* We try to instantiate the evar assuming the body won't depend
* on arguments that are not Rels or Vars, or appearing several times
* (i.e. we tackle a generalization of Miller-Pfenning patterns unification)
@@ -776,16 +786,16 @@ let rec invert_instance env evd (evk,_ as ev) subst rhs =
| Var id -> project_variable env' t k t
| Evar (evk',args' as ev') ->
(* Evar/Evar problem (but left evar is virtual) *)
- let subst = List.map (fun (id,(idc,c)) -> (id,(idc,lift k c))) subst in
+(* let subst = List.map (fun (id,(idc,c)) -> (id,(idc,lift k c))) subst in*)
let projs' =
- array_map_to_list (invert_subst env (evars_of !evdref) subst) args'
+ array_map_to_list (invert_subst env k (evars_of !evdref) subst) args'
in
let filter' = List.map filter_of_projection projs' in
(try
(* Try to project (a restriction of) the right evar *)
let projs' = effective_projections projs' in
let evd,args' =
- list_fold_map (instance_of_projection evar_define env t)
+ list_fold_map (instance_of_projection evar_define env' t)
!evdref projs'
in
let evd,evk' = do_restrict_hyps !evdref evk' filter' in
@@ -850,12 +860,7 @@ and evar_define env (evk,argsv as ev) rhs evd =
Evd.evar_define evk body evd'
with
| NotYetSolvable ->
- let evd,evk,args =
- restrict_upon_filter evd evi evk
- (fun a -> (isRel a or isVar a) & not (dependent a rhs))
- (Array.to_list argsv) in
- let evar = mkEvar (evk,Array.of_list args) in
- Evd.add_conv_pb (Reduction.CONV,env,evar,rhs) evd
+ add_evar_constraint env evd ev rhs
| NotClean t ->
error_not_clean env (evars_of evd) evk t (evar_source evk evd)
@@ -967,7 +972,7 @@ let solve_refl conv_algo env evd evk argsv1 argsv2 =
(* Rq: uncomplete algorithm if pbty = CONV_X_LEQ ! *)
let solve_simple_eqn conv_algo env evd (pbty,(evk1,args1 as ev1),t2) =
try
- let t2 = nf_evar (evars_of evd) t2 in
+ let t2 = whd_evar (evars_of evd) t2 in
let evd = match kind_of_term t2 with
| Evar (evk2,args2 as ev2) ->
if evk1 = evk2 then
diff --git a/pretyping/evarutil.mli b/pretyping/evarutil.mli
index a3c3267e1..36b674fe5 100644
--- a/pretyping/evarutil.mli
+++ b/pretyping/evarutil.mli
@@ -34,10 +34,10 @@ val new_untyped_evar : unit -> existential_key
(***********************************************************)
(* Creating a fresh evar given their type and context *)
val new_evar :
- evar_defs -> env -> ?src:loc * hole_kind -> ?filter:bool list option -> types -> evar_defs * constr
+ evar_defs -> env -> ?src:loc * hole_kind -> ?filter:bool list -> types -> evar_defs * constr
(* the same with side-effects *)
val e_new_evar :
- evar_defs ref -> env -> ?src:loc * hole_kind -> ?filter:bool list option -> types -> constr
+ evar_defs ref -> env -> ?src:loc * hole_kind -> ?filter:bool list -> types -> constr
(* Create a fresh evar in a context different from its definition context:
[new_evar_instance sign evd ty inst] creates a new evar of context
@@ -46,7 +46,7 @@ val e_new_evar :
of [inst] are typed in the occurrence context and their type (seen
as a telescope) is [sign] *)
val new_evar_instance :
- named_context_val -> evar_defs -> types -> ?src:loc * hole_kind -> ?filter:bool list option -> constr list -> evar_defs * constr
+ named_context_val -> evar_defs -> types -> ?src:loc * hole_kind -> ?filter:bool list -> constr list -> evar_defs * constr
(***********************************************************)
(* Instantiate evars *)
diff --git a/pretyping/evd.ml b/pretyping/evd.ml
index 06b3a542d..300b4c8e6 100644
--- a/pretyping/evd.ml
+++ b/pretyping/evd.ml
@@ -425,7 +425,7 @@ let evar_define evk body evd =
evars = define evd.evars evk body;
last_mods = evk :: evd.last_mods }
-let evar_declare hyps evk ty ?(src=(dummy_loc,InternalHole)) ?(filter=None) evd =
+let evar_declare hyps evk ty ?(src=(dummy_loc,InternalHole)) ?filter evd =
let filter =
if filter = None then
List.map (fun _ -> true) (named_context_of_val hyps)
diff --git a/pretyping/evd.mli b/pretyping/evd.mli
index 1bf737609..b5a36c1f3 100644
--- a/pretyping/evd.mli
+++ b/pretyping/evd.mli
@@ -158,7 +158,7 @@ val is_undefined_evar : evar_defs -> constr -> bool
val undefined_evars : evar_defs -> evar_defs
val evar_declare :
named_context_val -> evar -> types -> ?src:loc * hole_kind ->
- ?filter:bool list option -> evar_defs -> evar_defs
+ ?filter:bool list -> evar_defs -> evar_defs
val evar_define : evar -> constr -> evar_defs -> evar_defs
val evar_source : existential_key -> evar_defs -> loc * hole_kind
diff --git a/test-suite/success/evars.v b/test-suite/success/evars.v
index 27470730d..e117bf62f 100644
--- a/test-suite/success/evars.v
+++ b/test-suite/success/evars.v
@@ -88,6 +88,14 @@ Parameter Out : STATE -> Output.
Check fun (s : STATE) (reg : Input) => reg = Out s.
End A.
+(* The return predicate found should be: "in _=U return U" *)
+(* (feature already available in V8.0) *)
+
+Definition g (T1 T2:Type) (x:T1) (e:T1=T2) : T2 :=
+ match e with
+ | refl_equal => x
+ end.
+
(* An example extracted from FMapAVL which (may) test restriction on
evars problems of the form ?n[args1]=?n[args2] with distinct args1
and args2 *)
@@ -121,9 +129,9 @@ Check (fun (A:Set) (a b x:A) (l:list A)
(* An example from NMake (simplified), that uses restriction in solve_refl *)
-Parameter g:(nat->nat)->(nat->nat).
+Parameter h:(nat->nat)->(nat->nat).
Fixpoint G p cont {struct p} :=
- g (fun n => match p with O => cont | S p => G p cont end n).
+ h (fun n => match p with O => cont | S p => G p cont end n).
(* An example from Bordeaux/Cantor that applies evar restriction
below a binder *)
@@ -150,3 +158,31 @@ Axiom merge_correct :
match merge eqA eqB l1 l2 with _ => True end.
Unset Implicit Arguments.
+(* An example from Bordeaux/Additions that tests restriction below binders *)
+
+Section Additions_while.
+
+Variable A : Set.
+Variables P Q : A -> Prop.
+Variable le : A -> A -> Prop.
+Hypothesis Q_dec : forall s : A, P s -> {Q s} + {~ Q s}.
+Hypothesis le_step : forall s : A, ~ Q s -> P s -> {s' | P s' /\ le s' s}.
+Hypothesis le_wf : well_founded le.
+
+Lemma loopexec : forall s : A, P s -> {s' : A | P s' /\ Q s'}.
+refine
+ (well_founded_induction_type le_wf (fun s => _ -> {s' : A | _ /\ _})
+ (fun s hr i =>
+ match Q_dec s i with
+ | left _ => _
+ | right _ =>
+ match le_step s _ _ with
+ | exist s' h' =>
+ match hr s' _ _ with
+ | exist s'' _ => exist _ s'' _
+ end
+ end
+ end)).
+Abort.
+
+End Additions_while.