@@ -96,7 +96,9 @@ let check_univ_leq ?(is_real_arg=false) env u info =
9696 | HasRelevantArg -> info
9797 | NoRelevantArg -> match u with
9898 | Sorts. SProp -> info
99- | QSort (q ,_ ) -> if Sorts.Quality. equal (QVar q) (Sorts. quality info.ind_univ)
99+ | QSort (q ,_ ) ->
100+ if Environ.Internal. is_above_prop env q
101+ || Sorts.Quality. equal (QVar q) (Sorts. quality info.ind_univ)
100102 then { info with record_arg_info = HasRelevantArg }
101103 else info
102104 | Prop | Set | Type _ -> { info with record_arg_info = HasRelevantArg }
@@ -109,12 +111,15 @@ let check_univ_leq ?(is_real_arg=false) env u info =
109111 info
110112
111113 | Prop , SProp -> { info with ind_squashed = Some AlwaysSquashed }
112- | (SProp |Prop ), QSort _ -> add_squash (Sorts. quality u) info
114+ | (SProp |Prop ), QSort (q ,_ ) ->
115+ if Environ.Internal. is_above_prop env q then info
116+ else add_squash (Sorts. quality u) info
113117 | Prop , (Prop | Set | Type _ ) -> info
114118
115119 | Set , (SProp | Prop ) -> { info with ind_squashed = Some AlwaysSquashed }
116- | Set , QSort (_ , indu ) ->
117- if UGraph. check_leq (universes env) Universe. type0 indu
120+ | Set , QSort (q , indu ) ->
121+ if Environ.Internal. is_above_prop env q then info
122+ else if UGraph. check_leq (universes env) Universe. type0 indu (* XXX always true *)
118123 then add_squash qtype info
119124 else { info with missing = u :: info .missing }
120125 | Set , Set -> info
@@ -227,6 +232,11 @@ let check_constructors env_ar_par isrecord params lc (arity,indices,univ_info) =
227232 | _ -> check_univ_leq env_ar_par Sorts. set univ_info
228233 in
229234 let univ_info = Array. fold_left (check_constructor_univs env_ar_par) univ_info splayed_lc in
235+ let () = if univ_info.ind_template then match univ_info.ind_squashed with
236+ | None | Some AlwaysSquashed -> ()
237+ | Some (SometimesSquashed _ ) ->
238+ CErrors. user_err Pp. (str " Cannot handle sometimes squashed template polymorphic type." )
239+ in
230240 (* generalize the constructors over the parameters *)
231241 let lc = Array. map (fun c -> Term. it_mkProd_or_LetIn c params) lc in
232242 (arity, lc), (indices, splayed_lc), univ_info
@@ -304,7 +314,7 @@ let get_arity c =
304314 | _ -> None
305315
306316let get_template (mie :mutual_inductive_entry ) = match mie.mind_entry_universes with
307- | Monomorphic_ind_entry | Polymorphic_ind_entry _ -> None
317+ | Monomorphic_ind_entry | Polymorphic_ind_entry _ -> mie, None
308318| Template_ind_entry {univs =(template_univs , _ as template_context ); pseudo_sort_poly} ->
309319 let params = mie.mind_entry_params in
310320 let ind =
@@ -334,7 +344,7 @@ let get_template (mie:mutual_inductive_entry) = match mie.mind_entry_universes w
334344 (* * params *)
335345 (* for each non-letin param, find whether it binds a template univ *)
336346 let template_params =
337- CList. filter_map (fun param ->
347+ CList. map (fun param ->
338348 match param with
339349 | LocalDef (_ ,b ,t ) ->
340350 check_not_appearing b;
@@ -352,8 +362,8 @@ let get_template (mie:mutual_inductive_entry) = match mie.mind_entry_universes w
352362 in
353363 let bound_in_params =
354364 List. fold_left (fun bound_in_params -> function
355- | None -> bound_in_params
356- | Some l ->
365+ | Some None | None -> bound_in_params
366+ | Some (Some l ) ->
357367 if Level.Set. mem l bound_in_params then
358368 CErrors. user_err Pp. (str " Non-linear template level " ++ Level. raw_pr l)
359369 else Level.Set. add l bound_in_params)
@@ -371,15 +381,15 @@ let get_template (mie:mutual_inductive_entry) = match mie.mind_entry_universes w
371381 in
372382
373383 (* * arity *)
374- let () =
384+ let arity_for_pseudo_poly =
375385 (* don't use get_arity, we allow constant template poly (eg eq) *)
376386 let (decls, s) = Term. decompose_prod_decls ind.mind_entry_arity in
377387 let () = if not (isSort s) then
378388 CErrors. user_err Pp. (str " Template polymorphic inductive's type must be a syntactic arity." )
379389 in
380390 check_not_appearing_rel_ctx decls;
381391 match destSort s with
382- | SProp | Prop | Set -> ()
392+ | SProp | Prop | Set -> None
383393 | QSort _ -> assert false
384394 | Type u ->
385395 (* forbid template poly with an increment on a template univ in the conclusion
@@ -394,13 +404,49 @@ let get_template (mie:mutual_inductive_entry) = match mie.mind_entry_universes w
394404 if has_increment then
395405 CErrors. user_err
396406 Pp. (str " Template polymorphism with conclusion strictly larger than a bound universe not supported." )
407+ else Some (decls, u)
397408 in
398409
399410 (* * ctors *)
400411 let () = List. iter check_not_appearing ind.mind_entry_lc in
401412
402- Some {
403- template_param_arguments = List. rev_map Option. has_some template_params;
413+ (* for typechecking pseudo sort poly, replace Type@{u} with Type@{Var 0 | u}
414+ in the conclusion and for the bound univs which appear in the conclusion
415+ XXX it would be nicer to have the higher layers send us qvars instead *)
416+ let mie = match pseudo_sort_poly, arity_for_pseudo_poly with
417+ | TemplateUnivOnly , _ -> mie
418+ | TemplatePseudoSortPoly , None ->
419+ CErrors. user_err Pp. (str " Invalid pseudo sort poly template inductive." )
420+ | TemplatePseudoSortPoly , Some (indices , concl ) ->
421+ let concl_bound_univs = Level.Set. inter template_univs (Universe. levels concl) in
422+ let bound_qvar = Sorts.QVar. make_var 0 in
423+ let params = List. map (fun param ->
424+ match param with
425+ | LocalDef _ -> param (* letin *)
426+ | LocalAssum (na , t ) ->
427+ match get_arity t with
428+ | None -> param
429+ | Some (decls , l ) ->
430+ if Level.Set. mem l concl_bound_univs then
431+ let l = Universe. make l in
432+ LocalAssum (na, it_mkProd_or_LetIn (mkSort (Sorts. qsort bound_qvar l)) decls)
433+ else param)
434+ params
435+ in
436+ let arity = it_mkProd_or_LetIn (mkSort (Sorts. qsort bound_qvar concl)) indices in
437+ { mie with
438+ mind_entry_params = params;
439+ mind_entry_inds =
440+ [{ind with
441+ mind_entry_arity = arity;
442+ }];
443+ }
444+ in
445+
446+ let template_assums = CList. filter_map (fun x -> x) template_params in
447+
448+ mie, Some {
449+ template_param_arguments = List. rev_map Option. has_some template_assums;
404450 template_context;
405451 template_pseudo_sort_poly = pseudo_sort_poly;
406452 }
@@ -421,7 +467,7 @@ let abstract_packets env usubst ((arity,lc),(indices,splayed_lc),univ_info) =
421467
422468 let arity =
423469 if univ_info.ind_template then
424- TemplateArity { template_level = univ_info. ind_univ; }
470+ TemplateArity { template_level = ind_univ; }
425471 else
426472 RegularArity {mind_user_arity = arity; mind_sort = ind_univ}
427473 in
@@ -450,17 +496,15 @@ let typecheck_inductive env ~sec_univs (mie:mutual_inductive_entry) =
450496 assert (List. is_empty (Environ. rel_context env));
451497
452498 (* universes *)
453- let template = get_template mie in
499+ let mie, template = get_template mie in
454500
455501 let env_univs =
456502 match mie.mind_entry_universes with
457503 | Template_ind_entry {univs =ctx ; pseudo_sort_poly} ->
504+ let env = Environ. push_context_set ~strict: false ctx env in
458505 begin match pseudo_sort_poly with
459- | TemplatePseudoSortPoly ->
460- (* For that particular case, we typecheck the inductive in an environment
461- where the universes introduced by the definition are only [>= Prop] *)
462- Environ. push_floating_context_set ctx env
463- | TemplateUnivOnly -> Environ. push_context_set ~strict: false ctx env
506+ | TemplatePseudoSortPoly -> Environ.Internal. for_checking_pseudo_sort_poly env
507+ | TemplateUnivOnly -> env
464508 end
465509 | Monomorphic_ind_entry -> env
466510 | Polymorphic_ind_entry ctx -> push_context ctx env
@@ -532,8 +576,19 @@ let typecheck_inductive env ~sec_univs (mie:mutual_inductive_entry) =
532576
533577 (* Abstract universes *)
534578 let usubst, univs = match mie.mind_entry_universes with
535- | Monomorphic_ind_entry | Template_ind_entry _ ->
536- UVars. empty_sort_subst, Monomorphic
579+ | Monomorphic_ind_entry ->
580+ UVars. empty_sort_subst, Monomorphic
581+ | Template_ind_entry info -> begin match info.pseudo_sort_poly with
582+ | TemplateUnivOnly -> UVars. empty_sort_subst, Monomorphic
583+ | TemplatePseudoSortPoly ->
584+ (* replace Type@{Var 0 | u} back to Type@{u}
585+ XXX it would be nicer to keep the qvar in the declared structure *)
586+ let qsubst =
587+ Sorts.QVar.Map. singleton (Sorts.QVar. make_var 0 ) Sorts.Quality. (QConstant QType )
588+ in
589+ let usubst = Univ. empty_level_subst in
590+ (qsubst, usubst), Monomorphic
591+ end
537592 | Polymorphic_ind_entry uctx ->
538593 let (inst, auctx) = UVars. abstract_universes uctx in
539594 let inst = UVars. make_instance_subst inst in
0 commit comments