aboutsummaryrefslogtreecommitdiff
path: root/pretyping
diff options
context:
space:
mode:
Diffstat (limited to 'pretyping')
-rw-r--r--pretyping/classops.ml8
-rw-r--r--pretyping/classops.mli3
-rw-r--r--pretyping/clenv.ml44
-rw-r--r--pretyping/coercion.ml95
-rw-r--r--pretyping/coercion.mli3
-rw-r--r--pretyping/evd.ml24
-rw-r--r--pretyping/evd.mli18
-rw-r--r--pretyping/reductionops.ml6
-rw-r--r--pretyping/unification.ml52
-rw-r--r--pretyping/unification.mli5
10 files changed, 139 insertions, 119 deletions
diff --git a/pretyping/classops.ml b/pretyping/classops.ml
index 5b0c2eb367..0d7e3d611c 100644
--- a/pretyping/classops.ml
+++ b/pretyping/classops.ml
@@ -44,7 +44,7 @@ type coe_typ = global_reference
type coe_info_typ = {
coe_value : constr;
coe_type : types;
- coe_strength : strength;
+ coe_strength : locality;
coe_is_identity : bool;
coe_param : int }
@@ -290,7 +290,7 @@ let add_coercion_in_graph (ic,source,target) =
if (!ambig_paths <> []) && is_verbose () then
ppnl (message_ambig !ambig_paths)
-type coercion = coe_typ * strength * bool * cl_typ * cl_typ * int
+type coercion = coe_typ * locality * bool * cl_typ * cl_typ * int
(* Calcul de l'arit้ d'une classe *)
@@ -304,7 +304,7 @@ let class_params = function
| CL_SECVAR sp -> reference_arity_length (VarRef sp)
| CL_IND sp -> reference_arity_length (IndRef sp)
-(* add_class : cl_typ -> strength option -> bool -> unit *)
+(* add_class : cl_typ -> locality_flag option -> bool -> unit *)
let add_class cl =
add_new_class cl { cl_param = class_params cl }
@@ -366,6 +366,8 @@ let coercion_identity v = v.coe_is_identity
(* For printing purpose *)
let get_coercion_value v = v.coe_value
+let pr_cl_index n = int n
+
let classes () = Bijint.dom !class_tab
let coercions () = Gmap.rng !coercion_tab
let inheritance_graph () = Gmap.to_list !inheritance_graph
diff --git a/pretyping/classops.mli b/pretyping/classops.mli
index dd51ee970a..c1a62b34fd 100644
--- a/pretyping/classops.mli
+++ b/pretyping/classops.mli
@@ -66,7 +66,7 @@ val class_args_of : constr -> constr list
(*s [declare_coercion] adds a coercion in the graph of coercion paths *)
val declare_coercion :
- coe_typ -> strength -> isid:bool ->
+ coe_typ -> locality -> isid:bool ->
src:cl_typ -> target:cl_typ -> params:int -> unit
(*s Access to coercions infos *)
@@ -90,6 +90,7 @@ val install_path_printer :
(*s This is for printing purpose *)
val string_of_class : cl_typ -> string
val pr_class : cl_typ -> std_ppcmds
+val pr_cl_index : cl_index -> std_ppcmds
val get_coercion_value : coe_index -> constr
val inheritance_graph : unit -> ((cl_index * cl_index) * inheritance_path) list
val classes : unit -> cl_typ list
diff --git a/pretyping/clenv.ml b/pretyping/clenv.ml
index ed9d779ad7..e7423c748b 100644
--- a/pretyping/clenv.ml
+++ b/pretyping/clenv.ml
@@ -28,15 +28,7 @@ open Unification
open Mod_subst
open Coercion.Default
-(* *)
-let w_coerce env c ctyp target evd =
- try
- let j = make_judge c ctyp in
- let tycon = mk_tycon_type target in
- let (evd',j') = inh_conv_coerce_to dummy_loc env evd j tycon in
- (evd',j'.uj_val)
- with e when precatchable_exception e ->
- evd,c
+(* Abbreviations *)
let pf_env gls = Global.env_of_context gls.it.evar_hyps
let pf_type_of gls c = Typing.type_of (pf_env gls) gls.sigma c
@@ -398,36 +390,24 @@ let error_already_defined b =
anomalylabstrm ""
(str "Position " ++ int n ++ str" already defined")
-let rec similar_type_shapes t u =
- let t,_ = decompose_app t and u,_ = decompose_app u in
- match kind_of_term t, kind_of_term u with
- | Prod (_,t1,t2), Prod (_,u1,u2) -> similar_type_shapes t2 u2
- | Const cst, Const cst' -> cst = cst'
- | Var id, Var id' -> id = id'
- | Ind ind, Ind ind' -> ind = ind'
- | Rel n, Rel n' -> n = n'
- | Sort s, Sort s' -> family_of_sort s = family_of_sort s'
- | Case (_,_,c,_), Case (_,_,c',_) -> similar_type_shapes c c'
- | _ -> false
-
-let clenv_unify_similar_types clenv c t u =
- if occur_meta u then
- if similar_type_shapes t u then
- try TypeProcessed, clenv_unify true CUMUL t u clenv, c
- with e when precatchable_exception e -> TypeNotProcessed, clenv, c
- else
- CoerceToType, clenv, c
+let clenv_unify_binding_type clenv c t u =
+ if isMeta (fst (whd_stack u)) then
+ (* Not enough information to know if some subtyping is needed *)
+ CoerceToType, clenv, c
else
- let evd,c = w_coerce (cl_env clenv) c t u clenv.evd in
- TypeProcessed, { clenv with evd = evd }, c
+ (* Enough information so as to try a coercion now *)
+ try
+ let evd,c = w_coerce_to_type (cl_env clenv) clenv.evd c t u in
+ TypeProcessed, { clenv with evd = evd }, c
+ with e when precatchable_exception e ->
+ TypeNotProcessed, clenv, c
let clenv_assign_binding clenv k (sigma,c) =
let k_typ = clenv_hnf_constr clenv (clenv_meta_type clenv k) in
let clenv' = { clenv with evd = evar_merge clenv.evd sigma} in
let c_typ = nf_betaiota (clenv_get_type_of clenv' c) in
let c_typ = clenv_hnf_constr clenv' c_typ in
- let status,clenv'',c = clenv_unify_similar_types clenv' c c_typ k_typ in
-(* let evd,c' = w_coerce (cl_env clenv') c c_typ k_typ clenv'.evd in*)
+ let status,clenv'',c = clenv_unify_binding_type clenv' c c_typ k_typ in
{ clenv'' with evd = meta_assign k (c,(UserGiven,status)) clenv''.evd }
let clenv_match_args bl clenv =
diff --git a/pretyping/coercion.ml b/pretyping/coercion.ml
index 729bd84f1f..bd023721ae 100644
--- a/pretyping/coercion.ml
+++ b/pretyping/coercion.ml
@@ -48,7 +48,9 @@ module type S = sig
[j.uj_type] are convertible; it fails if no coercion is applicable *)
val inh_conv_coerce_to : loc ->
env -> evar_defs -> unsafe_judgment -> type_constraint_type -> evar_defs * unsafe_judgment
-
+
+ val inh_conv_coerce_rigid_to : loc ->
+ env -> evar_defs -> unsafe_judgment -> type_constraint_type -> evar_defs * unsafe_judgment
(* [inh_conv_coerces_to loc env evd t t'] checks if an object of type [t]
is coercible to an object of type [t'] adding evar constraints if needed;
@@ -158,7 +160,11 @@ module Default = struct
let inh_coerce_to_base loc env evd j = (evd, j)
- let inh_coerce_to_fail env evd c1 v t =
+ let inh_coerce_to_fail env evd rigidonly v c1 t =
+ if rigidonly & not (Heads.is_rigid env c1 && Heads.is_rigid env t)
+ then
+ raise NoCoercion
+ else
let v', t' =
try
let t1,i1 = class_of1 env evd c1 in
@@ -171,77 +177,44 @@ module Default = struct
| None -> None, t
with Not_found -> raise NoCoercion
in
- try (the_conv_x_leq env t' c1 evd, v', t')
+ try (the_conv_x_leq env t' c1 evd, v')
with Reduction.NotConvertible -> raise NoCoercion
- let rec inh_conv_coerce_to_fail loc env evd v t c1 =
- try (the_conv_x_leq env t c1 evd, v, t)
+ let rec inh_conv_coerce_to_fail loc env evd rigidonly v t c1 =
+ try (the_conv_x_leq env t c1 evd, v)
with Reduction.NotConvertible ->
- try inh_coerce_to_fail env evd c1 v t
+ try inh_coerce_to_fail env evd rigidonly v c1 t
with NoCoercion ->
match
kind_of_term (whd_betadeltaiota env (evars_of evd) t),
kind_of_term (whd_betadeltaiota env (evars_of evd) c1)
with
- | Prod (_,t1,t2), Prod (name,u1,u2) ->
- let v' = Option.map (whd_betadeltaiota env (evars_of evd)) v in
- let (evd',b) =
- match v' with
- | Some v' ->
- (match kind_of_term v' with
- | Lambda (x,v1,v2) ->
- (* sous-typage non contravariant: pas de "leq v1 u1" *)
- (try the_conv_x env v1 u1 evd, Some (x, v1, v2)
- with Reduction.NotConvertible -> (evd, None))
- | _ -> (evd, None))
- | None -> (evd, None)
- in
- (match b with
- | Some (x, v1, v2) ->
- let env1 = push_rel (x,None,v1) env in
- let (evd'', v2', t2') = inh_conv_coerce_to_fail loc env1 evd'
- (Some v2) t2 u2 in
- (evd'', Option.map (fun v2' -> mkLambda (x, v1, v2')) v2',
- mkProd (x, v1, t2'))
- | None ->
- (* Mismatch on t1 and u1 or not a lambda: we eta-expand *)
- (* we look for a coercion c:u1->t1 s.t. [name:u1](v' (c x)) *)
- (* has type (name:u1)u2 (with v' recursively obtained) *)
- let name = match name with
- | Anonymous -> Name (id_of_string "x")
- | _ -> name
- in
- let env1 = push_rel (name,None,u1) env in
- let (evd', v1', t1') =
- inh_conv_coerce_to_fail loc env1 evd
- (Some (mkRel 1)) (lift 1 u1) (lift 1 t1)
- in
- let (evd'', v2', t2') =
- let v2 =
- match v with
- | Some v -> Option.map (fun x -> mkApp(lift 1 v,[|x|])) v1'
- | None -> None
- and evd', t2 =
- match v1' with
- | Some v1' -> evd', subst_term v1' t2
- | None ->
- let evd', ev =
- new_evar evd' env ~src:(loc, InternalHole) t1' in
- evd', subst_term ev t2
- in
- inh_conv_coerce_to_fail loc env1 evd' v2 t2 u2
- in
- (evd'', Option.map (fun v2' -> mkLambda (name, u1, v2')) v2',
- mkProd (name, u1, t2')))
+ | Prod (name,t1,t2), Prod (_,u1,u2) ->
+ (* Conversion did not work, we may succeed with a coercion. *)
+ (* We eta-expand (hence possibly modifying the original term!) *)
+ (* and look for a coercion c:u1->t1 s.t. fun x:u1 => v' (c x)) *)
+ (* has type forall (x:u1), u2 (with v' recursively obtained) *)
+ let name = match name with
+ | Anonymous -> Name (id_of_string "x")
+ | _ -> name in
+ let env1 = push_rel (name,None,u1) env in
+ let (evd', v1) =
+ inh_conv_coerce_to_fail loc env1 evd rigidonly
+ (Some (mkRel 1)) (lift 1 u1) (lift 1 t1) in
+ let v1 = Option.get v1 in
+ let v2 = Option.map (fun v -> beta_applist (lift 1 v,[v1])) v in
+ let t2 = subst_term v1 t2 in
+ let (evd'',v2') = inh_conv_coerce_to_fail loc env1 evd' rigidonly v2 t2 u2 in
+ (evd'', Option.map (fun v2' -> mkLambda (name, u1, v2')) v2')
| _ -> raise NoCoercion
(* Look for cj' obtained from cj by inserting coercions, s.t. cj'.typ = t *)
- let inh_conv_coerce_to loc env evd cj (n, t) =
+ let inh_conv_coerce_to_gen rigidonly loc env evd cj (n, t) =
match n with
None ->
- let (evd', val', type') =
+ let (evd', val') =
try
- inh_conv_coerce_to_fail loc env evd (Some cj.uj_val) cj.uj_type t
+ inh_conv_coerce_to_fail loc env evd rigidonly (Some cj.uj_val) cj.uj_type t
with NoCoercion ->
let sigma = evars_of evd in
error_actual_type_loc loc env sigma cj t
@@ -249,6 +222,10 @@ module Default = struct
let val' = match val' with Some v -> v | None -> assert(false) in
(evd',{ uj_val = val'; uj_type = t })
| Some (init, cur) -> (evd, cj)
+
+ let inh_conv_coerce_to = inh_conv_coerce_to_gen false
+ let inh_conv_coerce_rigid_to = inh_conv_coerce_to_gen true
+
let inh_conv_coerces_to loc env (evd : evar_defs) t (abs, t') = evd
(* Still problematic, as it changes unification
diff --git a/pretyping/coercion.mli b/pretyping/coercion.mli
index 5476a4820c..00735d8746 100644
--- a/pretyping/coercion.mli
+++ b/pretyping/coercion.mli
@@ -45,6 +45,9 @@ module type S = sig
[j.uj_type] are convertible; it fails if no coercion is applicable *)
val inh_conv_coerce_to : loc ->
env -> evar_defs -> unsafe_judgment -> type_constraint_type -> evar_defs * unsafe_judgment
+
+ val inh_conv_coerce_rigid_to : loc ->
+ env -> evar_defs -> unsafe_judgment -> type_constraint_type -> evar_defs * unsafe_judgment
(* [inh_conv_coerces_to loc env isevars t t'] checks if an object of type [t]
is coercible to an object of type [t'] adding evar constraints if needed;
diff --git a/pretyping/evd.ml b/pretyping/evd.ml
index 3adf749f07..ddc3654dc7 100644
--- a/pretyping/evd.ml
+++ b/pretyping/evd.ml
@@ -341,7 +341,7 @@ let mk_freelisted c =
let map_fl f cfl = { cfl with rebus=f cfl.rebus }
-(* Status of an instance wrt to the meta it solves:
+(* Status of an instance found by unification wrt to the meta it solves:
- a supertype of the meta (e.g. the solution to ?X <= T is a supertype of ?X)
- a subtype of the meta (e.g. the solution to T <= ?X is a supertype of ?X)
- a term that can be eta-expanded n times while still being a solution
@@ -351,9 +351,24 @@ let map_fl f cfl = { cfl with rebus=f cfl.rebus }
type instance_constraint =
IsSuperType | IsSubType | ConvUpToEta of int | UserGiven
+(* Status of the unification of the type of an instance against the type of
+ the meta it instantiates:
+ - CoerceToType means that the unification of types has not been done
+ and that a coercion can still be inserted: the meta should not be
+ substituted freely (this happens for instance given via the
+ "with" binding clause).
+ - TypeProcessed means that the information obtainable from the
+ unification of types has been extracted.
+ - TypeNotProcessed means that the unification of types has not been
+ done but it is known that no coercion may be inserted: the meta
+ can be substituted freely.
+*)
+
type instance_typing_status =
CoerceToType | TypeNotProcessed | TypeProcessed
+(* Status of an instance together with the status of its type unification *)
+
type instance_status = instance_constraint * instance_typing_status
(* Clausal environments *)
@@ -519,6 +534,13 @@ let metas_of evd =
| (n,Cltyp (_,typ)) -> (n,typ.rebus))
(meta_list evd)
+let map_metas_fvalue f evd =
+ { evd with metas =
+ Metamap.map
+ (function
+ | Clval(id,(c,s),typ) -> Clval(id,(mk_freelisted (f c.rebus),s),typ)
+ | x -> x) evd.metas }
+
let meta_opt_fvalue evd mv =
match Metamap.find mv evd.metas with
| Clval(_,b,_) -> Some b
diff --git a/pretyping/evd.mli b/pretyping/evd.mli
index 352d3021d9..71c6bb0dc3 100644
--- a/pretyping/evd.mli
+++ b/pretyping/evd.mli
@@ -122,11 +122,28 @@ val map_fl : ('a -> 'b) -> 'a freelisted -> 'b freelisted
type instance_constraint =
IsSuperType | IsSubType | ConvUpToEta of int | UserGiven
+(* Status of the unification of the type of an instance against the type of
+ the meta it instantiates:
+ - CoerceToType means that the unification of types has not been done
+ and that a coercion can still be inserted: the meta should not be
+ substituted freely (this happens for instance given via the
+ "with" binding clause).
+ - TypeProcessed means that the information obtainable from the
+ unification of types has been extracted.
+ - TypeNotProcessed means that the unification of types has not been
+ done but it is known that no coercion may be inserted: the meta
+ can be substituted freely.
+*)
+
type instance_typing_status =
CoerceToType | TypeNotProcessed | TypeProcessed
+(* Status of an instance together with the status of its type unification *)
+
type instance_status = instance_constraint * instance_typing_status
+(* Clausal environments *)
+
type clbinding =
| Cltyp of name * constr freelisted
| Clval of name * (constr freelisted * instance_status) * constr freelisted
@@ -198,6 +215,7 @@ val meta_merge : evar_defs -> evar_defs -> evar_defs
val undefined_metas : evar_defs -> metavariable list
val metas_of : evar_defs -> metamap
+val map_metas_fvalue : (constr -> constr) -> evar_defs -> evar_defs
type metabinding = metavariable * constr * instance_status
diff --git a/pretyping/reductionops.ml b/pretyping/reductionops.ml
index e118a659e9..e825b3f488 100644
--- a/pretyping/reductionops.ml
+++ b/pretyping/reductionops.ml
@@ -946,7 +946,7 @@ let meta_reducible_instance evd b =
(match
try
let g,s = List.assoc m metas in
- if isConstruct g or s = TypeProcessed then Some g else None
+ if isConstruct g or s <> CoerceToType then Some g else None
with Not_found -> None
with
| Some g -> irec (mkCase (ci,p,g,bl))
@@ -956,13 +956,13 @@ let meta_reducible_instance evd b =
(match
try
let g,s = List.assoc m metas in
- if isLambda g or s = TypeProcessed then Some g else None
+ if isLambda g or s <> CoerceToType then Some g else None
with Not_found -> None
with
| Some g -> irec (mkApp (g,l))
| None -> mkApp (f,Array.map irec l))
| Meta m ->
- (try let g,s = List.assoc m metas in if s=TypeProcessed then irec g else u
+ (try let g,s = List.assoc m metas in if s<>CoerceToType then irec g else u
with Not_found -> u)
| _ -> map_constr irec u
in
diff --git a/pretyping/unification.ml b/pretyping/unification.ml
index c5e9dff8b4..b140ad51aa 100644
--- a/pretyping/unification.ml
+++ b/pretyping/unification.ml
@@ -24,6 +24,7 @@ open Pattern
open Evarutil
open Pretype_errors
open Retyping
+open Coercion.Default
(* if lname_typ is [xn,An;..;x1,A1] and l is a list of terms,
gives [x1:A1]..[xn:An]c' such that c converts to ([x1:A1]..[xn:An]c' l) *)
@@ -380,14 +381,39 @@ let is_mimick_head f =
(Const _|Var _|Rel _|Construct _|Ind _) -> true
| _ -> false
-let w_coerce env c ctyp target evd =
+let pose_all_metas_as_evars env evd t =
+ let evdref = ref evd in
+ let rec aux t = match kind_of_term t with
+ | Meta mv ->
+ (match Evd.meta_opt_fvalue !evdref mv with
+ | Some ({rebus=c},_) -> c
+ | None ->
+ let {rebus=ty;freemetas=mvs} = Evd.meta_ftype evd mv in
+ let ty = if mvs = Evd.Metaset.empty then ty else aux ty in
+ let ev = Evarutil.e_new_evar evdref env ~src:(dummy_loc,GoalEvar) ty in
+ evdref := meta_assign mv (ev,(ConvUpToEta 0,TypeNotProcessed)) !evdref;
+ ev)
+ | _ ->
+ map_constr aux t in
+ let c = aux t in
+ (* side-effect *)
+ (!evdref, c)
+
+let w_coerce_to_type env evd c cty mvty =
try
- let j = make_judge c ctyp in
- let tycon = mk_tycon_type target in
- let (evd',j') = Coercion.Default.inh_conv_coerce_to dummy_loc env evd j tycon in
+ let j = make_judge c cty in
+ let evd,mvty = pose_all_metas_as_evars env evd mvty in
+ let tycon = mk_tycon_type mvty in
+ let (evd',j') = inh_conv_coerce_rigid_to dummy_loc env evd j tycon in
+ let evd' = Evd.map_metas_fvalue (nf_evar (evars_of evd')) evd' in
(evd',j'.uj_val)
with e when precatchable_exception e ->
- evd,c
+ (evd,c)
+
+let w_coerce env evd mv c =
+ let cty = get_type_of env (evars_of evd) c in
+ let mvty = Typing.meta_type evd mv in
+ w_coerce_to_type env evd c cty mvty
let unify_to_type env evd flags c u =
let sigma = evars_of evd in
@@ -398,20 +424,6 @@ let unify_to_type env evd flags c u =
try unify_0 env sigma Cumul flags t u
with e when precatchable_exception e -> ([],[])
-let coerce_to_type env evd c u =
- let c = refresh_universes c in
- let t = get_type_of_with_meta env (evars_of evd) (metas_of evd) c in
- w_coerce env c t u evd
-
-let unify_or_coerce_type env evd flags mv c =
- let mvty = Typing.meta_type evd mv in
- (* nf_betaiota was before in type_of - useful to reduce
- types like (x:A)([x]P u) *)
- if occur_meta mvty then
- (evd,c),unify_to_type env evd flags c mvty
- else
- coerce_to_type env evd c mvty,([],[])
-
let unify_type env evd flags mv c =
let mvty = Typing.meta_type evd mv in
if occur_meta mvty then
@@ -471,7 +483,7 @@ let w_merge env with_types flags metas evars evd =
if with_types & to_type <> TypeProcessed then
if to_type = CoerceToType then
(* Some coercion may have to be inserted *)
- (unify_or_coerce_type env evd flags mv c,[])
+ (w_coerce env evd mv c,([],[])),[]
else
(* No coercion needed: delay the unification of types *)
((evd,c),([],[])),(mv,c)::eqns
diff --git a/pretyping/unification.mli b/pretyping/unification.mli
index 9156623f50..1b8f9ccd8b 100644
--- a/pretyping/unification.mli
+++ b/pretyping/unification.mli
@@ -35,6 +35,11 @@ val w_unify_to_subterm :
val w_unify_meta_types : env -> ?flags:unify_flags -> evar_defs -> evar_defs
+(* [w_coerce_to_type env evd c ctyp typ] tries to coerce [c] of type
+ [ctyp] so that its gets type [typ]; [typ] may contain metavariables *)
+val w_coerce_to_type : env -> evar_defs -> constr -> types -> types ->
+ evar_defs * constr
+
(*i This should be in another module i*)
(* [abstract_list_all env evd t c l] *)