aboutsummaryrefslogtreecommitdiffhomepage
path: root/kernel/subtyping.ml
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/subtyping.ml')
-rw-r--r--kernel/subtyping.ml78
1 files changed, 61 insertions, 17 deletions
diff --git a/kernel/subtyping.ml b/kernel/subtyping.ml
index f1402a3db..4f54220e7 100644
--- a/kernel/subtyping.ml
+++ b/kernel/subtyping.ml
@@ -79,8 +79,15 @@ let make_labmap mp list =
List.fold_right add_one list empty_labmap
-let check_conv_error error why cst f env a1 a2 =
- try Constraint.union cst (f env (Environ.universes env) a1 a2)
+let check_conv_error error why cst poly u f env a1 a2 =
+ try
+ let a1 = Vars.subst_instance_constr u a1 in
+ let a2 = Vars.subst_instance_constr u a2 in
+ let cst' = f env (Environ.universes env) a1 a2 in
+ if poly then
+ if Constraint.is_empty cst' then cst
+ else error (IncompatiblePolymorphism (env, a1, a2))
+ else Constraint.union cst cst'
with NotConvertible -> error why
(* for now we do not allow reorderings *)
@@ -89,15 +96,21 @@ let check_inductive cst env mp1 l info1 mp2 mib2 spec2 subst1 subst2 reso1 reso2
let kn1 = KerName.make2 mp1 l in
let kn2 = KerName.make2 mp2 l in
let error why = error_signature_mismatch l spec2 why in
- let check_conv why cst f = check_conv_error error why cst f in
+ let check_conv why cst poly u f = check_conv_error error why cst poly u f in
let mib1 =
match info1 with
| IndType ((_,0), mib) -> Declareops.subst_mind_body subst1 mib
| _ -> error (InductiveFieldExpected mib2)
in
+ let poly =
+ if not (mib1.mind_polymorphic == mib2.mind_polymorphic) then
+ error (PolymorphicStatusExpected mib2.mind_polymorphic)
+ else mib2.mind_polymorphic
+ in
let u =
- if mib1.mind_polymorphic then
- UContext.instance mib1.mind_universes
+ if poly then
+ Errors.error ("Checking of subtyping of polymorphic" ^
+ " inductive types not implemented")
else Instance.empty
in
let mib2 = Declareops.subst_mind_body subst2 mib2 in
@@ -134,7 +147,7 @@ let check_inductive cst env mp1 l info1 mp2 mib2 spec2 subst1 subst2 reso1 reso2
error (NotConvertibleInductiveField name)
| _ -> (s1, s2) in
check_conv (NotConvertibleInductiveField name)
- cst infer_conv_leq env (mkArity (ctx1,s1)) (mkArity (ctx2,s2))
+ cst poly u infer_conv_leq env (mkArity (ctx1,s1)) (mkArity (ctx2,s2))
in
let check_packet cst p1 p2 =
@@ -161,7 +174,8 @@ let check_inductive cst env mp1 l info1 mp2 mib2 spec2 subst1 subst2 reso1 reso2
let mind = mind_of_kn kn1 in
let check_cons_types i cst p1 p2 =
Array.fold_left3
- (fun cst id t1 t2 -> check_conv (NotConvertibleConstructorField id) cst infer_conv env t1 t2)
+ (fun cst id t1 t2 -> check_conv (NotConvertibleConstructorField id) cst
+ poly u infer_conv env t1 t2)
cst
p2.mind_consnames
(arities_of_specif (mind,u) (mib1,p1))
@@ -221,8 +235,8 @@ let check_inductive cst env mp1 l info1 mp2 mib2 spec2 subst1 subst2 reso1 reso2
let check_constant cst env mp1 l info1 cb2 spec2 subst1 subst2 =
let error why = error_signature_mismatch l spec2 why in
- let check_conv cst f = check_conv_error error cst f in
- let check_type cst env t1 t2 =
+ let check_conv cst poly u f = check_conv_error error cst poly u f in
+ let check_type poly u cst env t1 t2 =
let err = NotConvertibleTypeField (env, t1, t2) in
@@ -269,17 +283,47 @@ let check_constant cst env mp1 l info1 cb2 spec2 subst1 subst2 =
t1,t2
else
(t1,t2) in
- check_conv err cst infer_conv_leq env t1 t2
+ check_conv err cst poly u infer_conv_leq env t1 t2
in
match info1 with
| Constant cb1 ->
let () = assert (List.is_empty cb1.const_hyps && List.is_empty cb2.const_hyps) in
let cb1 = Declareops.subst_const_body subst1 cb1 in
let cb2 = Declareops.subst_const_body subst2 cb2 in
- (* Start by checking types*)
- let typ1 = Typeops.type_of_constant_type env cb1.const_type in
- let typ2 = Typeops.type_of_constant_type env cb2.const_type in
- let cst = check_type cst env typ1 typ2 in
+ (* Start by checking universes *)
+ let poly =
+ if not (cb1.const_polymorphic == cb2.const_polymorphic) then
+ error (PolymorphicStatusExpected cb2.const_polymorphic)
+ else cb2.const_polymorphic
+ in
+ let cst', env', u =
+ if poly then
+ let ctx1 = Univ.instantiate_univ_context cb1.const_universes in
+ let ctx2 = Univ.instantiate_univ_context cb2.const_universes in
+ let inst1, ctx1 = Univ.UContext.dest ctx1 in
+ let inst2, ctx2 = Univ.UContext.dest ctx2 in
+ if not (Univ.Instance.length inst1 == Univ.Instance.length inst2) then
+ error IncompatibleInstances
+ else
+ let cstrs = Univ.enforce_eq_instances inst1 inst2 cst in
+ let cstrs = Univ.Constraint.union cstrs ctx2 in
+ try
+ (* The environment with the expected universes plus equality
+ of the body instances with the expected instance *)
+ let env = Environ.add_constraints cstrs env in
+ (* Check that the given definition does not add any constraint over
+ the expected ones, so that it can be used in place of the original. *)
+ if Univ.check_constraints ctx1 (Environ.universes env) then
+ cstrs, env, inst2
+ else error (IncompatibleConstraints ctx1)
+ with Univ.UniverseInconsistency incon ->
+ error (IncompatibleUniverses incon)
+ else cst, env, Univ.Instance.empty
+ in
+ (* Now check types *)
+ let typ1 = Typeops.type_of_constant_type env' cb1.const_type in
+ let typ2 = Typeops.type_of_constant_type env' cb2.const_type in
+ let cst = check_type poly u cst env' typ1 typ2 in
(* Now we check the bodies:
- A transparent constant can only be implemented by a compatible
transparent constant.
@@ -296,7 +340,7 @@ let check_constant cst env mp1 l info1 cb2 spec2 subst1 subst2 =
Anyway [check_conv] will handle that afterwards. *)
let c1 = Mod_subst.force_constr lc1 in
let c2 = Mod_subst.force_constr lc2 in
- check_conv NotConvertibleBodyField cst infer_conv env c1 c2))
+ check_conv NotConvertibleBodyField cst poly u infer_conv env' c1 c2))
| IndType ((kn,i),mind1) ->
ignore (Errors.error (
"The kernel does not recognize yet that a parameter can be " ^
@@ -312,7 +356,7 @@ let check_constant cst env mp1 l info1 cb2 spec2 subst1 subst2 =
let typ2 = Typeops.type_of_constant_type env cb2.const_type in
let cst = Constraint.union cst (Constraint.union cst1 cst2) in
let error = NotConvertibleTypeField (env, arity1, typ2) in
- check_conv error cst infer_conv_leq env arity1 typ2
+ check_conv error cst false Univ.Instance.empty infer_conv_leq env arity1 typ2
| IndConstr (((kn,i),j) as cstr,mind1) ->
ignore (Errors.error (
"The kernel does not recognize yet that a parameter can be " ^
@@ -327,7 +371,7 @@ let check_constant cst env mp1 l info1 cb2 spec2 subst1 subst2 =
let ty2 = Typeops.type_of_constant_type env cb2.const_type in
let cst = Constraint.union cst (Constraint.union cst1 cst2) in
let error = NotConvertibleTypeField (env, ty1, ty2) in
- check_conv error cst infer_conv env ty1 ty2
+ check_conv error cst false Univ.Instance.empty infer_conv env ty1 ty2
let rec check_modules cst env msb1 msb2 subst1 subst2 =
let mty1 = module_type_of_module msb1 in