1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096(************************************************************************)(* * 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) *)(************************************************************************)openCErrorsopenUtilopenNamesopenUnivtypeuniverses_entry=|Monomorphic_entryofUniv.ContextSet.t|Polymorphic_entryofUniv.UContext.tmoduleUNameMap=Names.Id.Maptypeuinfo={uname:Id.toption;uloc:Loc.toption;}typequality=QVarofSorts.QVar.t|QProp|QSProp|QTypeletsort_inconsistency?explaincstlr=letexplain=Option.map(funp->UGraph.Otherp)explaininraise(UGraph.UniverseInconsistency(cst,l,r,explain))letpr_quality=function|QVarv->Sorts.QVar.prv|QProp->Pp.str"Prop"|QSProp->Pp.str"SProp"|QType->Pp.str"Type"moduleQState:sigtypettypeelt=Sorts.QVar.tvalempty:tvalunion:fail:(t->quality->quality->t)->t->t->tvaladd:elt->t->tvalrepr:elt->t->qualityvalunify_quality:fail:(unit->t)->Conversion.conv_pb->quality->quality->t->tvalis_above_prop:elt->t->boolvalcollapse:t->tvalpr:t->Pp.tend=structmoduleQSet=Set.Make(Sorts.QVar)moduleQMap=Map.Make(Sorts.QVar)typet={qmap:qualityoptionQMap.t;(* TODO: use a persistent union-find structure *)above:QSet.t;(** Set of quality variables known to be either in Prop or Type.
If q ∈ above then it must map to None in qmap. *)}typeelt=Sorts.QVar.tletempty={qmap=QMap.empty;above=QSet.empty}letquality_eqab=matcha,bwith|QProp,QProp|QSProp,QSProp|QType,QType->true|QVarq1,QVarq2->Sorts.QVar.equalq1q2|(QVar_|QProp|QSProp|QType),_->falseletrecreprqm=matchQMap.findqm.qmapwith|None->QVarq|Some(QVarq)->reprqm|Some(QProp|QSProp|QTypeasq)->q|exceptionNot_found->(* let () = assert !Flags.in_debugger in *)(* FIXME *)QVarqletis_above_propqm=QSet.memqm.aboveletsetqqvm=letq=reprqminletq=matchqwithQVarq->q|QProp|QSProp|QType->assertfalseinletqv=matchqvwithQVarqv->reprqvm|(QSProp|QProp|QTypeasqv)->qvinmatchq,qvwith|q,QVarqv->ifSorts.QVar.equalqqvthenSomemelseletabove=ifQSet.memqm.abovethenQSet.addqv(QSet.removeqm.above)elsem.aboveinSome{qmap=QMap.addq(Some(QVarqv))m.qmap;above}|q,(QProp|QSProp|QTypeasqv)->ifqv==QSProp&&QSet.memqm.abovethenNoneelseSome{qmap=QMap.addq(Someqv)m.qmap;above=QSet.removeqm.above}letset_above_propqm=letq=reprqminletq=matchqwithQVarq->q|QProp|QSProp|QType->assertfalsein{qmap=m.qmap;above=QSet.addqm.above}letunify_quality~failcq1q2local=matchq1,q2with|QType,QType|QProp,QProp|QSProp,QSProp->local|QProp,QVarqwhenc==Conversion.CUMUL->set_above_propqlocal|QVarq,(QType|QProp|QSProp|QVar_asqv)|(QType|QProp|QSPropasqv),QVarq->beginmatchsetqqvlocalwith|Somelocal->local|None->fail()end|(QType,(QProp|QSProp))->fail()|(QProp,QType)->beginmatchcwith|CONV->fail()|CUMUL->localend|(QSProp,(QType|QProp))->fail()|(QProp,QSProp)->fail()letnf_qualitym=function|QSProp|QProp|QTypeasq->q|QVarq->reprqmletunion~fails1s2=letextra=ref[]inletqmap=QMap.union(funqkq1q2->matchq1,q2with|Someq,None|None,Someq->Some(Someq)|None,None->SomeNone|Someq1,Someq2->let()=ifnot(quality_eqq1q2)thenextra:=(q1,q2)::!extrainSome(Someq1))s1.qmaps2.qmapinletextra=!extrainletfilterq=matchQMap.findqqmapwith|None->true|Some_->false|exceptionNot_found->falseinletabove=QSet.filterfilter@@QSet.unions1.aboves2.aboveinlets={qmap;above}inList.fold_left(funs(q1,q2)->letq1=nf_qualitysq1andq2=nf_qualitysq2inunify_quality~fail:(fun()->failsq1q2)CONVq1q2s)sextraletaddqm={qmap=QMap.addqNonem.qmap;above=m.above}letcollapsem=letmapqv=matchvwith|None->SomeQType|Some_->vin{qmap=QMap.mapimapm.qmap;above=QSet.empty}letpr{qmap;above}=letopenPpinletprbodyu=function|None->ifQSet.memuabovethenstr" >= Prop"elsemt()|Someq->letq=pr_qualityqinstr" := "++qinh(prlist_with_sepfnl(fun(u,v)->Sorts.QVar.pru++prbodyuv)(QMap.bindingsqmap))endmoduleUPairSet=UnivMinim.UPairSettypeuniv_names=UnivNames.universe_binders*uinfoLevel.Map.t(* 2nd part used to check consistency on the fly. *)typet={names:univ_names;(** Printing/location information *)local:ContextSet.t;(** The local graph of universes (variables and constraints) *)seff_univs:Level.Set.t;(** Local universes used through private constants *)univ_variables:UnivSubst.universe_opt_subst;(** The local universes that are unification variables *)univ_algebraic:Level.Set.t;(** The subset of unification variables that can be instantiated with
algebraic universes as they appear in inferred types only. *)sort_variables:QState.t;(** Local quality variables. *)universes:UGraph.t;(** The current graph extended with the local constraints *)universes_lbound:UGraph.Bound.t;(** The lower bound on universes (e.g. Set or Prop) *)initial_universes:UGraph.t;(** The graph at the creation of the evar_map *)minim_extra:UnivMinim.extra;}letempty={names=UNameMap.empty,Level.Map.empty;local=ContextSet.empty;seff_univs=Level.Set.empty;univ_variables=Level.Map.empty;univ_algebraic=Level.Set.empty;sort_variables=QState.empty;universes=UGraph.initial_universes;universes_lbound=UGraph.Bound.Set;initial_universes=UGraph.initial_universes;minim_extra=UnivMinim.empty_extra;}letmake~lboundunivs={emptywithuniverses=univs;universes_lbound=lbound;initial_universes=univs}letis_emptyuctx=ContextSet.is_emptyuctx.local&&Level.Map.is_emptyuctx.univ_variablesletuname_unionst=ifs==tthenselseUNameMap.merge(funklr->matchl,rwith|Some_,_->l|_,_->r)stletunionuctxuctx'=ifuctx==uctx'thenuctxelseifis_emptyuctx'thenuctxelseletlocal=ContextSet.unionuctx.localuctx'.localinletseff=Level.Set.unionuctx.seff_univsuctx'.seff_univsinletnames=uname_union(fstuctx.names)(fstuctx'.names)inletnames_rev=Level.Map.lunion(snductx.names)(snductx'.names)inletnewus=Level.Set.diff(ContextSet.levelsuctx'.local)(ContextSet.levelsuctx.local)inletnewus=Level.Set.diffnewus(Level.Map.domainuctx.univ_variables)inletextra=UnivMinim.extra_unionuctx.minim_extrauctx'.minim_extrainletdeclarenewg=Level.Set.fold(funug->UGraph.add_universeu~lbound:uctx.universes_lbound~strict:falseg)newusginletfail_unionsq1q2=ifUGraph.type_in_typeuctx.universesthenselseCErrors.user_errPp.(str"Could not merge universe contexts: could not unify"++spc()++pr_qualityq1++strbrk" and "++pr_qualityq2++str".")in{names=(names,names_rev);local=local;seff_univs=seff;univ_variables=Level.Map.subst_unionuctx.univ_variablesuctx'.univ_variables;univ_algebraic=Level.Set.unionuctx.univ_algebraicuctx'.univ_algebraic;sort_variables=QState.union~fail:fail_unionuctx.sort_variablesuctx'.sort_variables;initial_universes=declarenewuctx.initial_universes;universes=(iflocal==uctx.localthenuctx.universeselseletcstrsr=ContextSet.constraintsuctx'.localinUGraph.merge_constraintscstrsr(declarenewuctx.universes));universes_lbound=uctx.universes_lbound;minim_extra=extra}letcontext_setuctx=uctx.localletconstraintsuctx=snductx.localletcompute_instance_bindersrbindersinst=letmaplvl=tryName(Option.get(Level.Map.findlvlrbinders).uname)withOption.IsNone|Not_found->AnonymousinArray.mapmap(Instance.to_arrayinst)letcontextuctx=let(_,rbinders)=uctx.namesinContextSet.to_context(compute_instance_bindersrbinders)uctx.localtypenamed_universes_entry=universes_entry*UnivNames.universe_bindersletuniv_entry~polyuctx=let(binders,_)=uctx.namesinletentry=ifpolythenPolymorphic_entry(contextuctx)elseMonomorphic_entry(context_setuctx)inentry,bindersletof_context_setlocal={emptywithlocal}typeuniverse_opt_subst=UnivSubst.universe_opt_substletsubstuctx=uctx.univ_variablesletugraphuctx=uctx.universesletinitial_graphuctx=uctx.initial_universesletalgebraicsuctx=uctx.univ_algebraicletadd_names?locsl(names,names_rev)=ifUNameMap.memsnamesthenuser_err?locPp.(str"Universe "++Names.Id.prints++str" already bound.");(UNameMap.addslnames,Level.Map.addl{uname=Somes;uloc=loc}names_rev)letadd_loclloc(names,names_rev)=matchlocwith|None->(names,names_rev)|Some_->(names,Level.Map.addl{uname=None;uloc=loc}names_rev)letof_names(ubind,revubind)=letrevubind=Level.Map.map(funid->{uname=Someid;uloc=None})revubindin{emptywithnames=(ubind,revubind)}letuniverse_of_nameuctxs=UNameMap.finds(fstuctx.names)letname_levelleveliductx=assert(not(Names.Id.Map.memid(fstuctx.names)));{uctxwithnames=(Names.Id.Map.addidlevel(fstuctx.names),Univ.Level.Map.addlevel{uname=Someid;uloc=None}(snductx.names))}letuniverse_bindersuctx=letnamed,_=uctx.namesinnamedletnf_qvaructxq=QState.reprquctx.sort_variablesletinstantiate_variablel(b:Universe.t)v=tryv:=Level.Map.setl(Someb)!vwithNot_found->assertfalseexceptionUniversesDifferlet{Goptions.get=drop_weak_constraints}=Goptions.declare_bool_option_and_ref~key:["Cumulativity";"Weak";"Constraints"]~value:false()letlevel_inconsistencycstlr=letmku=Sorts.sort_of_univ@@Universe.makeuinraise(UGraph.UniverseInconsistency(cst,mkl,mkr,None))letsubst_univs_sortnormalizeqnormalizes=matchswith|Sorts.Set|Sorts.Prop|Sorts.SProp->s|Sorts.Typeu->Sorts.sort_of_univ(UnivSubst.subst_univs_universenormalizeu)|Sorts.QSort(q,u)->matchqnormalizeqwith|QSProp->Sorts.sprop|QProp->Sorts.prop|QType->Sorts.sort_of_univ(UnivSubst.subst_univs_universenormalizeu)|QVarq->Sorts.qsortq(UnivSubst.subst_univs_universenormalizeu)letnf_sortuctxs=letnormalizeu=UnivSubst.normalize_univ_variable_opt_substuctx.univ_variablesuinletqnormalizeq=QState.reprquctx.sort_variablesinsubst_univs_sortnormalizeqnormalizesletnf_relevanceuctxr=matchrwith|Sorts.Relevant|Sorts.Irrelevant->r|Sorts.RelevanceVarq->matchnf_qvaructxqwith|QSProp->Sorts.Irrelevant|QProp|QType->Sorts.Relevant|QVarq'->ifQState.is_above_propq'uctx.sort_variablesthenRelevantelseifSorts.QVar.equalqq'thenrelseSorts.RelevanceVarq'letnf_universesuctxc=letlsubst=uctx.univ_variablesinletlevel_valuel=UnivSubst.level_subst_of(funl->UnivSubst.normalize_univ_variable_opt_substlsubstl)linletsort_values=nf_sortuctxsinletrel_valuer=nf_relevanceuctxrinUnivSubst.nf_evars_and_universes_opt_subst(fun_->None)level_valuesort_valuerel_valuectypesmall_universe=USet|UProp|USPropletis_uset=functionUSet->true|UProp|USProp->falsetypesort_classification=|USmallofsmall_universe(* Set, Prop or SProp *)|ULevelofLevel.t(* Var or Global *)|UMaxofUniverse.t*Level.Set.t(* Max of Set, Var, Global without increments *)|UAlgebraicofUniverse.t(* Arbitrary algebraic expression *)letclassifys=matchswith|Sorts.Prop->USmallUProp|Sorts.SProp->USmallUSProp|Sorts.Set->USmallUSet|Sorts.Typeu|Sorts.QSort(_,u)->ifUniverse.is_levelsuthenmatchUniverse.leveluwith|None->UMax(u,Universe.levelsu)|Someu->ULeveluelseUAlgebraicutypelocal={local_cst:Constraints.t;local_above_prop:Level.Set.t;local_weak:UPairSet.t;local_sorts:QState.t;}letadd_localcstlocal={localwithlocal_cst=Constraints.addcstlocal.local_cst}(* Constraint with algebraic on the left and a single level on the right *)letenforce_leq_upuvlocal={localwithlocal_cst=UnivSubst.enforce_lequ(Universe.makev)local.local_cst}letquality_of_sort=function|Sorts.Set|Sorts.Type_->QType|Sorts.Prop->QProp|Sorts.SProp->QSProp|Sorts.QSort(q,_)->QVarqletget_constraint=function|Conversion.CONV->Eq|Conversion.CUMUL->Leletunify_qualityunivscs1s2l=letfail()=ifUGraph.type_in_typeunivsthenl.local_sortselsesort_inconsistency(get_constraintc)s1s2in{lwithlocal_sorts=QState.unify_quality~failc(quality_of_sorts1)(quality_of_sorts2)l.local_sorts;}letprocess_universe_constraintsuctxcstrs=letopenUnivSubstinletopenUnivProbleminletunivs=uctx.universesinletvars=refuctx.univ_variablesinletnormalizeu=normalize_univ_variable_opt_subst!varsuinletnormalize_sortsortss=letqnormalizeq=QState.reprqsortsinsubst_univs_sortnormalizeqnormalizesinletnf_constraintsorts=function|ULub(u,v)->ULub(level_subst_ofnormalizeu,level_subst_ofnormalizev)|UWeak(u,v)->UWeak(level_subst_ofnormalizeu,level_subst_ofnormalizev)|UEq(u,v)->UEq(normalize_sortsortsu,normalize_sortsortsv)|ULe(u,v)->ULe(normalize_sortsortsu,normalize_sortsortsv)inletis_locall=Level.Map.meml!varsinletequalize_smalllslocal=letls=matchlwith|USProp->Sorts.sprop|UProp->Sorts.prop|USet->Sorts.setinifUGraph.check_eq_sortunivslssthenlocalelseifis_usetlthenmatchclassifyswith|USmall_->sort_inconsistencyEqSorts.sets|ULevelr->ifis_localrthenlet()=instantiate_variablerUniverse.type0varsinadd_local(Level.set,Eq,r)localelsesort_inconsistencyEqSorts.sets|UMax(u,_)|UAlgebraicu->ifuniv_level_memLevel.setuthenletinst=univ_level_remLevel.setuuinenforce_leq_upinstLevel.setlocalelsesort_inconsistencyEqlsselsesort_inconsistencyEqlssinletequalize_variablesfol'r'local=ifLevel.equall'r'thenlocalelselet()=ifis_locall'theninstantiate_variablel'(Universe.maker')varselseifis_localr'theninstantiate_variabler'(Universe.makel')varselseifnot(UnivProblem.check_eq_levelunivsl'r')then(* Two rigid/global levels, none of them being local,
one of them being Prop/Set, disallow *)ifLevel.is_setl'||Level.is_setr'thenlevel_inconsistencyEql'r'elseiffothenraiseUniversesDifferinadd_local(l',Eq,r')localinletequalize_algebraiclrulocal=letalg=Level.Set.memluctx.univ_algebraicinletinst=univ_level_remlruruinifalg&¬(Level.Set.meml(Universe.levelsinst))thenlet()=instantiate_variablelinstvarsinlocalelseifuniv_level_memlruthenenforce_leq_upinstllocalelsesort_inconsistencyEq(Sorts.sort_of_univ(Universe.makel))(Sorts.sort_of_univru)inletequalize_universeslrlocal=matchclassifyl,classifyrwith|USmalll',(USmall_|ULevel_|UMax_|UAlgebraic_)->equalize_smalll'rlocal|(ULevel_|UMax_|UAlgebraic_),USmallr'->equalize_smallr'llocal|ULevell',ULevelr'->equalize_variablesfalsel'r'local|ULevell',(UAlgebraicr|UMax(r,_))|(UAlgebraicr|UMax(r,_)),ULevell'->equalize_algebraicl'rlocal|(UAlgebraic_|UMax_),(UAlgebraic_|UMax_)->(* both are algebraic *)ifUGraph.check_eq_sortunivslrthenlocalelsesort_inconsistencyEqlrinletunify_universescstlocal=letcst=nf_constraintlocal.local_sortscstinifUnivProblem.is_trivialcstthenlocalelsematchcstwith|ULe(l,r)->letlocal=unify_qualityunivsCUMULlrlocalinletl=normalize_sortlocal.local_sortslinletr=normalize_sortlocal.local_sortsrinbeginmatchclassifyrwith|UAlgebraic_|UMax_->ifUGraph.check_leq_sortunivslrthenlocalelsesort_inconsistencyLelr~explain:(Pp.str"(cannot handle algebraic on the right)")|USmallr'->(* Invariant: there are no universes u <= Set in the graph. Except for
template levels, Set <= u anyways. Otherwise, for template
levels, any constraint u <= Set is turned into u := Set. *)ifUGraph.type_in_typeunivsthenlocalelsebeginmatchclassifylwith|UAlgebraic_->(* l contains a +1 and r=r' small so l <= r impossible *)sort_inconsistencyLelr|USmalll'->ifUGraph.check_leq_sortunivslrthenlocalelsesort_inconsistencyLelr|ULevell'->ifis_usetr'&&is_locall'then(* Unbounded universe constrained from above, we equalize it *)let()=instantiate_variablel'Universe.type0varsinadd_local(l',Eq,Level.set)localelsesort_inconsistencyLelr|UMax(_,levels)->ifis_usetr'thenletfoldl'local=letl=Sorts.sort_of_univ@@Universe.makel'inifLevel.is_setl'||is_locall'thenequalize_variablesfalsel'Level.setlocalelsesort_inconsistencyLelrinLevel.Set.foldfoldlevelslocalelsesort_inconsistencyLelrend|ULevelr'->(* We insert the constraint in the graph even if the graph
already contains it. Indeed, checking the existence of the
constraint is costly when the constraint does not already
exist directly as a single edge in the graph, but adding an
edge in the graph which is implied by others is cheap.
Hence, by doing this, we avoid a costly check here, and
make further checks of this constraint easier since it will
exist directly in the graph. *)matchclassifylwith|USmallUProp->{localwithlocal_above_prop=Level.Set.addr'local.local_above_prop}|USmallUSProp->ifUGraph.type_in_typeunivsthenlocalelsesort_inconsistencyLelr|USmallUSet->add_local(Level.set,Le,r')local|ULevell'->add_local(l',Le,r')local|UAlgebraicl->enforce_leq_uplr'local|UMax(_,l)->Univ.Level.Set.fold(funl'accu->add_local(l',Le,r')accu)llocalend|ULub(l,r)->equalize_variablestruelrlocal|UWeak(l,r)->ifnot(drop_weak_constraints())then{localwithlocal_weak=UPairSet.add(l,r)local.local_weak}elselocal|UEq(l,r)->letlocal=unify_qualityunivsCONVlrlocalinletl=normalize_sortlocal.local_sortslinletr=normalize_sortlocal.local_sortsrinequalize_universeslrlocalinletunify_universescstlocal=ifnot(UGraph.type_in_typeunivs)thenunify_universescstlocalelsetryunify_universescstlocalwithUGraph.UniverseInconsistency_->localinletlocal={local_cst=Constraints.empty;local_weak=uctx.minim_extra.UnivMinim.weak_constraints;local_above_prop=uctx.minim_extra.UnivMinim.above_prop;local_sorts=uctx.sort_variables;}inletlocal=UnivProblem.Set.foldunify_universescstrslocalinletextra={UnivMinim.above_prop=local.local_above_prop;UnivMinim.weak_constraints=local.local_weak}in!vars,extra,local.local_cst,local.local_sortsletadd_constraintsuctxcstrs=letunivs,old_cstrs=uctx.localinletcstrs'=Constraints.fold(fun(l,d,r)acc->letl=Universe.makelandr=Sorts.sort_of_univ@@Universe.makerinletcstr'=letopenUnivProbleminmatchdwith|Lt->ULe(Sorts.sort_of_univ@@Universe.superl,r)|Le->ULe(Sorts.sort_of_univl,r)|Eq->UEq(Sorts.sort_of_univl,r)inUnivProblem.Set.addcstr'acc)cstrsUnivProblem.Set.emptyinletvars,extra,cstrs',sorts=process_universe_constraintsuctxcstrs'in{uctxwithlocal=(univs,Constraints.unionold_cstrscstrs');univ_variables=vars;universes=UGraph.merge_constraintscstrs'uctx.universes;sort_variables=sorts;minim_extra=extra;}letadd_universe_constraintsuctxcstrs=letunivs,local=uctx.localinletvars,extra,local',sorts=process_universe_constraintsuctxcstrsin{uctxwithlocal=(univs,Constraints.unionlocallocal');univ_variables=vars;universes=UGraph.merge_constraintslocal'uctx.universes;sort_variables=sorts;minim_extra=extra;}letconstrain_variablesdiffuctx=letunivs,local=uctx.localinletunivs,vars,local=Level.Set.fold(funl(univs,vars,cstrs)->trymatchLevel.Map.findlvarswith|Someu->(Level.Set.addlunivs,Level.Map.removelvars,Constraints.add(l,Eq,Option.get(Universe.levelu))cstrs)|None->(univs,vars,cstrs)withNot_found|Option.IsNone->(univs,vars,cstrs))diff(univs,uctx.univ_variables,local)in{uctxwithlocal=(univs,local);univ_variables=vars}letid_of_leveluctxl=trySome(Option.get(Level.Map.findl(snductx.names)).uname)withNot_found|Option.IsNone->Noneletqualid_of_level_names(map,map_rev)l=trySome(Libnames.qualid_of_ident(Option.get(Level.Map.findlmap_rev).uname))withNot_found|Option.IsNone->UnivNames.qualid_of_levelmaplletqualid_of_leveluctxl=qualid_of_level_namesuctx.nameslletpr_uctx_level_namesnamesl=matchqualid_of_level_namesnameslwith|Someqid->Libnames.pr_qualidqid|None->Level.raw_prlletpr_uctx_leveluctxl=pr_uctx_level_namesuctx.namesltype('a,'b)gen_universe_decl={univdecl_instance:'a;(* Declared universes *)univdecl_extensible_instance:bool;(* Can new universes be added *)univdecl_constraints:'b;(* Declared constraints *)univdecl_extensible_constraints:bool(* Can new constraints be added *)}typeuniverse_decl=(Level.tlist,Constraints.t)gen_universe_declletdefault_univ_decl={univdecl_instance=[];univdecl_extensible_instance=true;univdecl_constraints=Constraints.empty;univdecl_extensible_constraints=true}letpr_error_unbound_universesleftnames=letopenPpinletn=Level.Set.cardinalleftinletprlevu=letinfo=Level.Map.find_optu(sndnames)inh(pr_uctx_level_namesnamesu++(matchinfowith|None|Some{uloc=None}->mt()|Some{uloc=Someloc}->spc()++str"("++Loc.prloc++str")"))in(hv0(str(CString.pluraln"Universe")++spc()++(prlist_with_sepspcprlev(Level.Set.elementsleft))++spc()++str(CString.conjugate_verb_to_ben)++str" unbound."))exceptionUnboundUnivsofLevel.Set.t*univ_names(* Deliberately using no location as the location of the univs
doesn't correspond to the failing command. *)leterror_unbound_universesleftuctx=raise(UnboundUnivs(left,uctx))let_=CErrors.register_handler(function|UnboundUnivs(left,uctx)->Some(pr_error_unbound_universesleftuctx)|_->None)letuniverse_context_inst~prefix~extensiblelevelsnames=letleft=List.fold_left(funaccl->Level.Set.removelacc)levelsprefixinifnotextensible&¬(Level.Set.is_emptyleft)thenerror_unbound_universesleftnameselseletleft=ContextSet.sort_levels(Array.of_list(Level.Set.elementsleft))inletinst=Array.append(Array.of_listprefix)leftinletinst=Instance.of_arrayinstininstletcheck_universe_context_set~prefixlevelsnames=letleft=List.fold_left(funleftl->Level.Set.removelleft)levelsprefixinifnot(Level.Set.is_emptyleft)thenerror_unbound_universesleftnamesletcheck_implicationuctxcstrscstrs'=letgr=initial_graphuctxinletgrext=UGraph.merge_constraintscstrsgrinletcstrs'=Constraints.filter(func->not(UGraph.check_constraintgrextc))cstrs'inifConstraints.is_emptycstrs'then()elseCErrors.user_errPp.(str"Universe constraints are not implied by the ones declared: "++pr_constraints(pr_uctx_leveluctx)cstrs')letcheck_mono_univ_decluctxdecl=letlevels,csts=uctx.localinlet()=letprefix=decl.univdecl_instanceinifnotdecl.univdecl_extensible_instancethencheck_universe_context_set~prefixlevelsuctx.namesinifdecl.univdecl_extensible_constraintsthenuctx.localelsebegincheck_implicationuctxdecl.univdecl_constraintscsts;levels,decl.univdecl_constraintsendletcheck_poly_univ_decluctxdecl=letprefix=decl.univdecl_instanceinletextensible=decl.univdecl_extensible_instanceinletlevels,csts=uctx.localinletinst=universe_context_inst~prefix~extensiblelevelsuctx.namesinletnas=compute_instance_binders(snductx.names)instinletcsts=ifdecl.univdecl_extensible_constraintsthencstselsebegincheck_implicationuctxdecl.univdecl_constraintscsts;decl.univdecl_constraintsendinletuctx=UContext.makenas(inst,csts)inuctxletcheck_univ_decl~polyuctxdecl=letentry=ifnotpolythenletctx=check_mono_univ_decluctxdeclinMonomorphic_entryctxelseletctx=check_poly_univ_decluctxdeclinPolymorphic_entryctxinentry,fstuctx.namesletis_boundllbound=matchlboundwith|UGraph.Bound.Prop->false|UGraph.Bound.Set->Level.is_setlletrestrict_universe_context~lbound(univs,csts)keep=letremoved=Level.Set.diffunivskeepinifLevel.Set.is_emptyremovedthenunivs,cstselseletallunivs=Constraints.fold(fun(u,_,v)all->Level.Set.addu(Level.Set.addvall))cstsunivsinletg=UGraph.initial_universesinletg=Level.Set.fold(funvg->ifLevel.is_setvthengelseUGraph.add_universev~lbound~strict:falseg)allunivsginletg=UGraph.merge_constraintscstsginletallkept=Level.Set.union(UGraph.domainUGraph.initial_universes)(Level.Set.diffallunivsremoved)inletcsts=UGraph.constraints_for~kept:allkeptginletcsts=Constraints.filter(fun(l,d,r)->not(is_boundllbound&&d==Le))cstsin(Level.Set.interunivskeep,csts)letrestrictuctxvars=letvars=Level.Set.unionvarsuctx.seff_univsinletvars=Names.Id.Map.fold(funnalvars->Level.Set.addlvars)(fstuctx.names)varsinletuctx'=restrict_universe_context~lbound:uctx.universes_lbounductx.localvarsin{uctxwithlocal=uctx'}letrestrict_even_bindersuctxvars=letvars=Level.Set.unionvarsuctx.seff_univsinletuctx'=restrict_universe_context~lbound:uctx.universes_lbounductx.localvarsin{uctxwithlocal=uctx'}typerigid=|UnivRigid|UnivFlexibleofbool(** Is substitution by an algebraic ok? *)letuniv_rigid=UnivRigidletuniv_flexible=UnivFlexiblefalseletuniv_flexible_alg=UnivFlexibletrue(** ~sideff indicates that it is ok to redeclare a universe.
~extend also merges the universe context in the local constraint structures
and not only in the graph. This depends if the
context we merge comes from a side effect that is already inlined
or defined separately. In the later case, there is no extension,
see [emit_side_effects] for example. *)letmerge?loc~sideffrigiductxuctx'=letlevels=ContextSet.levelsuctx'inletuctx=matchrigidwith|UnivRigid->uctx|UnivFlexibleb->letfolduaccu=ifLevel.Map.memuaccuthenaccuelseLevel.Map.adduNoneaccuinletuvars'=Level.Set.foldfoldlevelsuctx.univ_variablesinifbthen{uctxwithuniv_variables=uvars';univ_algebraic=Level.Set.unionuctx.univ_algebraiclevels}else{uctxwithuniv_variables=uvars'}inletlocal=ContextSet.appenductx'uctx.localinletdeclareg=Level.Set.fold(funug->tryUGraph.add_universe~lbound:uctx.universes_lbound~strict:falseugwithUGraph.AlreadyDeclaredwhensideff->g)levelsginletnames=letfolduaccu=letmodify_info=matchinfo.ulocwith|None->{infowithuloc=loc}|Some_->infointryLevel.Map.modifyumodifyaccuwithNot_found->Level.Map.addu{uname=None;uloc=loc}accuin(fstuctx.names,Level.Set.foldfoldlevels(snductx.names))inletinitial=declareuctx.initial_universesinletunivs=declareuctx.universesinletuniverses=UGraph.merge_constraints(ContextSet.constraintsuctx')univsin{uctxwithnames;local;universes;initial_universes=initial}(* Check bug_4363 and bug_6323 when changing this code *)letdemote_seff_univsunivsuctx=letseff=Level.Set.unionuctx.seff_univsunivsin{uctxwithseff_univs=seff}letdemote_global_univsenvuctx=letenv_ugraph=Environ.universesenvinletglobal_univs=UGraph.domainenv_ugraphinletglobal_constraints,_=UGraph.constraints_of_universesenv_ugraphinletpromoted_uctx=ContextSet.(of_setglobal_univs|>add_constraintsglobal_constraints)in{uctxwithlocal=ContextSet.diffuctx.localpromoted_uctx}letmerge_seffuctxuctx'=letlevels=ContextSet.levelsuctx'inletdeclareg=Level.Set.fold(funug->tryUGraph.add_universe~lbound:uctx.universes_lbound~strict:falseugwithUGraph.AlreadyDeclared->g)levelsginletinitial_universes=declareuctx.initial_universesinletunivs=declareuctx.universesinletuniverses=UGraph.merge_constraints(ContextSet.constraintsuctx')univsin{uctxwithuniverses;initial_universes}letemit_side_effectseffu=letuctx=Safe_typing.universes_of_privateeffinletu=demote_seff_univs(fstuctx)uinmerge_seffuuctxletupdate_sigma_univsuctxunivs=leteunivs={uctxwithinitial_universes=univs;universes=univs}inmerge_seffeunivseunivs.localletadd_universe?locnamestrictlbounductxu=letinitial_universes=UGraph.add_universe~lbound~strictuuctx.initial_universesinletuniverses=UGraph.add_universe~lbound~strictuuctx.universesinletlocal=ContextSet.add_universeuuctx.localinletnames=matchnamewith|Somen->add_names?locnuuctx.names|None->add_loculocuctx.namesin{uctxwithnames;local;initial_universes;universes}letnew_sort_variableuctx=letq=UnivGen.new_sort_global()inletsort_variables=QState.addquctx.sort_variablesin{uctxwithsort_variables},qletnew_univ_variable?locrigidnameuctx=letu=UnivGen.fresh_level()inletuctx=matchrigidwith|UnivRigid->uctx|UnivFlexibleallow_alg->letuniv_variables=Level.Map.adduNoneuctx.univ_variablesinifallow_algthenletuniv_algebraic=Level.Set.adduuctx.univ_algebraicin{uctxwithuniv_variables;univ_algebraic}else{uctxwithuniv_variables}inletuctx=add_universe?locnamefalseuctx.universes_lbounductxuinuctx,uletadd_global_univuctxu=add_universeNonetrueUGraph.Bound.Setuctxuletmake_with_initial_binders~lboundunivsus=letuctx=make~lboundunivsinList.fold_left(funuctx{CAst.loc;v=id}->fst(new_univ_variable?locuniv_rigid(Someid)uctx))uctxusletfrom_env?(binders=[])env=make_with_initial_binders~lbound:(Environ.universes_lboundenv)(Environ.universesenv)bindersletmake_flexible_variableuctx~algebraicu=let{local=cstrs;univ_variables=uvars;univ_algebraic=avars;universes=g;}=uctxinassert(tryLevel.Map.finduuvars==NonewithNot_found->true);matchUGraph.choose(funv->not(Level.equaluv)&&(algebraic||not(Level.Set.memvavars)))guwith|Somev->letuvars'=Level.Map.addu(Some(Universe.makev))uvarsin{uctxwithuniv_variables=uvars';}|None->letuvars'=Level.Map.adduNoneuvarsinletavars'=ifalgebraicthenletuu=Universe.makeuinletsubstu_not_algu'v=Option.cata(funvu->Universe.equaluuvu&¬(Level.Set.memu'avars))falsevinlethas_upper_constraint()=Constraints.exists(fun(l,d,r)->d==Lt&&Level.equallu)(ContextSet.constraintscstrs)inifnot(Level.Map.existssubstu_not_alguvars||has_upper_constraint())thenLevel.Set.adduavarselseavarselseavarsin{uctxwithuniv_variables=uvars';univ_algebraic=avars'}letmake_nonalgebraic_variableuctxu={uctxwithuniv_algebraic=Level.Set.removeuuctx.univ_algebraic}letmake_flexible_nonalgebraicuctx={uctxwithuniv_algebraic=Level.Set.empty}letis_sort_variableuctxs=matchswith(* FIXME: normalize here *)|Sorts.Typeu->(matchUniverse.leveluwith|Somelasx->ifLevel.Set.meml(ContextSet.levelsuctx.local)thenxelseNone|None->None)|Sorts.QSort(q,u)->letq=nf_qvaructxqin(matchq,Universe.leveluwith|QType,Somel->ifLevel.Set.meml(ContextSet.levelsuctx.local)thenSomelelseNone|(_,Some_|_,None)->None)|_->Noneletsubst_univs_context_with_defdefusubst(uctx,cst)=(Level.Set.diffuctxdef,UnivSubst.subst_univs_constraintsusubstcst)letrefresh_constraintsunivs(ctx,cstrs)=letcstrs',univs'=Constraints.fold(func(cstrs',univs)->(Constraints.addccstrs',UGraph.enforce_constraintcunivs))cstrs(Constraints.empty,univs)in((ctx,cstrs'),univs')letnormalize_variablesuctx=letnormalized_variables,def,subst=UnivSubst.normalize_univ_variablesuctx.univ_variablesinletmake_substsubstl=Level.Map.find_optlsubstinletuctx_local=subst_univs_context_with_defdef(make_substsubst)uctx.localinletuctx_local',univs=refresh_constraintsuctx.initial_universesuctx_localin{uctxwithlocal=uctx_local';univ_variables=normalized_variables;universes=univs}letabstract_undefined_variablesuctx=letvars'=Level.Map.fold(funuvacc->ifv==NonethenLevel.Set.removeuaccelseacc)uctx.univ_variablesuctx.univ_algebraicin{uctxwithlocal=ContextSet.empty;univ_algebraic=vars'}letfix_undefined_variablesuctx=letalgs',vars'=Level.Map.fold(funuv(algs,varsasacc)->ifv==Nonethen(Level.Set.removeualgs,Level.Map.removeuvars)elseacc)uctx.univ_variables(uctx.univ_algebraic,uctx.univ_variables)in{uctxwithuniv_variables=vars';univ_algebraic=algs'}letcollapse_sort_variablesuctx={uctxwithsort_variables=QState.collapseuctx.sort_variables}letminimizeuctx=letopenUnivMiniminletlbound=uctx.universes_lboundinlet((vars',algs'),us')=normalize_context_set~lbounductx.universesuctx.localuctx.univ_variablesuctx.univ_algebraicuctx.minim_extrainifContextSet.equalus'uctx.localthenuctxelseletus',universes=refresh_constraintsuctx.initial_universesus'in{names=uctx.names;local=us';seff_univs=uctx.seff_univs;(* not sure about this *)univ_variables=vars';univ_algebraic=algs';sort_variables=uctx.sort_variables;universes=universes;universes_lbound=lbound;initial_universes=uctx.initial_universes;minim_extra=UnivMinim.empty_extra;(* weak constraints are consumed *)}(* XXX print above_prop too *)letpr_weakprl{minim_extra={UnivMinim.weak_constraints=weak}}=letopenPpinprlist_with_sepfnl(fun(u,v)->prlu++str" ~ "++prlv)(UPairSet.elementsweak)letpr_universe_bodyprl=function|None->Pp.mt()|Somex->Pp.(str" := "++Univ.Universe.prprlx)letpr_universe_opt_substprl=Univ.Level.Map.prprl(pr_universe_bodyprl)letpr_sort_opt_substuctx=QState.pructx.sort_variablesmoduleInternal=structletrebootenvuctx=letuctx_global=from_envenvin{uctx_globalwithuniv_variables=uctx.univ_variables;sort_variables=uctx.sort_variables}end