123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903(************************************************************************)(* * The Rocq Prover / The Rocq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)moduleCVars=VarsopenPpopenCErrorsopenSortsopenUtilopenContextopenEnvironopenNamesopenLibnamesopenConstrexpropenConstrexpr_opsopenConstrinternopenType_errorsopenPretypingopenContext.Rel.DeclarationopenEntriesopenEConstrmoduleRelDecl=Context.Rel.Declarationtypeflags={poly:bool;cumulative:bool;template:booloption;finite:Declarations.recursivity_kind;mode:Hints.hint_modelistoption;}(* 3b| Mutual inductive definitions *)letwarn_auto_template=CWarnings.create~name:"auto-template"~default:CWarnings.Disabled(funid->Pp.(strbrk"Automatically declaring "++Id.printid++strbrk" as template polymorphic. Use attributes or "++strbrk"disable Auto Template Polymorphism to avoid this warning."))letshould_auto_template=letopenGoptionsinletauto=reftrueinlet()=declare_bool_option{optstage=Summary.Stage.Interp;optdepr=None;optkey=["Auto";"Template";"Polymorphism"];optread=(fun()->!auto);optwrite=(funb->auto:=b);}infunidwould_auto->letb=!auto&&would_autoinifbthenwarn_auto_templateid;bletpush_typesenvidlrltl=List.fold_left3(funenvidrt->EConstr.push_rel(LocalAssum(make_annot(Nameid)r,t))env)envidlrltltypestructured_one_inductive_expr={ind_name:Id.t;ind_arity_explicit:bool;ind_arity:constr_expr;ind_lc:(Id.t*constr_expr)list}exceptionSameofId.tletcheck_all_names_differentenvindl=letrecelements=function|[]->Id.Set.empty|id::l->lets=elementslinifId.Set.memidsthenraise(Sameid)elseId.Set.addidsinletind_names=List.map(funind->ind.ind_name)indlinletcstr_names=List.map_append(funind->List.mapfstind.ind_lc)indlinletind_names=matchelementsind_nameswith|s->s|exception(Samet)->raise(InductiveError(env,SameNamesTypest))inletcstr_names=matchelementscstr_nameswith|s->s|exception(Samec)->raise(InductiveError(env,SameNamesConstructorsc))inletl=Id.Set.interind_namescstr_namesinifnot(Id.Set.is_emptyl)thenraise(InductiveError(env,SameNamesOverlap(Id.Set.elementsl)))(** Make the arity conclusion flexible to avoid generating an upper bound universe now,
only if the universe does not appear anywhere else.
This is really a hack to stay compatible with the semantics of template polymorphic
inductives which are recognized when a "Type" appears at the end of the conlusion in
the source syntax. *)letreccheck_type_conclusionind=letopenGlob_terminmatchDAst.getindwith|GSorts->(* not sure what this check is expected to be exactly *)beginmatchswith|(None,UAnonymous{rigid=UnivRigid})->(* should have been made flexible *)assertfalse|(None,UAnonymous{rigid=UnivFlexible_})->false|_->trueend|GProd(_,_,_,_,e)|GLetIn(_,_,_,_,e)->check_type_conclusione|_->falseletrecmake_anonymous_conclusion_flexibleind=letopenGlob_terminmatchDAst.getindwith|GSort(None,UAnonymous{rigid=UnivRigid})->Some(DAst.make?loc:ind.loc(GSort(None,UAnonymous{rigid=UnivFlexibletrue})))|GSort_->None|GProd(a,b,c,d,e)->beginmatchmake_anonymous_conclusion_flexibleewith|None->None|Somee->Some(DAst.make?loc:ind.loc(GProd(a,b,c,d,e)))end|GLetIn(a,b,c,d,e)->beginmatchmake_anonymous_conclusion_flexibleewith|None->None|Somee->Some(DAst.make?loc:ind.loc(GLetIn(a,b,c,d,e)))end|_->Nonetypesyntax_allows_template_poly=SyntaxAllowsTemplatePoly|SyntaxNoTemplatePolyletintern_ind_arityenvsigmaind=letc=intern_genIsTypeenvsigmaind.ind_arityinletimpls=Implicit_quantifiers.implicits_of_glob_constr~with_products:truecinletpseudo_poly,c=matchmake_anonymous_conclusion_flexiblecwith|None->check_type_conclusionc,c|Somec->true,cinlettemplate_syntax=ifpseudo_polythenSyntaxAllowsTemplatePolyelseSyntaxNoTemplatePolyin(constr_locind.ind_arity,c,impls,template_syntax)letpretype_ind_arity~unconstrained_sortsenvsigma(loc,c,impls,template_syntax)=letflags={Pretyping.all_no_fail_flagswithunconstrained_sorts}inletsigma,t=understand_tcc~flagsenvsigma~expected_type:IsTypecinmatchReductionops.sort_of_arityenvsigmatwith|exceptionReduction.NotArity->user_err?loc(str"Not an arity")|s->sigma,(t,Retyping.relevance_of_sorts,template_syntax,impls)(* ind_rel is the Rel for this inductive in the context without params.
n is how many arguments there are in the constructor. *)letmodel_conclusionenvsigmaind_relparamsnarity_indices=letmodel_head=EConstr.mkRel(n+Context.Rel.lengthparams+ind_rel)inletmodel_params=Context.Rel.instanceEConstr.mkRelnparamsinletsigma,model_indices=List.fold_right(fun(_,t)(sigma,subst)->lett=EConstr.Vars.substlsubst(EConstr.Vars.liftnn(List.lengthsubst+1)t)inletsigma,c=Evarutil.new_evarenvsigmatinsigma,c::subst)arity_indices(sigma,[])insigma,mkApp(mkApp(model_head,model_params),Array.of_list(List.revmodel_indices))letinterp_cstrsenv(sigma,ind_rel)implsparamsindarity=letcnames,ctyps=List.splitind.ind_lcinletarity_indices,cstr_sort=Reductionops.splay_arityenvsigmaarityin(* Interpret the constructor types *)letinterp_cstrsigmactyp=letflags=Pretyping.{all_no_fail_flagswithuse_typeclasses=UseTCForConv;solve_unification_constraints=false}inletsigma,(ctyp,cimpl)=interp_type_evars_impls~flagsenvsigma~implsctypinletctx,concl=Reductionops.whd_decompose_prod_declsenvsigmactypinletconcl_env=EConstr.push_rel_contextctxenvinletsigma_with_model_evars,model=model_conclusionconcl_envsigmaind_relparams(Context.Rel.lengthctx)arity_indicesin(* unify the expected with the provided conclusion *)letsigma=tryEvarconv.unifyconcl_envsigma_with_model_evarsConversion.CONVconclmodelwithEvarconv.UnableToUnify(sigma,e)->user_err(Himsg.explain_pretype_errorconcl_envsigma(Pretype_errors.CannotUnify(concl,model,(Somee))))insigma,(ctyp,cimpl)inletsigma,(ctyps,cimpls)=on_sndList.split@@List.fold_left_mapinterp_cstrsigmactypsin(sigma,predind_rel),(cnames,ctyps,cimpls)(***** Generate constraints from constructor arguments *****)letcompute_constructor_levelsenvevdsign=fst(List.fold_right(fund(lev,env)->matchdwith|LocalDef_->lev,EConstr.push_reldenv|LocalAssum_->lets=Retyping.get_sort_ofenvevd(RelDecl.get_typed)in(s::lev,EConstr.push_reldenv))sign([],env))letis_flexible_sortevds=matchESorts.kindevdswith|Set|Prop|SProp->false|Typeu|QSort(_,u)->matchUniv.Universe.leveluwith|Somel->Evd.is_flexible_levelevdl|None->falseletprop_lowering_candidatesevd~arities_explicitinds=letless_than_2=function[]|[_]->true|_::_::_->falsein(* handle automatic lowering to Prop
We repeatedly add information about which inductives should not be Prop
until no more progress can be made
*)letis_prop_candidate_arity(raw_arity,(_,s),indices,ctors)=less_than_2ctors&&EConstr.isArityevdraw_arity&&is_flexible_sortevds&¬(Evd.check_leqevdESorts.sets)inletcandidates=List.filter_map(fun(explicit,(_,(_,s),_,_asind))->if(notexplicit)&&is_prop_candidate_arityindthenSomeselseNone)(List.combinearities_explicitinds)inletin_candidatesscandidates=List.mem_f(ESorts.equalevd)scandidatesinletis_prop_candidate_sizecandidates(_,_,indices,ctors)=List.for_all(List.for_all(funs->matchESorts.kindevdswith|SProp|Prop->true|Set->false|Type_|QSort_->not(Evd.check_leqevdESorts.sets)&&in_candidatesscandidates))(Option.List.consindicesctors)inletrecspread_nonpropcandidates=let(changed,candidates)=List.fold_left(fun(changed,candidatesasacc)(raw_arity,(_,s),indices,ctorsasind)->ifis_prop_candidate_sizecandidatesindthenacc(* still a Prop candidate *)elseifin_candidatesscandidatesthen(true,List.remove(ESorts.equalevd)scandidates)elseacc)(false,candidates)indsinifchangedthenspread_nonpropcandidateselsecandidatesinletcandidates=spread_nonpropcandidatesincandidatesletinclude_constructor_argumentenvevd~poly~ctor_sort~inductive_sort=ifpolythen(* We ignore the quality when comparing the sorts: it has an impact
on squashing in the kernel but cannot cause a universe error. *)letuniv_of_sorts=matchESorts.kindevdswith|SProp|Prop->None|Set->SomeUniv.Universe.type0|Typeu|QSort(_,u)->Someuinmatchuniv_of_sortctor_sort,univ_of_sortinductive_sortwith|_,None->(* This function is only called when [s] is not impredicative *)assertfalse|None,Some_->evd|Someuctor,Someuind->letmku=ESorts.make(Sorts.sort_of_univu)inEvd.set_leq_sortenvevd(mkuctor)(mkuind)elsematchESorts.kindevdctor_sortwith|SProp|Prop->evd|Set|Type_|QSort_->Evd.set_leq_sortenvevdctor_sortinductive_sorttypedefault_dep_elim=DeclareInd.default_dep_elim=DefaultElim|PropButDepElimletinductive_levelsenvevd~poly~indnames~arities_explicitaritiesctors=letinds=List.map2(funxctors->letctx,s=Reductionops.dest_arityenvevdxinx,(ctx,s),List.map(compute_constructor_levelsenvevd)ctors)aritiesctorsin(* Inductives explicitly put in an impredicative sort can be
squashed, so there are no constraints to get from them. *)letis_impredicative_sortevds=is_impredicative_sortenv(ESorts.kindevds)in(* Inductives with >= 2 constructors are >= Set *)letless_than_2=function[]|[_]->true|_::_::_->falseinletevd=List.fold_left(funevd(raw_arity,(_,s),ctors)->ifless_than_2ctors||is_impredicative_sortevdsthenevdelse(* >=2 constructors is like having a bool argument *)include_constructor_argumentenvevd~poly~ctor_sort:ESorts.set~inductive_sort:s)evdindsin(* If indices_matter, the index telescope acts like an extra
constructor except for constructor count checks. *)letinds=List.map(fun(raw_arity,(ctx,_asarity),ctors)->letindices=ifindices_matterenvthenSome(compute_constructor_levelsenvevdctx)elseNonein(raw_arity,arity,indices,ctors))indsinletcandidates=prop_lowering_candidatesevd~arities_explicitindsin(* Do the lowering. We forget about the generated universe for the
lowered inductive and rely on universe restriction to get rid of
it.
NB: it would probably be less hacky to use the sort polymorphism system
ie lowering to Prop by setting a qvar equal to prop.
However this means we wouldn't lower "Inductive foo : Type := ."
as "Type" doesn't produce a qvar.
Perhaps someday we can stop lowering these explicit ": Type". *)letinds=List.map3(funnaexplicit(raw_arity,(ctx,s),indices,ctors)->ifList.mem_f(ESorts.equalevd)scandidatesthen(* NB: is_prop_candidate requires is_flexible_sort
so in this branch we know s <> Prop *)((PropButDepElim,mkArity(ctx,ESorts.prop)),ESorts.prop,indices,ctors)else((DefaultElim,raw_arity),s,indices,ctors))indnamesarities_explicitindsin(* Add constraints from constructor arguments and indices.
We must do this after Prop lowering as otherwise we risk unifying sorts
eg on "Box (A:Type)" we risk unifying the parameter sort and the output sort
then ESorts.equal would make us believe that the constructor argument is a lowering candidate.
*)letevd=List.fold_left(funevd(_,s,indices,ctors)->ifis_impredicative_sortevdsthenevdelseList.fold_left(List.fold_left(funevdctor_sort->include_constructor_argumentenvevd~poly~ctor_sort~inductive_sort:s))evd(Option.List.consindicesctors))evdindsinletarities=List.map(fun(arity,_,_,_)->arity)indsinevd,List.splitarities(** Template poly ***)letcheck_named{CAst.loc;v=na}=matchnawith|Name_->()|Anonymous->letmsg=str"Parameters must be named."inuser_err?locmsgletget_arityc=letdecls,c=Term.decompose_prod_declscinmatchConstr.kindcwith|Sort(Typeu)->beginmatchUniv.Universe.leveluwith|Somel->Some(decls,l)|None->Noneend|_->Noneletnon_template_levels~paramsentry=letctx,u=Term.destArityentry.mind_entry_arityinletadd_levelsclevels=Univ.Level.Set.unionlevels(CVars.universes_of_constrc)inletfold_paramslevels=function|LocalDef(_,b,t)->add_levelsb(add_levelstlevels)|LocalAssum(_,t)->matchget_aritytwith|None->add_levelstlevels|Some(decls,_)->add_levels(Term.it_mkProd_or_LetInConstr.mkPropdecls)levelsin(* Levels in LocalDef params, on the left of the context in LocalAssum params,
in the indices and in the constructor types are not allowed to be template.
(partly to guarantee Irrelevant variance, and partly to simplify universe substitution code) *)letlevels=List.fold_leftfold_paramsUniv.Level.Set.emptyparamsinletlevels=add_levels(Term.mkArity(ctx,Sorts.prop))levelsinletlevels=List.fold_left(funlevelsc->add_levelsclevels)levelsentry.mind_entry_lcin(* levels with nonzero increment in the conclusion may not be template
(until constraint checking can handle arbitrary +k, cf #19230) *)letconcl_univs=matchuwith|Sorts.Typeu->Univ.Universe.repru|QSort_->assertfalse|SProp|Prop|Set->[]inletlevels=List.fold_left(funlevels(u,n)->ifInt.equaln0thenlevelselseUniv.Level.Set.addulevels)levelsconcl_univsinlevelsletunbounded_from_belowucstrs=letopenUnivinUniv.Constraints.for_all(fun(l,d,r)->matchdwith|Eq|Lt->not(Univ.Level.equallu)&¬(Univ.Level.equalru)|Le->not(Univ.Level.equalru))cstrstypelinearity=Linear|NonLinear(* Returns the list [x_1, ..., x_n] of levels contributing to template
polymorphism. The elements x_k is None if the k-th parameter
(starting from the most recent and ignoring let-definitions) is not
template or is Some u_k if its level is u_k and is template. *)lettemplate_polymorphic_univsuctxparamsentry=letnon_template_levels=non_template_levels~paramsentryinletfold_paramsaccudecl=matchdeclwith|LocalAssum(_,p)->letc=Term.strip_prod_declspinbeginmatchget_aritycwith|Some(_,l)->Univ.Level.Map.updatel(functionNone->SomeLinear|Some_->SomeNonLinear)accu|None->accuend|LocalDef_->accuinletparamslevels=List.fold_leftfold_paramsUniv.Level.Map.emptyparamsinletparamslevels=Univ.Level.Map.filter(funu->function|NonLinear->false|Linear->assert(not@@Univ.Level.is_setu);Univ.Level.Set.memu(Univ.ContextSet.levelsuctx)&&unbounded_from_belowu(Univ.ContextSet.constraintsuctx)&¬(Univ.Level.Set.memunon_template_levels))paramslevelsinUniv.Level.Map.domainparamslevelslettemplate_polymorphism_candidateuctxparamsentrytemplate_syntax=matchtemplate_syntaxwith|SyntaxNoTemplatePoly->Univ.Level.Set.empty|SyntaxAllowsTemplatePoly->letunivs=template_polymorphic_univsuctxparamsentryinunivsletsplit_universe_contextsubset(univs,csts)=letrem=Univ.Level.Set.diffunivssubsetinletsubfilter(l,_,r)=let()=assert(not@@Univ.Level.Set.memrsubset)inUniv.Level.Set.memlsubsetinletsubcst,remcst=Univ.Constraints.partitionsubfiltercstsin(subset,subcst),(rem,remcst)letwarn_no_template_universe=CWarnings.create~name:"no-template-universe"(fun()->Pp.str"This inductive type has no template universes.")letcompute_template_inductive~user_template~ctx_params~univ_entryentrytemplate_syntax=matchuser_template,univ_entrywith|Somefalse,UState.Monomorphic_entryuctx->Monomorphic_ind_entry,uctx|Somefalse,UState.Polymorphic_entryuctx->Polymorphic_ind_entryuctx,Univ.ContextSet.empty|Sometrue,UState.Monomorphic_entryuctx->lettemplate_universes=template_polymorphism_candidateuctxctx_paramsentrytemplate_syntaxinlettemplate,global=split_universe_contexttemplate_universesuctxinlet()=ifUniv.Level.Set.is_empty(fsttemplate)thenwarn_no_template_universe()inTemplate_ind_entrytemplate,global|Sometrue,UState.Polymorphic_entry_->user_errPp.(strbrk"Template-polymorphism and universe polymorphism are not compatible.")|None,UState.Polymorphic_entryuctx->Polymorphic_ind_entryuctx,Univ.ContextSet.empty|None,UState.Monomorphic_entryuctx->lettemplate_candidate=template_polymorphism_candidateuctxctx_paramsentrytemplate_syntaxinlethas_template=not@@Univ.Level.Set.is_emptytemplate_candidateinlettemplate=should_auto_templateentry.mind_entry_typenamehas_templateiniftemplatethenlettemplate,global=split_universe_contexttemplate_candidateuctxinTemplate_ind_entrytemplate,globalelseMonomorphic_ind_entry,uctxletcheck_param=function|CLocalDef(na,_,_,_)->check_namedna|CLocalAssum(nas,_,Default_,_)->List.itercheck_namednas|CLocalAssum(nas,_,Generalized_,_)->()|CLocalPattern{CAst.loc}->Loc.raise?loc(Gramlib.Grammar.Error"pattern with quote not allowed here")letrestrict_inductive_universes~lboundsigmactx_paramsaritiesconstructors=letmerge_universes_of_constrc=Univ.Level.Set.union(snd(EConstr.universes_of_constrsigma(EConstr.of_constrc)))inletuvars=Univ.Level.Set.emptyinletuvars=Context.Rel.(fold_outside(Declaration.fold_constrmerge_universes_of_constr)ctx_params~init:uvars)inletuvars=List.fold_rightmerge_universes_of_constraritiesuvarsinletuvars=List.fold_right(fun(_,ctypes)->List.fold_rightmerge_universes_of_constrctypes)constructorsuvarsinEvd.restrict_universe_context~lboundsigmauvarsletcheck_trivial_variancesvariances=Array.iter(function|None|SomeUVars.Variance.Invariant->()|Some_->CErrors.user_errPp.(strbrk"Universe variance was specified but this inductive will not be cumulative."))variancesletvariance_of_entry~cumulative~variancesuctx=matchuctxwith|Monomorphic_ind_entry|Template_ind_entry_->check_trivial_variancesvariances;None|Polymorphic_ind_entryuctx->ifnotcumulativethenbegincheck_trivial_variancesvariances;Noneendelseletlvs=Array.lengthvariancesinlet_,lus=UVars.UContext.sizeuctxinassert(lvs<=lus);Some(Array.appendvariances(Array.make(lus-lvs)None))letinterp_mutual_inductive_constr~sigma~flags~udecl~variances~ctx_params~indnames~arities_explicit~arities~template_syntax~constructors~env_ar_params~private_ind=let{poly;cumulative;template;finite;}=flagsin(* Compute renewed arities *)letctor_args=List.map(fun(_,tys)->List.map(funty->letctx=fst(Reductionops.whd_decompose_prod_declsenv_ar_paramssigmaty)inctx)tys)constructorsinletsigma,(default_dep_elim,arities)=inductive_levelsenv_ar_paramssigma~poly~indnames~arities_explicitaritiesctor_argsinletlbound=ifpolythenUGraph.Bound.SetelseUGraph.Bound.Propinletsigma=Evd.minimize_universes~lboundsigmainletarities=List.mapEConstr.(to_constrsigma)aritiesinletconstructors=List.map(on_snd(List.map(EConstr.to_constrsigma)))constructorsinletctx_params=List.map(fund->EConstr.to_rel_declsigmad)ctx_paramsinletsigma=restrict_inductive_universes~lboundsigmactx_paramsaritiesconstructorsinletuniv_entry,binders=Evd.check_univ_decl~polysigmaudeclin(* Build the inductive entries *)letentries=List.map3(funindnamearity(cnames,ctypes)->{mind_entry_typename=indname;mind_entry_arity=arity;mind_entry_consnames=cnames;mind_entry_lc=ctypes})indnamesaritiesconstructorsinletuniv_entry,ctx=matchentries,template_syntaxwith|[entry],[template_syntax]->compute_template_inductive~user_template:template~ctx_params~univ_entryentrytemplate_syntax|_->let()=matchtemplatewith|Sometrue->user_errPp.(str"Template-polymorphism not allowed with mutual inductives.")|_->()inmatchuniv_entrywith|UState.Monomorphic_entryctx->Monomorphic_ind_entry,ctx|UState.Polymorphic_entryuctx->Polymorphic_ind_entryuctx,Univ.ContextSet.emptyinletvariance=variance_of_entry~cumulative~variancesuniv_entryin(* Build the mutual inductive entry *)letmind_ent={mind_entry_params=ctx_params;mind_entry_record=None;mind_entry_finite=finite;mind_entry_inds=entries;mind_entry_private=ifprivate_indthenSomefalseelseNone;mind_entry_universes=univ_entry;mind_entry_variance=variance;}indefault_dep_elim,mind_ent,binders,ctxletinterp_params~unconstrained_sortsenvudecluparamslparamsl=letsigma,udecl,variances=interp_cumul_univ_decl_optenvudeclinletsigma,(uimpls,((env_uparams,ctx_uparams),useruimpls))=interp_context_evars~program_mode:false~unconstrained_sortsenvsigmauparamslinletsigma,(impls,((env_params,ctx_params),userimpls))=interp_context_evars~program_mode:false~unconstrained_sorts~impl_env:uimplsenv_uparamssigmaparamslin(* Names of parameters as arguments of the inductive type (defs removed) *)sigma,env_params,(ctx_params,env_uparams,ctx_uparams,userimpls,useruimpls,impls,udecl,variances)(* When a hole remains for a param, pretend the param is uniform and
do the unification.
[env_ar_par] is [uparams; inds; params]
*)letmaybe_unify_params_inenv_ar_parsigma~ninds~nparams~binders:kc=letis_indsigmakc=matchEConstr.kindsigmacwith|Constr.Reln->(* env is [uparams; inds; params; k other things] *)n>k+nparams&&n<=k+nparams+ninds|_->falseinletrecaux(env,kasenvk)sigmac=matchEConstr.kindsigmacwith|Constr.App(h,args)whenis_indsigmakh->Array.fold_left_i(funisigmaarg->ifi>=nparams||not(EConstr.isEvarsigmaarg)thensigmaelsebegintryEvarconv.unify_delayenvsigmaarg(EConstr.mkRel(k+nparams-i))withEvarconv.UnableToUnify_->(* ignore errors, we will get a "Cannot infer ..." error instead *)sigmaend)sigmaargs|_->Termops.fold_constr_with_full_bindersenvsigma(fund(env,k)->EConstr.push_reldenv,k+1)auxenvksigmacinaux(env_ar_par,k)sigmacletinterp_mutual_inductive_genenv0~flagsudecl(uparamsl,paramsl,indl)notations~private_ind=check_all_names_differentenv0indl;List.itercheck_paramparamsl;ifnot(List.is_emptyuparamsl)&¬(List.is_emptynotations)thenuser_err(str"Inductives with uniform parameters may not have attached notations.");letindnames=List.map(funind->ind.ind_name)indlinletninds=List.lengthindlin(* In case of template polymorphism, we need to compute more constraints *)letunconstrained_sorts=notflags.polyinletsigma,env_params,(ctx_params,env_uparams,ctx_uparams,userimpls,useruimpls,impls,udecl,variances)=interp_params~unconstrained_sortsenv0udecluparamslparamslin(* Interpret the arities *)letarities=List.map(intern_ind_arityenv_paramssigma)indlinletsigma,arities=List.fold_left_map(pretype_ind_arity~unconstrained_sortsenv_params)sigmaaritiesinletarities,relevances,template_syntax,indimpls=List.split4aritiesinletlift_ctxnctx=lett=EConstr.it_mkProd_or_LetInEConstr.mkPropctxinlett=EConstr.Vars.liftntinletctx,_=EConstr.decompose_prod_declssigmatinctxinletctx_params_lifted,fullarities=lift_ctxnindsctx_params,CList.map_i(funic->EConstr.Vars.lifti(EConstr.it_mkProd_or_LetIncctx_params))0aritiesinletenv_ar=push_typesenv_uparamsindnamesrelevancesfullaritiesinletenv_ar_params=EConstr.push_rel_contextctx_params_liftedenv_arin(* Compute interpretation metadatas *)letindimpls=List.map(funimpls->userimpls@impls)indimplsinletimpls=compute_internalization_envenv_uparamssigma~implsInductiveindnamesfullaritiesindimplsinletntn_impls=compute_internalization_envenv_uparamssigmaInductiveindnamesfullaritiesindimplsinlet(sigma,_),constructors=Metasyntax.with_syntax_protection(fun()->(* Temporary declaration of notations and scopes *)List.iter(Metasyntax.set_notation_for_interpretationenv_paramsntn_impls)notations;(* Interpret the constructor types *)List.fold_left2_map(fun(sigma,ind_rel)indarity->interp_cstrsenv_ar_params(sigma,ind_rel)implsctx_params_liftedind(EConstr.Vars.liftnninds(Rel.lengthctx_params+1)arity))(sigma,ninds)indlarities)()inletnparams=Context.Rel.lengthctx_paramsinletsigma=List.fold_left(funsigma(_,ctyps,_)->List.fold_left(funsigmactyp->maybe_unify_params_inenv_ar_paramssigma~ninds~nparams~binders:0ctyp)sigmactyps)sigmaconstructorsin(* generalize over the uniform parameters *)letnuparams=Context.Rel.lengthctx_uparamsinletuargs=Context.Rel.instanceEConstr.mkRel0ctx_uparamsinletuparam_subst=List.initnindsEConstr.(funi->mkApp(mkRel(i+1+nuparams),uargs))@List.initnuparamsEConstr.(funi->mkRel(i+1))inletgeneralize_constructorc=EConstr.Vars.substnluparam_substnparamscinletcimpls=List.mappi3constructorsinletconstructors=List.map(fun(cnames,ctypes,cimpls)->(cnames,List.mapgeneralize_constructorctypes))constructorsinletctx_params=ctx_params@ctx_uparamsinletuserimpls=useruimpls@userimplsinletindimpls=List.map(funiimpl->useruimpls@iimpl)indimplsinletfullarities=List.map(func->EConstr.it_mkProd_or_LetIncctx_uparams)fullaritiesinletenv_ar=push_typesenv0indnamesrelevancesfullaritiesinletenv_ar_params=EConstr.push_rel_contextctx_paramsenv_arin(* Try further to solve evars, and instantiate them *)letsigma=solve_remaining_evarsall_and_fail_flagsenv_paramssigmainletimpls=List.map2(funindimplscimpls->indimpls,List.map(funimpls->userimpls@impls)cimpls)indimplscimplsinletarities_explicit=List.map(funar->ar.ind_arity_explicit)indlinletdefault_dep_elim,mie,binders,ctx=interp_mutual_inductive_constr~flags~sigma~ctx_params~udecl~variances~arities_explicit~arities~template_syntax~constructors~env_ar_params~private_ind~indnamesin(default_dep_elim,mie,binders,impls,ctx)(* Very syntactical equality *)leteq_local_bindersbl1bl2=List.equallocal_binder_eqbl1bl2leteq_params(up1,p1)(up2,p2)=eq_local_bindersup1up2&&Option.equaleq_local_bindersp1p2letextract_coercionsindl=letmkqid(_,({CAst.v=id},_))=qualid_of_identidinletiscoe(_,coe,inst)=matchinstwith|Vernacexpr.NoInstance->coe=Vernacexpr.AddCoercion|_->user_err(Pp.str"'::' not allowed in inductives.")inletextractlc=List.filter(fun(coe,_)->iscoecoe)lcinList.mapmkqid(List.flatten(List.map(fun(_,_,_,lc)->extractlc)indl))exceptionDifferingParamsofstring(* inductive or record *)*(Id.t*Vernacexpr.inductive_params_expr)*(Id.t*Vernacexpr.inductive_params_expr)letexplain_differing_paramskind(ind,p)(ind',p')=letpr_params=function|([],None)->str"no parameters"|(up,p)->letenv=Global.env()inletsigma=Evd.from_envenvinletpr_binders=Ppconstr.pr_bindersenvsigmainstr"parameters"++spc()++hov1(quote(pr_bindersup++pr_opt(funp->str"|"++spc()++pr_bindersp)p))inv0(str"Parameters should be syntactically the same for each "++strkind++str" type."++spc()++hov0(str"Type "++quote(Id.printind)++str" has "++pr_paramsp)++spc()++hov0(str"but type "++quote(Id.printind')++str" has "++pr_paramsp')++str".")let()=CErrors.register_handler(function|DifferingParams(kind,a,b)->Some(explain_differing_paramskindab)|_->None)leterror_differing_params~kind(ind,p)(ind',p')=Loc.raise?loc:ind'.CAst.loc(DifferingParams(kind,(ind.CAst.v,p),(ind'.CAst.v,p')))letextract_paramsindl=matchindlwith|[]->anomaly(Pp.str"empty list of inductive types.")|(ind,params,_,_)::rest->matchList.find_opt(fun(_,p',_,_)->not@@eq_paramsparamsp')restwith|None->params|Some(ind',p',_,_)->error_differing_params~kind:"inductive"(ind,params)(ind',p')letextract_inductiveindl=List.map(fun({CAst.v=indname},_,ar,lc)->{ind_name=indname;ind_arity_explicit=Option.has_somear;ind_arity=Option.default(CAst.make@@CSortConstrexpr_ops.expr_Type_sort)ar;ind_lc=List.map(fun(_,({CAst.v=id},t))->(id,t))lc})indlletextract_mutual_inductive_declaration_componentsindl=letindl,ntnl=List.splitindlinletparams=extract_paramsindlinletcoes=extract_coercionsindlinletindl=extract_inductiveindlin(params,indl),coes,List.flattenntnltypeuniform_inductive_flag=|UniformParameters|NonUniformParametersmoduleMind_decl=structtypet={mie:Entries.mutual_inductive_entry;default_dep_elim:default_dep_elimlist;nuparams:intoption;univ_binders:UnivNames.universe_binders;implicits:DeclareInd.one_inductive_implslist;uctx:Univ.ContextSet.t;where_notations:Metasyntax.notation_interpretation_decllist;coercions:Libnames.qualidlist;indlocs:DeclareInd.indlocs;}endletreccount_binder_expr=function|[]->0|CLocalAssum(l,_,_,_)::rest->List.lengthl+count_binder_exprrest|CLocalDef_::rest->1+count_binder_exprrest|CLocalPattern{CAst.loc}::_->Loc.raise?loc(Gramlib.Grammar.Error"pattern with quote not allowed here")letinterp_mutual_inductive~env~flags?typing_flagsudeclindl~private_ind~uniform=letindlocs=List.map(fun((n,_,_,constructors),_)->letconslocs=List.map(fun(_,(c,_))->c.CAst.loc)constructorsinn.CAst.loc,conslocs)indlinlet(params,indl),coercions,ntns=extract_mutual_inductive_declaration_componentsindlinletwhere_notations=List.mapMetasyntax.prepare_where_notationntnsin(* Interpret the types *)letindl,nuparams=matchparamswith|uparams,Someparams->(uparams,params,indl),Some(count_binder_exprparams)|params,None->matchuniformwith|UniformParameters->(params,[],indl),Some0|NonUniformParameters->([],params,indl),Noneinletenv=Environ.update_typing_flags?typing_flagsenvinletdefault_dep_elim,mie,univ_binders,implicits,uctx=interp_mutual_inductive_gen~flagsenvudeclindlwhere_notations~private_indinletopenMind_declin{mie;default_dep_elim;nuparams;univ_binders;implicits;uctx;where_notations;coercions;indlocs}letdo_mutual_inductive~flags?typing_flagsudeclindl~private_ind~uniform=letopenMind_declinletenv=Global.env()inlet{mie;default_dep_elim;univ_binders;implicits;uctx;where_notations;coercions;indlocs}=interp_mutual_inductive~flags~envudeclindl?typing_flags~private_ind~uniformin(* Slightly hackish global universe declaration due to template types. *)letbinders=matchmie.mind_entry_universeswith|Monomorphic_ind_entry->(UState.Monomorphic_entryuctx,univ_binders)|Template_ind_entryctx->(UState.Monomorphic_entry(Univ.ContextSet.unionuctxctx),univ_binders)|Polymorphic_ind_entryuctx->(UState.Polymorphic_entryuctx,UnivNames.empty_binders)in(* Declare the global universes *)Global.push_context_setuctx;(* Declare the mutual inductive block with its associated schemes *)ignore(DeclareInd.declare_mutual_inductive_with_eliminations~default_dep_elim?typing_flags~indlocsmiebindersimplicits);(* Declare the possible notations of inductive types *)List.iter(Metasyntax.add_notation_interpretation~local:false(Global.env()))where_notations;(* Declare the coercions *)List.iter(funqid->ComCoercion.try_add_new_coercion(Nametab.locateqid)~local:false~reversible:true)coercions(** Prepare a "match" template for a given inductive type.
For each branch of the match, we list the constructor name
followed by enough pattern variables.
[Not_found] is raised if the given string isn't the qualid of
a known inductive type. *)(*
HH notes in PR #679:
The Show Match could also be made more robust, for instance in the
presence of let in the branch of a constructor. A
decompose_prod_decls would probably suffice for that, but then, it
is a Context.Rel.Declaration.t which needs to be matched and not
just a pair (name,type).
Otherwise, this is OK. After all, the API on inductive types is not
so canonical in general, and in this simple case, working at the
low-level of mind_nf_lc seems reasonable (compared to working at the
higher-level of Inductiveops).
*)letmake_casesind=letopenDeclarationsinletmib,mip=Global.lookup_inductiveindinUtil.Array.fold_right_i(funi(ctx,_)l->letal=Util.List.skipn(List.lengthmib.mind_params_ctxt)(List.revctx)inletrecrenameavoid=function|[]->[]|RelDecl.LocalDef_::l->"_"::renameavoidl|RelDecl.LocalAssum(n,_)::l->letn'=Namegen.next_name_away_with_default(Id.to_stringNamegen.default_dependent_ident)n.Context.binder_nameavoidinId.to_stringn'::rename(Id.Set.addn'avoid)linletal'=renameId.Set.emptyalinletconsref=GlobRef.ConstructRef(ith_constructor_of_inductiveind(i+1))in(Libnames.string_of_qualid(Nametab.shortest_qualid_of_globalId.Set.emptyconsref)::al')::l)mip.mind_nf_lc[]moduleInternal=structletinductive_levels=inductive_levelsleterror_differing_params=error_differing_paramsend