Skip to content

Commit 66fd506

Browse files
authored
Merge pull request #125 from ppedrot/template-linear-levels
Work around the non-linearity of template parameter levels.
2 parents 7db5cb1 + 62d4e3e commit 66fd506

File tree

1 file changed

+119
-2
lines changed

1 file changed

+119
-2
lines changed

src/parametricity.ml

+119-2
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,95 @@ open Declarations
10521052

10531053
(* Translation of inductives. *)
10541054

1055+
let get_arity t =
1056+
let decls, s = Term.decompose_prod_decls t in
1057+
match Constr.kind s with
1058+
| Sort (Type s) ->
1059+
begin match Univ.Universe.level s with
1060+
| None -> None
1061+
| Some l -> Some (decls, l)
1062+
end
1063+
| _ -> None
1064+
1065+
(* Workaround to ensure that template universe levels are linear *)
1066+
let fix_template_params order evdr env temp b params =
1067+
let templ = List.rev temp.template_param_levels in
1068+
(* For all template levels generate fresh levels for all translated parameters *)
1069+
let rec freshen umap templ params = match templ with
1070+
| [] ->
1071+
let () = assert (List.is_empty params) in
1072+
umap, []
1073+
| None :: templ ->
1074+
let decls, params = List.chop (order + 1) params in
1075+
let umap, params = freshen umap templ params in
1076+
umap, decls @ params
1077+
| Some _ :: templ ->
1078+
let decls, params = List.chop (order + 1) params in
1079+
let umap, params = freshen umap templ params in
1080+
let rel, pdecls = match decls with
1081+
| rel :: decls -> rel, decls
1082+
| _ -> assert false
1083+
in
1084+
let u0 = match get_arity (Context.Rel.Declaration.get_type rel) with
1085+
| None -> assert false
1086+
| Some (_, l) -> l
1087+
in
1088+
let umap, (ur, repl) = match Univ.Level.Map.find_opt u0 umap with
1089+
| None ->
1090+
let ur = UnivGen.fresh_level () in
1091+
let r = List.init order (fun _ -> UnivGen.fresh_level ()) in
1092+
let r = (ur, r) in
1093+
Univ.Level.Map.add u0 r umap, r
1094+
| Some r -> umap, r
1095+
in
1096+
let map pdecl u = match pdecl with
1097+
| Context.Rel.Declaration.LocalDef _ -> assert false
1098+
| Context.Rel.Declaration.LocalAssum (na, pdecl) ->
1099+
match get_arity pdecl with
1100+
| Some (ctx, _) ->
1101+
let u = Univ.Universe.make u in
1102+
let pdecl = Term.it_mkProd_or_LetIn (Constr.mkType u) ctx in
1103+
Context.Rel.Declaration.LocalAssum (na, pdecl)
1104+
| None -> assert false
1105+
in
1106+
let rel = map rel ur in
1107+
let pdecls = List.map2 map pdecls repl in
1108+
umap, rel :: pdecls @ params
1109+
in
1110+
let umap, decls = freshen Univ.Level.Map.empty templ params in
1111+
(* Add corresponding declaration and constraints for each new level *)
1112+
let fold_univs u0 accu = match Univ.Level.Map.find_opt u0 umap with
1113+
| None -> assert false (* unbound template level *)
1114+
| Some (ur, repl) ->
1115+
let accu = Univ.Level.Set.add ur accu in
1116+
let fold accu u = Univ.Level.Set.add u accu in
1117+
List.fold_left fold accu repl
1118+
in
1119+
let fold_cstrs (u0, cst, v) accu =
1120+
(* We know that v cannot be template because of the unbounded-from-below property *)
1121+
let () = assert (not (Univ.Level.Map.mem v umap)) in
1122+
match Univ.Level.Map.find_opt u0 umap with
1123+
| None ->
1124+
(* not template, this is technically allowed but dubious *)
1125+
Univ.Constraints.add (u0, cst, v) accu
1126+
| Some (ur, repl) ->
1127+
let accu = Univ.Constraints.add (ur, cst, v) accu in
1128+
let fold accu u = Univ.Constraints.add (u, cst, v) accu in
1129+
List.fold_left fold accu repl
1130+
in
1131+
let fold_templ u0 (ur, repl) accu =
1132+
(* This is needed to typecheck inner template applications of the inductive.
1133+
FIXME: when new-template-poly lands this can probably be removed. *)
1134+
let accu = Univ.Constraints.add (ur, Le, u0) accu in
1135+
let fold accu u = Univ.Constraints.add (u, Le, u0) accu in
1136+
List.fold_left fold accu repl
1137+
in
1138+
let (univs, cstrs) = temp.template_context in
1139+
let univs = Univ.Level.Set.fold fold_univs univs Univ.Level.Set.empty in
1140+
let cstrs = Univ.Constraints.fold fold_cstrs cstrs Univ.Constraints.empty in
1141+
let cstrs = Univ.Level.Map.fold fold_templ umap cstrs in
1142+
umap, (univs, cstrs), decls
1143+
10551144
let rec translate_mind_body name order evdr env kn b inst =
10561145
(* XXX: What is going on here? This doesn't make sense after cumulativity *)
10571146
(* let env = push_context b.mind_universes env in *)
@@ -1082,6 +1171,12 @@ let rec translate_mind_body name order evdr env kn b inst =
10821171
let mind_entry_params_R =
10831172
translate_mind_param order evdr env (CVars.subst_instance_context inst b.mind_params_ctxt)
10841173
in
1174+
let template_univs, mind_entry_params_R = match b.mind_template with
1175+
| None -> None, mind_entry_params_R
1176+
| Some temp ->
1177+
let umap, univs, params = fix_template_params order evdr env temp b mind_entry_params_R in
1178+
Some (umap, univs), params
1179+
in
10851180
debug_string [`Inductive] "translatation of inductive ...";
10861181
let mind_entry_inds_R =
10871182
List.mapi
@@ -1091,14 +1186,36 @@ let rec translate_mind_body name order evdr env kn b inst =
10911186
debug_evar_map [`Inductive] "translate_mind, evd = \n" env !evdr;
10921187
let univs = match b.mind_universes with
10931188
| Monomorphic ->
1094-
begin match b.mind_template with
1189+
begin match template_univs with
10951190
| None -> Monomorphic_ind_entry
1096-
| Some t -> Template_ind_entry t.Declarations.template_context
1191+
| Some (_, ctx) -> Template_ind_entry ctx
10971192
end
10981193
| Polymorphic _ ->
10991194
let uctx, _ = (Evd.univ_entry ~poly:true !evdr) in
11001195
match uctx with Polymorphic_entry uctx -> Polymorphic_ind_entry uctx | _ -> assert false
11011196
in
1197+
let mind_entry_inds_R = match template_univs with
1198+
| None -> mind_entry_inds_R
1199+
| Some (umap, _) ->
1200+
let entry = match mind_entry_inds_R with
1201+
| [entry] -> entry
1202+
| _ -> assert false
1203+
in
1204+
let decls, sort = Term.decompose_prod_decls entry.mind_entry_arity in
1205+
let sort = match Constr.kind sort with
1206+
| Sort (Type u) ->
1207+
let u = Univ.Universe.repr u in
1208+
let map (u0, n) = match Univ.Level.Map.find_opt u0 umap with
1209+
| None -> [u0, n]
1210+
| Some (ur, repl) -> (ur, n) :: List.map (fun u -> u, n) repl
1211+
in
1212+
Constr.mkType (Univ.Universe.unrepr (List.map_append map u))
1213+
| _ -> sort
1214+
in
1215+
let arity = Term.it_mkProd_or_LetIn sort decls in
1216+
let entry = { entry with mind_entry_arity = arity } in
1217+
[entry]
1218+
in
11021219
let res = {
11031220
mind_entry_record = None;
11041221
mind_entry_finite = b.mind_finite;

0 commit comments

Comments
 (0)