123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885(************************************************************************)(* * The Coq Proof Assistant / The Coq 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.Declaration(* 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_differentindl=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(SameNamesTypest))inletcstr_names=matchelementscstr_nameswith|s->s|exception(Samec)->raise(InductiveError(SameNamesConstructorsc))inletl=Id.Set.interind_namescstr_namesinifnot(Id.Set.is_emptyl)thenraise(InductiveError(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))letdo_auto_prop_lowering=reftruelet()=Goptions.declare_bool_option{optstage=Interp;optdepr=None;optkey=["Automatic";"Proposition";"Inductives"];optread=(fun()->!do_auto_prop_lowering);optwrite=(funb->do_auto_prop_lowering:=b);}letwarn_auto_prop_lowering=CWarnings.create~name:"automatic-prop-lowering"~category:Deprecation.Version.v8_20Pp.(funna->strbrk"Automatically putting "++Id.printna++strbrk" in Prop"++spc()++strbrk"even though it was declared with Type."++fnl()++strbrk"Unset Automatic Proposition Inductives to prevent this"++spc()++strbrk"(it will become the default in a future version)."++fnl()++strbrk"If you instead put "++Id.printna++strbrk" explicitly in Prop,"++spc()++strbrk"set Dependent Proposition Eliminators around the declaration for full backwards compatibility.")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(!do_auto_prop_lowering||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 *)let()=ifexplicitthenwarn_auto_prop_loweringnain((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?locmsg(* 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
contributing to the inductive type's sort or is Some u_k if its level
is u_k and is contributing. *)lettemplate_polymorphic_univs~ctor_levelsuctxparamsctxtu=letunbounded_from_belowucstrs=letopenUnivinUniv.Constraints.for_all(fun(l,d,r)->matchdwith|Eq->not(Univ.Level.equallu)&¬(Univ.Level.equalru)|Lt|Le->not(Univ.Level.equalru))cstrsinletfold_paramsaccudecl=matchdeclwith|LocalAssum(_,p)->letc=Term.strip_prod_declspinbeginmatchConstr.kindcwith|Constr.Sort(Typeu)->beginmatchUniv.Universe.leveluwith|Somel->Univ.Level.Set.addlaccu|None->accuend|_->accuend|LocalDef_->accuinletparamslevels=List.fold_leftfold_paramsUniv.Level.Set.emptyparamsctxtinletcheck_levell=Univ.Level.Set.meml(Univ.ContextSet.levelsuctx)&&Univ.Level.Set.memlparamslevels&&(let()=assert(not@@Univ.Level.is_setl)intrue)&&unbounded_from_belowl(Univ.ContextSet.constraintsuctx)&¬(Univ.Level.Set.memlctor_levels)inletunivs=Univ.Universe.levelsuinletunivs=Univ.Level.Set.filter(funl->check_levell)univsinunivslettemplate_polymorphism_candidateuctxparamsentrytemplate_syntax=matchtemplate_syntaxwith|SyntaxNoTemplatePoly->Univ.Level.Set.empty|SyntaxAllowsTemplatePoly->let_,concl=Term.destArityentry.mind_entry_arityinmatchconclwith|Set|SProp|Prop->Univ.Level.Set.empty|Typeu->letctor_levels=letadd_levelsclevels=Univ.Level.Set.unionlevels(CVars.universes_of_constrc)inletparam_levels=List.fold_left(funlevelsd->matchdwith|LocalAssum_->levels|LocalDef(_,b,t)->add_levelsb(add_levelstlevels))Univ.Level.Set.emptyparamsinList.fold_left(funlevelsc->add_levelsclevels)param_levelsentry.mind_entry_lcinletunivs=template_polymorphic_univs~ctor_levelsuctxparamsuinunivs|QSort_->assertfalseletsplit_universe_contextsubset(univs,csts)=letsubfilter(l,_,r)=let()=assert(not@@Univ.Level.Set.memrsubset)inUniv.Level.Set.memlsubsetinletsubcst=Univ.Constraints.filtersubfiltercstsinletrem=Univ.Level.Set.diffunivssubsetinletremfilter(l,_,r)=not(Univ.Level.Set.memlsubset)&¬(Univ.Level.Set.memrsubset)inletremcst=Univ.Constraints.filterremfiltercstsin(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~template~udecl~variances~ctx_params~indnames~arities_explicit~arities~template_syntax~constructors~env_ar_params~cumulative~poly~private_ind~finite=(* 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~templateudecl(uparamsl,paramsl,indl)notations~cumulative~poly~private_indfinite=check_all_names_differentindl;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=notpolyinletsigma,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~template~sigma~ctx_params~udecl~variances~arities_explicit~arities~template_syntax~constructors~env_ar_params~poly~finite~cumulative~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(* remove BackInstanceWarning after deprecation phase *)|Vernacexpr.(NoInstance|BackInstanceWarning)->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:Loc.toptionlist;}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~templateudeclindl~cumulative~poly?typing_flags~private_ind~uniformfinite=letindlocs=List.map(fun((n,_,_,_),_)->n.CAst.loc)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_genenv~templateudeclindlwhere_notations~cumulative~poly~private_indfiniteinletopenMind_declin{mie;default_dep_elim;nuparams;univ_binders;implicits;uctx;where_notations;coercions;indlocs}letdo_mutual_inductive~templateudeclindl~cumulative~poly?typing_flags~private_ind~uniformfinite=letopenMind_declinletenv=Global.env()inlet{mie;default_dep_elim;univ_binders;implicits;uctx;where_notations;coercions;indlocs}=interp_mutual_inductive~env~templateudeclindl~cumulative~poly?typing_flags~private_ind~uniformfinitein(* 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_entryctx,univ_binders)|Polymorphic_ind_entryuctx->(UState.Polymorphic_entryuctx,UnivNames.empty_binders)in(* Declare the global universes *)Global.push_context_set~strict:trueuctx;(* 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_levelsletdo_auto_prop_lowering=do_auto_prop_loweringleterror_differing_params=error_differing_paramsend