aboutsummaryrefslogtreecommitdiff
path: root/pretyping
diff options
context:
space:
mode:
authorPierre-Marie Pédrot2016-07-13 17:00:25 +0200
committerPierre-Marie Pédrot2016-07-13 17:00:25 +0200
commit9f003b933c2a3504683a84ed817021659e80bc8f (patch)
tree4e9636ca44aed009d2274b03e64313c770a8b026 /pretyping
parent7217d14466bf900ec0353b6bbcb7e4d4b78ec2bf (diff)
parent45250332a1e65d434432940a468312f2ab18a2e8 (diff)
Merge branch 'v8.6'
Diffstat (limited to 'pretyping')
-rw-r--r--pretyping/cases.ml12
-rw-r--r--pretyping/evarsolve.ml7
-rw-r--r--pretyping/evarsolve.mli8
-rw-r--r--pretyping/indrec.ml34
-rw-r--r--pretyping/indrec.mli7
-rw-r--r--pretyping/inductiveops.ml34
-rw-r--r--pretyping/inductiveops.mli15
-rw-r--r--pretyping/pretyping.ml17
-rw-r--r--pretyping/recordops.ml18
9 files changed, 100 insertions, 52 deletions
diff --git a/pretyping/cases.ml b/pretyping/cases.ml
index 985ad4b0d3..447a4c487c 100644
--- a/pretyping/cases.ml
+++ b/pretyping/cases.ml
@@ -1329,14 +1329,6 @@ let build_branch initial current realargs deps (realnames,curname) pb arsign eqn
*)
-let mk_case pb (ci,pred,c,brs) =
- let mib = lookup_mind (fst ci.ci_ind) pb.env in
- match mib.mind_record with
- | Some (Some (_, cs, pbs)) ->
- Reduction.beta_appvect brs.(0)
- (Array.map (fun p -> mkProj (Projection.make p true, c)) cs)
- | _ -> mkCase (ci,pred,c,brs)
-
(**********************************************************************)
(* Main compiling descent *)
let rec compile pb =
@@ -1383,7 +1375,9 @@ and match_current pb (initial,tomatch) =
pred current indt (names,dep) tomatch in
let ci = make_case_info pb.env (fst mind) pb.casestyle in
let pred = nf_betaiota !(pb.evdref) pred in
- let case = mk_case pb (ci,pred,current,brvals) in
+ let case =
+ make_case_or_project pb.env indf ci pred current brvals
+ in
Typing.check_allowed_sort pb.env !(pb.evdref) mind current pred;
{ uj_val = applist (case, inst);
uj_type = prod_applist typ inst }
diff --git a/pretyping/evarsolve.ml b/pretyping/evarsolve.ml
index 338ac43009..6c8677855a 100644
--- a/pretyping/evarsolve.ml
+++ b/pretyping/evarsolve.ml
@@ -47,7 +47,8 @@ let refresh_level evd s =
| None -> true
| Some l -> not (Evd.is_flexible_level evd l)
-let refresh_universes ?(status=univ_rigid) ?(onlyalg=false) pbty env evd t =
+let refresh_universes ?(status=univ_rigid) ?(onlyalg=false) ?(refreshset=false)
+ pbty env evd t =
let evdref = ref evd in
let modified = ref false in
let rec refresh status dir t =
@@ -62,6 +63,10 @@ let refresh_universes ?(status=univ_rigid) ?(onlyalg=false) pbty env evd t =
else set_leq_sort env !evdref s s'
in
modified := true; evdref := evd; mkSort s'
+ | Sort (Prop Pos as s) when refreshset && not dir ->
+ let s' = evd_comb0 (new_sort_variable status) evdref in
+ let evd = set_leq_sort env !evdref s s' in
+ modified := true; evdref := evd; mkSort s'
| Prod (na,u,v) ->
mkProd (na,u,refresh status dir v)
| _ -> t
diff --git a/pretyping/evarsolve.mli b/pretyping/evarsolve.mli
index 918ba12f0f..f94c83b6dc 100644
--- a/pretyping/evarsolve.mli
+++ b/pretyping/evarsolve.mli
@@ -34,8 +34,12 @@ type conv_fun_bool =
val evar_define : conv_fun -> ?choose:bool -> env -> evar_map ->
bool option -> existential -> constr -> evar_map
-val refresh_universes : ?status:Evd.rigid ->
- ?onlyalg:bool (* Only algebraic universes *) ->
+val refresh_universes :
+ ?status:Evd.rigid ->
+ ?onlyalg:bool (* Only algebraic universes *) ->
+ ?refreshset:bool ->
+ (* Also refresh Prop and Set universes, so that the returned type can be any supertype
+ of the original type *)
bool option (* direction: true for levels lower than the existing levels *) ->
env -> evar_map -> types -> evar_map * types
diff --git a/pretyping/indrec.ml b/pretyping/indrec.ml
index 0c80bd0193..39aeb41f77 100644
--- a/pretyping/indrec.ml
+++ b/pretyping/indrec.ml
@@ -36,12 +36,14 @@ type dep_flag = bool
type recursion_scheme_error =
| NotAllowedCaseAnalysis of (*isrec:*) bool * sorts * pinductive
| NotMutualInScheme of inductive * inductive
+ | NotAllowedDependentAnalysis of (*isrec:*) bool * inductive
exception RecursionSchemeError of recursion_scheme_error
let make_prod_dep dep env = if dep then mkProd_name env else mkProd
let mkLambda_string s t c = mkLambda (Name (Id.of_string s), t, c)
+
(*******************************************)
(* Building curryfied elimination *)
(*******************************************)
@@ -375,27 +377,9 @@ let mis_make_indrec env sigma listdepkind mib u =
(Anonymous,depind',concl))
arsign'
in
- let obj =
- let projs = get_projections env indf in
- match projs with
- | None -> (mkCase (ci, pred,
- mkRel 1,
- branches))
- | Some ps ->
- let branch = branches.(0) in
- let ctx, br = decompose_lam_assum branch in
- let n, subst =
- List.fold_right (fun decl (i, subst) ->
- match decl with
- | LocalAssum (na,t) ->
- let t = mkProj (Projection.make ps.(i) true, mkRel 1) in
- i + 1, t :: subst
- | LocalDef (na,b,t) ->
- i, mkRel 0 :: subst)
- ctx (0, [])
- in
- let term = substl subst br in
- term
+ let obj =
+ Inductiveops.make_case_or_project env indf ci pred
+ (mkRel 1) branches
in
it_mkLambda_or_LetIn_name env obj
(Termops.lift_rel_context nrec deparsign)
@@ -483,6 +467,8 @@ let mis_make_indrec env sigma listdepkind mib u =
let build_case_analysis_scheme env sigma pity dep kind =
let (mib,mip) = lookup_mind_specif env (fst pity) in
+ if dep && not (Inductiveops.has_dependent_elim mib) then
+ raise (RecursionSchemeError (NotAllowedDependentAnalysis (false, fst pity)));
mis_make_case_com dep env sigma pity (mib,mip) kind
let is_in_prop mip =
@@ -492,7 +478,7 @@ let is_in_prop mip =
let build_case_analysis_scheme_default env sigma pity kind =
let (mib,mip) = lookup_mind_specif env (fst pity) in
- let dep = not (is_in_prop mip) in
+ let dep = not (is_in_prop mip || not (Inductiveops.has_dependent_elim mib)) in
mis_make_case_com dep env sigma pity (mib,mip) kind
(**********************************************************************)
@@ -553,6 +539,8 @@ let check_arities env listdepkind =
let build_mutual_induction_scheme env sigma = function
| ((mind,u),dep,s)::lrecspec ->
let (mib,mip) = lookup_mind_specif env mind in
+ if dep && not (Inductiveops.has_dependent_elim mib) then
+ raise (RecursionSchemeError (NotAllowedDependentAnalysis (true, mind)));
let (sp,tyi) = mind in
let listdepkind =
((mind,u),mib,mip,dep,s)::
@@ -572,6 +560,8 @@ let build_mutual_induction_scheme env sigma = function
let build_induction_scheme env sigma pind dep kind =
let (mib,mip) = lookup_mind_specif env (fst pind) in
+ if dep && not (Inductiveops.has_dependent_elim mib) then
+ raise (RecursionSchemeError (NotAllowedDependentAnalysis (true, fst pind)));
let sigma, l = mis_make_indrec env sigma [(pind,mib,mip,dep,kind)] mib (snd pind) in
sigma, List.hd l
diff --git a/pretyping/indrec.mli b/pretyping/indrec.mli
index f0736d2dda..192b64a5ed 100644
--- a/pretyping/indrec.mli
+++ b/pretyping/indrec.mli
@@ -16,6 +16,7 @@ open Evd
type recursion_scheme_error =
| NotAllowedCaseAnalysis of (*isrec:*) bool * sorts * pinductive
| NotMutualInScheme of inductive * inductive
+ | NotAllowedDependentAnalysis of (*isrec:*) bool * inductive
exception RecursionSchemeError of recursion_scheme_error
@@ -28,13 +29,15 @@ type dep_flag = bool
val build_case_analysis_scheme : env -> 'r Sigma.t -> pinductive ->
dep_flag -> sorts_family -> (constr, 'r) Sigma.sigma
-(** Build a dependent case elimination predicate unless type is in Prop *)
+(** Build a dependent case elimination predicate unless type is in Prop
+ or is a recursive record with primitive projections. *)
val build_case_analysis_scheme_default : env -> 'r Sigma.t -> pinductive ->
sorts_family -> (constr, 'r) Sigma.sigma
(** Builds a recursive induction scheme (Peano-induction style) in the same
- sort family as the inductive family; it is dependent if not in Prop *)
+ sort family as the inductive family; it is dependent if not in Prop
+ or a recursive record with primitive projections. *)
val build_induction_scheme : env -> evar_map -> pinductive ->
dep_flag -> sorts_family -> evar_map * constr
diff --git a/pretyping/inductiveops.ml b/pretyping/inductiveops.ml
index fbad0d949d..214e19fecf 100644
--- a/pretyping/inductiveops.ml
+++ b/pretyping/inductiveops.ml
@@ -269,6 +269,11 @@ let projection_nparams_env env p =
let projection_nparams p = projection_nparams_env (Global.env ()) p
+let has_dependent_elim mib =
+ match mib.mind_record with
+ | Some (Some _) -> mib.mind_finite == Decl_kinds.BiFinite
+ | _ -> true
+
(* Annotation for cases *)
let make_case_info env ind style =
let (mib,mip) = Inductive.lookup_mind_specif env ind in
@@ -338,6 +343,35 @@ let get_projections env (ind,params) =
| Some (Some (id, projs, pbs)) -> Some projs
| _ -> None
+let make_case_or_project env indf ci pred c branches =
+ let projs = get_projections env indf in
+ match projs with
+ | None -> (mkCase (ci, pred, c, branches))
+ | Some ps ->
+ assert(Array.length branches == 1);
+ let () =
+ let _, _, t = destLambda pred in
+ let (ind, _), _ = dest_ind_family indf in
+ let mib, _ = Inductive.lookup_mind_specif env ind in
+ if (* dependent *) not (noccurn 1 t) &&
+ not (has_dependent_elim mib) then
+ errorlabstrm "make_case_or_project"
+ Pp.(str"Dependent case analysis not allowed" ++
+ str" on inductive type " ++ Names.MutInd.print (fst ind))
+ in
+ let branch = branches.(0) in
+ let ctx, br = decompose_lam_n_assum (Array.length ps) branch in
+ let n, subst =
+ List.fold_right
+ (fun decl (i, subst) ->
+ match decl with
+ | LocalAssum (na, t) ->
+ let t = mkProj (Projection.make ps.(i) true, c) in
+ (i + 1, t :: subst)
+ | LocalDef (na, b, t) -> (i, substl subst b :: subst))
+ ctx (0, [])
+ in substl subst br
+
(* substitution in a signature *)
let substnl_rel_context subst n sign =
diff --git a/pretyping/inductiveops.mli b/pretyping/inductiveops.mli
index d25f8a8378..7bd616591f 100644
--- a/pretyping/inductiveops.mli
+++ b/pretyping/inductiveops.mli
@@ -122,11 +122,16 @@ val inductive_has_local_defs : inductive -> bool
val allowed_sorts : env -> inductive -> sorts_family list
+(** (Co)Inductive records with primitive projections do not have eta-conversion,
+ hence no dependent elimination. *)
+val has_dependent_elim : mutual_inductive_body -> bool
+
(** Primitive projections *)
val projection_nparams : projection -> int
val projection_nparams_env : env -> projection -> int
val type_of_projection_knowing_arg : env -> evar_map -> Projection.t ->
- constr -> types -> types
+ constr -> types -> types
+
(** Extract information from an inductive family *)
@@ -175,6 +180,14 @@ val type_case_branches_with_names :
(** Annotation for cases *)
val make_case_info : env -> inductive -> case_style -> case_info
+(** Make a case or substitute projections if the inductive type is a record
+ with primitive projections.
+ Fail with an error if the elimination is dependent while the
+ inductive type does not allow dependent elimination. *)
+val make_case_or_project :
+ env -> inductive_family -> case_info ->
+ (* pred *) constr -> (* term *) constr -> (* branches *) constr array -> constr
+
(*i Compatibility
val make_default_case_info : env -> case_style -> inductive -> case_info
i*)
diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml
index c8f61c66b8..187eba16b6 100644
--- a/pretyping/pretyping.ml
+++ b/pretyping/pretyping.ml
@@ -953,14 +953,17 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) env evdref (lvar : ltac_
| CastConv t | CastVM t | CastNative t ->
let k = (match k with CastVM _ -> VMcast | CastNative _ -> NATIVEcast | _ -> DEFAULTcast) in
let tj = pretype_type empty_valcon env evdref lvar t in
- let tval = nf_evar !evdref tj.utj_val in
- let cj = match k with
+ let tval = evd_comb1 (Evarsolve.refresh_universes
+ ~onlyalg:true ~status:Evd.univ_flexible (Some false) env)
+ evdref tj.utj_val in
+ let tval = nf_evar !evdref tval in
+ let cj, tval = match k with
| VMcast ->
let cj = pretype empty_tycon env evdref lvar c in
- let cty = nf_evar !evdref cj.uj_type and tval = nf_evar !evdref tj.utj_val in
+ let cty = nf_evar !evdref cj.uj_type and tval = nf_evar !evdref tval in
if not (occur_existential cty || occur_existential tval) then
let (evd,b) = Reductionops.vm_infer_conv env !evdref cty tval in
- if b then (evdref := evd; cj)
+ if b then (evdref := evd; cj, tval)
else
error_actual_type_loc loc env !evdref cj tval
(ConversionFailed (env,cty,tval))
@@ -968,16 +971,16 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) env evdref (lvar : ltac_
str "unresolved arguments remain.")
| NATIVEcast ->
let cj = pretype empty_tycon env evdref lvar c in
- let cty = nf_evar !evdref cj.uj_type and tval = nf_evar !evdref tj.utj_val in
+ let cty = nf_evar !evdref cj.uj_type and tval = nf_evar !evdref tval in
begin
let (evd,b) = Nativenorm.native_infer_conv env !evdref cty tval in
- if b then (evdref := evd; cj)
+ if b then (evdref := evd; cj, tval)
else
error_actual_type_loc loc env !evdref cj tval
(ConversionFailed (env,cty,tval))
end
| _ ->
- pretype (mk_tycon tval) env evdref lvar c
+ pretype (mk_tycon tval) env evdref lvar c, tval
in
let v = mkCast (cj.uj_val, k, tval) in
{ uj_val = v; uj_type = tval }
diff --git a/pretyping/recordops.ml b/pretyping/recordops.ml
index 682a883338..284af0cb15 100644
--- a/pretyping/recordops.ml
+++ b/pretyping/recordops.ml
@@ -195,7 +195,7 @@ let warn_projection_no_head_constant =
++ con_pp ++ str " of " ++ proji_sp_pp ++ strbrk ", ignoring it.")
(* Intended to always succeed *)
-let compute_canonical_projections (con,ind) =
+let compute_canonical_projections warn (con,ind) =
let env = Global.env () in
let ctx = Univ.instantiate_univ_context (Environ.constant_context env con) in
let u = Univ.UContext.instance ctx in
@@ -222,7 +222,7 @@ let compute_canonical_projections (con,ind) =
with Not_found ->
let con_pp = Nametab.pr_global_env Id.Set.empty (ConstRef con)
and proji_sp_pp = Nametab.pr_global_env Id.Set.empty (ConstRef proji_sp) in
- warn_projection_no_head_constant (t,con_pp,proji_sp_pp);
+ if warn then warn_projection_no_head_constant (t,con_pp,proji_sp_pp);
l
end
| _ -> l)
@@ -246,9 +246,8 @@ let warn_redundant_canonical_projection =
++ strbrk " by " ++ prj ++ strbrk " in "
++ new_can_s ++ strbrk ": redundant with " ++ old_can_s)
-let open_canonical_structure i (_,o) =
- if Int.equal i 1 then
- let lo = compute_canonical_projections o in
+let add_canonical_structure warn o =
+ let lo = compute_canonical_projections warn o in
List.iter (fun ((proj,(cs_pat,_ as pat)),s) ->
let l = try Refmap.find proj !object_table with Not_found -> [] in
let ocs = try Some (assoc_pat cs_pat l)
@@ -260,11 +259,14 @@ let open_canonical_structure i (_,o) =
and new_can_s = (Termops.print_constr s.o_DEF) in
let prj = (Nametab.pr_global_env Id.Set.empty proj)
and hd_val = (pr_cs_pattern cs_pat) in
- warn_redundant_canonical_projection (hd_val,prj,new_can_s,old_can_s))
+ if warn then warn_redundant_canonical_projection (hd_val,prj,new_can_s,old_can_s))
lo
-let cache_canonical_structure o =
- open_canonical_structure 1 o
+let open_canonical_structure i (_, o) =
+ if Int.equal i 1 then add_canonical_structure false o
+
+let cache_canonical_structure (_, o) =
+ add_canonical_structure true o
let subst_canonical_structure (subst,(cst,ind as obj)) =
(* invariant: cst is an evaluable reference. Thus we can take *)