123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742(************************************************************************)(* * 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) *)(************************************************************************)(** This module is about the low-level declaration of logical objects *)openPpopenUtilopenNamesopenSafe_typingmoduleNamedDecl=Context.Named.Declaration(* Hooks naturally belong here as they apply to both definitions and lemmas *)moduleHook=structmoduleS=structtypet={uctx:UState.t(** [ustate]: universe constraints obtained when the term was closed *);obls:(Names.Id.t*Constr.t)list(** [(n1,t1),...(nm,tm)]: association list between obligation
name and the corresponding defined term (might be a constant,
but also an arbitrary term in the Expand case of obligations) *);scope:Locality.definition_scope(** [locality]: Locality of the original declaration *);dref:Names.GlobRef.t(** [ref]: identifier of the original declaration *)}endtype'ag=(S.t->'a->'a)CEphemeron.keytypet=unitgletmake_ghook=CEphemeron.createhookletmake(hook:S.t->unit):t=CEphemeron.create(funx()->hookx)lethcallhookxs=CEphemeron.defaulthook(fun_x->x)xsletcall_g?hookxs=Option.cata(funhook->hcallhookxs)shookletcall?hookx=Option.iter(funhook->hcallhookx())hookendmoduleCInfo=structtype'constrt={name:Id.t(** Name of theorem *);typ:'constr(** Type of theorem *);args:Name.tlist(** Names to pre-introduce *);impargs:Impargs.manual_implicits(** Explicitily declared implicit arguments *)}letmake~name~typ?(args=[])?(impargs=[])()={name;typ;args;impargs}letto_constrsigmathm={thmwithtyp=EConstr.to_constrsigmathm.typ}letget_typ{typ;_}=typletget_name{name;_}=nameend(** Information for a declaration, interactive or not, includes
parameters shared by mutual constants *)moduleInfo=structtypet={poly:bool;inline:bool;kind:Decls.logical_kind;udecl:UState.universe_decl;scope:Locality.definition_scope;clearbody:bool(* always false for non Discharge scope *);hook:Hook.toption;typing_flags:Declarations.typing_flagsoption;user_warns:UserWarn.toption;ntns:Metasyntax.notation_interpretation_decllist}(** Note that [opaque] doesn't appear here as it is not known at the
start of the proof in the interactive case. *)letmake?(poly=false)?(inline=false)?(kind=Decls.(IsDefinitionDefinition))?(udecl=UState.default_univ_decl)?(scope=Locality.default_scope)?(clearbody=false)?hook?typing_flags?user_warns?(ntns=[])()={poly;inline;kind;udecl;scope;hook;typing_flags;clearbody;user_warns;ntns}end(** Declaration of constants and parameters *)type'approof_entry={proof_entry_body:'a;(* List of section variables *)proof_entry_secctx:Id.Set.toption;(* State id on which the completion of type checking is reported *)proof_entry_feedback:Stateid.toption;proof_entry_type:Constr.typesoption;proof_entry_universes:UState.named_universes_entry;proof_entry_opaque:bool;proof_entry_inline_code:bool;}typeproof_entry=Evd.side_effectsOpaques.const_entry_bodypproof_entrytypeparameter_entry={parameter_entry_secctx:Id.Set.toption;parameter_entry_type:Constr.types;parameter_entry_universes:UState.named_universes_entry;parameter_entry_inline_code:Entries.inline;}typeprimitive_entry={prim_entry_type:(Constr.types*UState.named_universes_entry)option;prim_entry_content:CPrimitives.op_or_type;}typesymbol_entry={symb_entry_type:Constr.types;symb_entry_unfold_fix:bool;symb_entry_universes:UState.named_universes_entry;}letdefault_univ_entry=UState.Monomorphic_entryUniv.ContextSet.emptyletdefault_named_univ_entry=default_univ_entry,UnivNames.empty_binders(** [univsbody] are universe-constraints attached to the body-only,
used in vio-delayed opaque constants and private poly universes *)letdefinition_entry_core?(opaque=false)?using?(inline=false)?types?(univs=default_named_univ_entry)?(eff=Evd.empty_side_effects)?(univsbody=Univ.ContextSet.empty)body={proof_entry_body=Future.from_val((body,univsbody),eff);proof_entry_secctx=using;proof_entry_type=types;proof_entry_universes=univs;proof_entry_opaque=opaque;proof_entry_feedback=None;proof_entry_inline_code=inline}letdefinition_entry=definition_entry_core?eff:None?univsbody:Noneletparameter_entry?inline?(univs=default_named_univ_entry)typ={parameter_entry_secctx=None;parameter_entry_type=typ;parameter_entry_universes=univs;parameter_entry_inline_code=inline;}letprimitive_entry?typesc={prim_entry_type=types;prim_entry_content=c;}letsymbol_entry?(univs=default_named_univ_entry)~unfold_fixsymb_entry_type={symb_entry_universes=univs;symb_entry_unfold_fix=unfold_fix;symb_entry_type;}typeconstant_entry=|DefinitionEntryofproof_entry|ParameterEntryofparameter_entry|PrimitiveEntryofprimitive_entry|SymbolEntryofsymbol_entryletlocal_csts=Summary.ref~name:"local-csts"Cset_env.emptyletis_local_constantc=Cset_env.memc!local_cststypeconstant_obj={cst_kind:Decls.logical_kind;cst_locl:Locality.import_status;cst_warn:UserWarn.toption;}letload_constanti((sp,kn),obj)=ifNametab.exists_ccispthenraise(DeclareUniv.AlreadyDeclared(None,Libnames.basenamesp));letcon=Global.constant_of_delta_knkninNametab.push?user_warns:obj.cst_warn(Nametab.Untili)sp(GlobRef.ConstRefcon);Dumpglob.add_constant_kindconobj.cst_kind;beginmatchobj.cst_loclwith|Locality.ImportNeedQualified->local_csts:=Cset_env.addcon!local_csts|Locality.ImportDefaultBehavior->()end(* Opening means making the name without its module qualification available *)letopen_constanti((sp,kn),obj)=(* Never open a local definition *)matchobj.cst_loclwith|Locality.ImportNeedQualified->()|Locality.ImportDefaultBehavior->letcon=Global.constant_of_delta_knkninNametab.push(Nametab.Exactlyi)sp(GlobRef.ConstRefcon)letexists_nameid=Decls.variable_existsid||Global.exists_objlabel(Label.of_idid)letcheck_existsid=ifexists_nameidthenraise(DeclareUniv.AlreadyDeclared(None,id))letcache_constant((sp,kn),obj)=letkn=Global.constant_of_delta_knkninNametab.push?user_warns:obj.cst_warn(Nametab.Until1)sp(GlobRef.ConstRefkn);Dumpglob.add_constant_kindknobj.cst_kindletdischarge_constantobj=Someobjletclassify_constantcst=Libobject.Substitutelet(objConstant:(Id.t*constant_obj)Libobject.Dyn.tag)=letopenLibobjectindeclare_named_object_full{(default_object"CONSTANT")withcache_function=cache_constant;load_function=load_constant;open_function=simple_openopen_constant;classify_function=classify_constant;subst_function=ident_subst_function;discharge_function=discharge_constant}letinConstantv=Libobject.Dyn.Easy.injvobjConstantletupdate_tablesc=Impargs.declare_constant_implicitsc;Notation.declare_ref_arguments_scope(GlobRef.ConstRefc)letregister_constantknkind?user_warnslocal=letid=Label.to_id(Constant.labelkn)inleto=inConstant(id,{cst_kind=kind;cst_locl=local;cst_warn=user_warns})inlet()=Lib.add_leafoinupdate_tablesknletregister_side_effect(c,body,role)=(* Register the body in the opaque table *)let()=matchbodywith|None->()|Someopaque->Opaques.declare_private_opaqueopaqueinlet()=register_constantcDecls.(IsProofTheorem)Locality.ImportDefaultBehaviorinmatchrolewith|None->()|Some(Evd.Schema(ind,kind))->DeclareScheme.declare_schemekind(ind,c)letget_rolesexporteff=letmap(c,body)=letrole=trySome(Cmap.findceff.Evd.seff_roles)withNot_found->Nonein(c,body,role)inList.mapmapexportletexport_side_effectseff=letexport=Global.export_private_constantseff.Evd.seff_privateinletexport=get_rolesexporteffinList.iterregister_side_effectexportletrecord_auxenvs_tys_bo=letopenEnvironinletin_ty=keep_hypsenvs_tyinletv=String.concat" "(CList.map_filter(fundecl->letid=NamedDecl.get_iddeclinifList.exists(NamedDecl.get_id%>Id.equalid)in_tythenNoneelseSome(Id.to_stringid))(keep_hypsenvs_bo))inAux_file.record_in_aux"context_used"vletpure_definition_entry?(opaque=false)?(inline=false)?types?(univs=default_named_univ_entry)body={proof_entry_body=((body,Univ.ContextSet.empty),());proof_entry_secctx=None;proof_entry_type=types;proof_entry_universes=univs;proof_entry_opaque=opaque;proof_entry_feedback=None;proof_entry_inline_code=inline}letdelayed_definition_entry~opaque?feedback_id~using~univs?typesbody={proof_entry_body=body;proof_entry_secctx=using;proof_entry_type=types;proof_entry_universes=univs;proof_entry_opaque=opaque;proof_entry_feedback=feedback_id;proof_entry_inline_code=false}letextract_monomorphic=function|UState.Monomorphic_entryctx->Entries.Monomorphic_entry,ctx|UState.Polymorphic_entryuctx->Entries.Polymorphic_entryuctx,Univ.ContextSet.emptyletcast_proof_entrye=let(body,ctx),()=e.proof_entry_bodyinletuniv_entry=ifUniv.ContextSet.is_emptyctxthenfst(e.proof_entry_universes)elsematchfst(e.proof_entry_universes)with|UState.Monomorphic_entryctx'->(* This can actually happen, try compiling EqdepFacts for instance *)UState.Monomorphic_entry(Univ.ContextSet.unionctx'ctx)|UState.Polymorphic_entry_->CErrors.anomalyPp.(str"Local universes in non-opaque polymorphic definition.");inletuniv_entry,ctx=extract_monomorphicuniv_entryin{Entries.const_entry_body=body;const_entry_secctx=e.proof_entry_secctx;const_entry_type=e.proof_entry_type;const_entry_universes=univ_entry;const_entry_inline_code=e.proof_entry_inline_code;},ctxtype('a,'b)effect_entry=|EffectEntry:(private_constantsOpaques.const_entry_body,unit)effect_entry|PureEntry:(unitEntries.proof_output,Constr.constr)effect_entryletcast_opaque_proof_entry(typeab)(entry:(a,b)effect_entry)(e:approof_entry):bEntries.opaque_entry*_=lettyp=matche.proof_entry_typewith|None->assertfalse|Sometyp->typinletsecctx=matche.proof_entry_secctxwith|None->letopenEnvironinletenv=Global.env()inlethyp_typ,hyp_def=ifList.is_empty(Environ.named_contextenv)thenId.Set.empty,Id.Set.emptyelseletids_typ=global_vars_setenvtypinletpf,env=matchentrywith|PureEntry->let(pf,_),()=e.proof_entry_bodyinpf,env|EffectEntry->let(pf,_),eff=Future.forcee.proof_entry_bodyinletenv=Safe_typing.push_private_constantsenveffinpf,envinletvars=global_vars_setenvpfinids_typ,varsinlet()=ifAux_file.recording()thenrecord_auxenvhyp_typhyp_definEnviron.really_neededenv(Id.Set.unionhyp_typhyp_def)|Somehyps->hypsinlet(body,(univ_entry,ctx):b*_)=matchentrywith|PureEntry->let(body,uctx),()=e.proof_entry_bodyinletuniv_entry=matchfst(e.proof_entry_universes)with|UState.Monomorphic_entryuctx'->Entries.Monomorphic_entry,(Univ.ContextSet.unionuctxuctx')|UState.Polymorphic_entryuctx'->assert(Univ.ContextSet.is_emptyuctx);Entries.Polymorphic_entryuctx',Univ.ContextSet.emptyinbody,univ_entry|EffectEntry->(),extract_monomorphic(fst(e.proof_entry_universes))in{Entries.opaque_entry_body=body;opaque_entry_secctx=secctx;opaque_entry_type=typ;opaque_entry_universes=univ_entry;},ctxletfeedback_axiom()=Feedback.(feedbackAddedAxiom)letis_unsafe_typing_flagsflags=letflags=Option.default(Global.typing_flags())flagsinletopenDeclarationsinnot(flags.check_universes&&flags.check_guarded&&flags.check_positive)letmake_ubindersuctx(univs,ubindersasu)=matchunivswith|UState.Polymorphic_entry_->u|UState.Monomorphic_entry_->(UState.Monomorphic_entryuctx,ubinders)letdeclare_constant_core~name~typing_flagscd=(* Logically define the constant and its subproofs, no libobject tampering *)letdecl,unsafe,ubinders,delayed=matchcdwith|DefinitionEntryde->(* We deal with side effects *)ifnotde.proof_entry_opaquethenletbody,eff=Future.forcede.proof_entry_bodyin(* This globally defines the side-effects in the environment
and registers their libobjects. *)let()=export_side_effectseffinletde={dewithproof_entry_body=body,()}inlete,ctx=cast_proof_entrydeinletubinders=make_ubindersctxde.proof_entry_universesin(* We register the global universes after exporting side-effects, since
the latter depend on the former. *)let()=Global.push_context_set~strict:truectxinletcd=Entries.DefinitionEntryeinConstantEntrycd,false,ubinders,Noneelseletmap(body,eff)=body,eff.Evd.seff_privateinletbody=Future.chainde.proof_entry_bodymapinletfeedback_id=de.proof_entry_feedbackinletde={dewithproof_entry_body=body}inletcd,ctx=cast_opaque_proof_entryEffectEntrydeinletubinders=make_ubindersctxde.proof_entry_universesinlet()=Global.push_context_set~strict:truectxinOpaqueEntrycd,false,ubinders,Some(body,feedback_id)|ParameterEntrye->letuniv_entry,ctx=extract_monomorphic(fste.parameter_entry_universes)inletubinders=make_ubindersctxe.parameter_entry_universesinlet()=Global.push_context_set~strict:truectxinlete={Entries.parameter_entry_secctx=e.parameter_entry_secctx;Entries.parameter_entry_type=e.parameter_entry_type;Entries.parameter_entry_universes=univ_entry;Entries.parameter_entry_inline_code=e.parameter_entry_inline_code;}inConstantEntry(Entries.ParameterEntrye),not(Lib.is_modtype_strict()),ubinders,None|PrimitiveEntrye->lettyp,univ_entry,ctx=matche.prim_entry_typewith|None->None,(UState.Monomorphic_entryUniv.ContextSet.empty,UnivNames.empty_binders),Univ.ContextSet.empty|Some(typ,entry_univs)->letuniv_entry,ctx=extract_monomorphic(fstentry_univs)inSome(typ,univ_entry),entry_univs,ctxinlet()=Global.push_context_set~strict:truectxinlete={Entries.prim_entry_type=typ;Entries.prim_entry_content=e.prim_entry_content;}inletubinders=make_ubindersctxuniv_entryinConstantEntry(Entries.PrimitiveEntrye),false,ubinders,None|SymbolEntry{symb_entry_type=typ;symb_entry_unfold_fix=un_fix;symb_entry_universes=entry_univs}->letuniv_entry,ctx=extract_monomorphic(fstentry_univs)inlet()=Global.push_context_set~strict:truectxinlete={Entries.symb_entry_type=typ;Entries.symb_entry_unfold_fix=un_fix;Entries.symb_entry_universes=univ_entry;}inletubinders=make_ubindersctxentry_univsinConstantEntry(Entries.SymbolEntrye),false,ubinders,Noneinletkn=Global.add_constant?typing_flagsnamedeclinlet()=DeclareUniv.declare_univ_binders(GlobRef.ConstRefkn)ubindersinifunsafe||is_unsafe_typing_flagstyping_flagsthenfeedback_axiom();kn,delayedletdeclare_constant?(local=Locality.ImportDefaultBehavior)~name~kind~typing_flags?user_warnscd=let()=check_existsnameinletkn,delayed=declare_constant_core~typing_flags~namecdin(* Register the libobjects attached to the constants *)let()=matchdelayedwith|None->()|Some(body,feedback_id)->letopenDeclarationsinmatch(Global.lookup_constantkn).const_bodywith|OpaqueDefo->let(_,_,_,i)=Opaqueproof.reproinOpaques.declare_defined_opaque?feedback_idibody|Def_|Undef_|Primitive_|Symbol_->assertfalseinlet()=register_constantknkindlocal?user_warnsinknletdeclare_private_constant?role?(local=Locality.ImportDefaultBehavior)~name~kindde=letde,ctx=ifnotde.proof_entry_opaquethenletde,ctx=cast_proof_entrydeinDefinitionEffde,ctxelseletde,ctx=cast_opaque_proof_entryPureEntrydeinOpaqueEffde,ctxinletkn,eff=Global.add_private_constantnamectxdeinlet()=register_constantknkindlocalinletseff_roles=matchrolewith|None->Cmap.empty|Somer->Cmap.singletonknrinleteff={Evd.seff_private=eff;Evd.seff_roles;}inkn,effletinline_private_constants~uctxenvce=letbody,eff=ce.proof_entry_bodyinletcb,ctx=Safe_typing.inline_private_constantsenv(body,eff.Evd.seff_private)inletuctx=UState.merge~sideff:trueEvd.univ_rigiductxctxincb,uctx(** Declaration of section variables and local definitions *)typevariable_declaration=|SectionLocalDefof{clearbody:bool;entry:proof_entry;}|SectionLocalAssumof{typ:Constr.types;impl:Glob_term.binding_kind;univs:UState.named_universes_entry;}(* This object is only for things which iterate over objects to find
variables (only Prettyp.print_context AFAICT) *)letobjVariable:Id.tLibobject.Dyn.tag=letopenLibobjectindeclare_object_full{(default_object"VARIABLE")withclassify_function=(fun_->Dispose)}letinVariablev=Libobject.Dyn.Easy.injvobjVariableletdeclare_variable~name~kind~typing_flagsd=(* Variables are distinguished by only short names *)ifDecls.variable_existsnamethenraise(DeclareUniv.AlreadyDeclared(None,name));letimpl,opaque=matchdwith(* Fails if not well-typed *)|SectionLocalAssum{typ;impl;univs}->let()=matchfstunivswith|UState.Monomorphic_entryuctx->Global.push_context_set~strict:trueuctx|UState.Polymorphic_entryuctx->Global.push_section_contextuctxinlet()=Global.push_named_assum(name,typ)inimpl,true|SectionLocalDef{clearbody;entry=de}->(* The body should already have been forced upstream because it is a
section-local definition, but it's not enforced by typing *)let((body,body_uctx),eff)=Future.forcede.proof_entry_bodyinlet()=export_side_effectseffin(* We must declare the universe constraints before type-checking the
term. *)let()=matchfstde.proof_entry_universeswith|UState.Monomorphic_entryuctx->Global.push_context_set~strict:true(Univ.ContextSet.unionuctxbody_uctx)|UState.Polymorphic_entryuctx->Global.push_section_contextuctx;letmk_anon_namesu=letqs,us=UVars.Instance.to_arrayuinArray.make(Array.lengthqs)Anonymous,Array.make(Array.lengthus)AnonymousinGlobal.push_section_context(UVars.UContext.of_context_setmk_anon_namesSorts.QVar.Set.emptybody_uctx)inletopaque=de.proof_entry_opaqueinletse=ifopaquethenletcname=Id.of_string(Id.to_stringname^"_subproof")inletcname=Namegen.next_global_ident_awaycnameId.Set.emptyinletpoly=matchfstde.proof_entry_universeswith|Monomorphic_entry_->false|Polymorphic_entry_->trueinletde={proof_entry_body=Future.from_val((body,Univ.ContextSet.empty),Evd.empty_side_effects);proof_entry_secctx=None;(* de.proof_entry_secctx is NOT respected *)proof_entry_feedback=de.proof_entry_feedback;proof_entry_type=de.proof_entry_type;proof_entry_universes=UState.univ_entry~polyUState.empty;proof_entry_opaque=true;proof_entry_inline_code=de.proof_entry_inline_code;}inletkn=declare_constant~name:cname~local:ImportNeedQualified~kind:(IsProofLemma)~typing_flags(DefinitionEntryde)in{Entries.secdef_body=Constr.mkConstU(kn,UVars.Instance.empty);secdef_type=None;}else{Entries.secdef_body=body;secdef_type=de.proof_entry_type;}inlet()=Global.push_named_def(name,se)in(* opaque implies clearbody, so we don't see useless "foo := foo_subproof" in the context *)Glob_term.Explicit,opaque||clearbodyinNametab.push(Nametab.Until1)(Libnames.make_pathDirPath.emptyname)(GlobRef.VarRefname);Decls.(add_variable_dataname{opaque;kind});Lib.add_leaf(inVariablename);Impargs.declare_var_implicits~implname;Notation.declare_ref_arguments_scope(GlobRef.VarRefname)(* Declaration messages *)letpr_ranki=pr_nth(i+1)letfixpoint_messageindexesl=Flags.if_verboseFeedback.msg_info(matchlwith|[]->CErrors.anomaly(Pp.str"no recursive definition.")|[id]->Id.printid++str" is recursively defined"++(matchindexeswith|Some[|i|]->str" (guarded on "++pr_ranki++str" argument)"|_->mt())|l->hov0(prlist_with_seppr_commaId.printl++spc()++str"are recursively defined"++matchindexeswith|Somea->spc()++str"(guarded respectively on "++prvect_with_seppr_commapr_ranka++str" arguments)"|None->mt()))letcofixpoint_messagel=Flags.if_verboseFeedback.msg_info(matchlwith|[]->CErrors.anomaly(Pp.str"No corecursive definition.")|[id]->Id.printid++str" is corecursively defined"|l->hov0(prlist_with_seppr_commaId.printl++spc()++str"are corecursively defined"))letrecursive_messageisfixindexesl=(ifisfixthenfixpoint_messageindexeselsecofixpoint_message)lletdefinition_messageid=Flags.if_verboseFeedback.msg_info(Id.printid++str" is defined")letassumption_messageid=(* Changing "assumed" to "declared", "assuming" referring more to
the type of the object than to the name of the object (see
discussion on coqdev: "Chapter 4 of the Reference Manual", 8/10/2015) *)Flags.if_verboseFeedback.msg_info(Id.printid++str" is declared")moduleInternal=structletpmap_entry_body~fentry={entrywithproof_entry_body=fentry.proof_entry_body}letmap_entry_body~fentry={entrywithproof_entry_body=Future.chainentry.proof_entry_bodyf}letmap_entry_type~fentry={entrywithproof_entry_type=fentry.proof_entry_type}letset_opacity~opaqueentry={entrywithproof_entry_opaque=opaque}letrecshrinkctxsignctaccu=letopenConstrinletopenVarsinmatchctx,signwith|[],[]->(c,t,accu)|p::ctx,decl::sign->ifnoccurn1c&&noccurn1tthenletc=subst1mkPropcinlett=subst1mkProptinshrinkctxsignctaccuelseletc=Term.mkLambda_or_LetInpcinlett=Term.mkProd_or_LetInptinletaccu=ifContext.Rel.Declaration.is_local_assumpthenmkVar(NamedDecl.get_iddecl)::accuelseaccuinshrinkctxsignctaccu|_->assertfalseletshrink_entrysignconst=lettyp=matchconst.proof_entry_typewith|None->assertfalse|Somet->tinlet((body,uctx),eff)=const.proof_entry_bodyinlet(ctx,body,typ)=Term.decompose_lambda_prod_n_decls(List.lengthsign)bodytypinlet(body,typ,args)=shrinkctxsignbodytyp[]in{constwithproof_entry_body=((body,uctx),eff);proof_entry_type=Sometyp},argsmoduleConstant=structtypet=constant_objlettag=objConstantletkindobj=obj.cst_kindendletobjVariable=objVariableletexport_side_effects=export_side_effectsendletdeclare_definition_scheme~internal~univs~role~name?locc=letkind=Decls.(IsDefinitionScheme)inletentry=pure_definition_entry~univscinletkn,eff=declare_private_constant~role~kind~nameentryinDumpglob.dump_definition(CAst.make?loc(Constant.labelkn|>Label.to_id))false"scheme";let()=ifinternalthen()elsedefinition_messagenameinkn,eff(* Locality stuff *)letdeclare_entry_core~name?(scope=Locality.default_scope)?(clearbody=false)~kind~typing_flags~user_warns?hook~obls~impargs~uctxentry=letshould_suggest=entry.proof_entry_opaque&¬(List.is_empty(Global.named_context()))&&Option.is_emptyentry.proof_entry_secctxinletdref=matchscopewith|Locality.Discharge->let()=declare_variable~typing_flags~name~kind(SectionLocalDef{clearbody;entry})inifshould_suggestthenProof_using.suggest_variable(Global.env())name;Names.GlobRef.VarRefname|Locality.Globallocal->assert(notclearbody);letkn=declare_constant~name~local~kind~typing_flags?user_warns(DefinitionEntryentry)inletgr=Names.GlobRef.ConstRefkninifshould_suggestthenProof_using.suggest_constant(Global.env())kn;grinlet()=Impargs.maybe_declare_manual_implicitsfalsedrefimpargsinlet()=definition_messagenameinHook.call?hook{Hook.S.uctx;obls;scope;dref};drefletdeclare_entry=declare_entry_core~obls:[](* Using processing *)letinterp_proof_using_genfenvevdcinfousing=letcextractv(fixnames,terms)=letname,new_terms=fvinname::fixnames,new_terms@termsinletfixnames,terms=CList.fold_rightcextractcinfo([],[])inProof_using.definition_usingenvevd~fixnames~terms~usingletinterp_proof_using_cinfoenvevdcinfousing=letf{CInfo.name;typ;_}=name,[EConstr.of_constrtyp]ininterp_proof_using_genfenvevdcinfousingletmake_recursive_bodyenvpossible_guardrec_declaration=letindexes=Pretyping.search_guardenvpossible_guardrec_declarationinletbody=matchindexeswith|Someindexes->Constr.mkFix((indexes,0),rec_declaration)|None->Constr.mkCoFix(0,rec_declaration)inbody,indexesletgather_mutual_using_data=List.fold_left2(funaccCInfo.{name;typ;_}body->lettyp,body=EConstr.(of_constrtyp,of_constrbody)in(name,[typ;body])::acc)[]letselect_bodyit=letopenConstrinmatchConstr.kindtwith|Fix((nv,0),decls)->mkFix((nv,i),decls)|CoFix(0,decls)->mkCoFix(i,decls)|_->assertfalseletmake_mutual_bodiesenv~typing_flags~rec_declaration~possible_guard=letenv=Environ.update_typing_flags?typing_flagsenvinletbody,indexes=make_recursive_bodyenvpossible_guardrec_declarationinletvars=Vars.universes_of_constrbodyinletnfix=Array.length(pi1rec_declaration)inletfixdecls=List.initnfix(funi->select_bodyibody)invars,fixdecls,indexesletprepare_recursive_declarationfixitems(fixdefs,fixrs)=letfixnames=List.map(funCInfo.{name}->name)fixitemsinletnames=List.map2(funCInfo.{name}r->Context.make_annot(Namename)r)fixitemsfixrsinletfixtypes=List.map(funCInfo.{typ}->typ)fixitemsinletdefs=List.map(Vars.subst_vars(List.revfixnames))fixdefsin(Array.of_listnames,Array.of_listfixtypes,Array.of_listdefs)letdeclare_mutual_definitions~info~cinfo~opaque~uctx~bodies~possible_guard?using()=let{Info.poly;udecl;scope;clearbody;kind;typing_flags;user_warns;ntns;_}=infoinletenv=Global.env()inletrec_declaration=prepare_recursive_declarationcinfobodiesinletvars,fixdecls,indexes=make_mutual_bodiesenv~typing_flags~rec_declaration~possible_guardinletuctx=UState.restrictuctxvarsinletunivs=UState.check_univ_decl~polyuctxudeclinletevd=Evd.from_envenvinletusing=Option.map(funusing->letcinfos=gather_mutual_using_datacinfofixdeclsinletfx=xininterp_proof_using_genfenvevdcinfosusing)usinginletcsts=CList.map2(funCInfo.{name;typ;impargs}body->letentry=definition_entry~opaque~types:typ~univs?usingbodyindeclare_entry~name~scope~clearbody~kind~impargs~uctx~typing_flags~user_warnsentry)cinfofixdeclsinletisfix=Option.has_someindexesinletfixnames=List.map(fun{CInfo.name}->name)cinfoinrecursive_messageisfixindexesfixnames;List.iter(Metasyntax.add_notation_interpretation~local:(scope=Locality.Discharge)(Global.env()))ntns;cstsletwarn_let_as_axiom=CWarnings.create~name:"let-as-axiom"~category:CWarnings.CoreCategories.vernacularPp.(funid->strbrk"Let definition"++spc()++Names.Id.printid++spc()++strbrk"declared as an axiom.")(* Declare an assumption when not in a section: Parameter/Axiom but also
Variable/Hypothesis seen as Local Parameter/Axiom *)letdeclare_parameter~name~scope~hook~impargs~uctxpe=letlocal=matchscopewith|Locality.Discharge->warn_let_as_axiomname;Locality.ImportNeedQualified|Locality.Globallocal->localinletkind=Decls.(IsAssumptionConjectural)inletdecl=ParameterEntrypeinletkn=declare_constant~name~local~kind~typing_flags:Nonedeclinletdref=Names.GlobRef.ConstRefkninlet()=Impargs.maybe_declare_manual_implicitsfalsedrefimpargsinlet()=assumption_messagenameinlet()=Hook.(call?hook{S.uctx;obls=[];scope;dref})indref(* Preparing proof entries *)leterror_unresolved_evarsenvsigmatevars=letpr_unresolved_evare=hov2(str"- "++Printer.pr_existential_keyenvsigmae++str": "++Himsg.explain_pretype_errorenvsigma(Pretype_errors.UnsolvableImplicit(e,None)))inCErrors.user_err(hov0beginstr"The following term contains unresolved implicit arguments:"++fnl()++str" "++Printer.pr_econstr_envenvsigmat++fnl()++str"More precisely: "++fnl()++v0(prlist_with_sepcutpr_unresolved_evar(Evar.Set.elementsevars))end)letcheck_evars_are_solvedenvsigmat=letevars=Evarutil.undefined_evars_of_termsigmatinifnot(Evar.Set.is_emptyevars)thenerror_unresolved_evarsenvsigmatevarsletprepare_definition~info~opaque?using~name~body~typsigma=let{Info.poly;udecl;inline;_}=infoinletenv=Global.env()inOption.iter(check_evars_are_solvedenvsigma)typ;check_evars_are_solvedenvsigmabody;letsigma,(body,types)=Evarutil.finalizesigma(funnf->nfbody,Option.mapnftyp)inletunivs=Evd.check_univ_decl~polysigmaudeclinletusing=letf(name,body,typ)=name,Option.List.flatten[Some(EConstr.of_constrbody);typ]inOption.map(interp_proof_using_genfenvsigma[name,body,typ])usinginletentry=definition_entry~opaque?using~inline?types~univsbodyinletuctx=Evd.evar_universe_contextsigmainentry,uctxletdeclare_definition_core~info~cinfo~opaque~obls~body?usingsigma=let{CInfo.name;impargs;typ;_}=cinfoinletentry,uctx=prepare_definition~info~opaque?using~name~body~typsigmainlet{Info.scope;clearbody;kind;hook;typing_flags;user_warns;ntns;_}=infoinletgref=declare_entry_core~name~scope~clearbody~kind~impargs~typing_flags~user_warns~obls?hook~uctxentryinList.iter(Metasyntax.add_notation_interpretation~local:(info.scope=Locality.Discharge)(Global.env()))ntns;gref,uctxletdeclare_definition~info~cinfo~opaque~body?usingsigma=declare_definition_core~obls:[]~info~cinfo~opaque~body?usingsigma|>fstletprepare_obligations~name?types~bodyenvsigma=letenv=Global.env()inlettypes=matchtypeswith|Somet->t|None->Retyping.get_type_ofenvsigmabodyinletsigma,(body,types)=Evarutil.finalize~abort_on_undefined_evars:falsesigma(funnf->nfbody,nftypes)inRetrieveObl.check_evarsenvsigma;letbody,types=EConstr.(of_constrbody,of_constrtypes)inletobls,(_,evmap),body,cty=RetrieveObl.retrieve_obligationsenvnamesigma0bodytypesinletuctx=Evd.evar_universe_contextsigmainbody,cty,uctx,evmap,oblsletprepare_parameter~poly~udecl~typessigma=letenv=Global.env()inPretyping.check_evars_are_solved~program_mode:falseenvsigma;letsigma,typ=Evarutil.finalize~abort_on_undefined_evars:truesigma(funnf->nftypes)inletunivs=Evd.check_univ_decl~polysigmaudeclinletpe={parameter_entry_secctx=None;parameter_entry_type=typ;parameter_entry_universes=univs;parameter_entry_inline_code=None;}insigma,petypeprogress=Remainofint|Dependent|DefinedofGlobRef.tmoduleObls_=structopenConstrtype'aobligation_body=DefinedOblof'a|TermOblofconstrmoduleObligation=structtypet={obl_name:Id.t;obl_type:types;obl_location:Evar_kinds.tLoc.located;obl_body:pconstantobligation_bodyoption;obl_status:bool*Evar_kinds.obligation_definition_status;obl_deps:Int.Set.t;obl_tac:unitProofview.tacticoption}letset_type~typobl={oblwithobl_type=typ}endtypeobligations={obls:Obligation.tarray;remaining:int}typefixpoint_kind=IsFixpointoflidentoptionlist|IsCoFixpointmoduleProgramDecl=structtype'at={prg_cinfo:constrCInfo.t;prg_info:Info.t;prg_using:Vernacexpr.section_subset_exproption;prg_opaque:bool;prg_hook:'aoption;prg_body:constr;prg_uctx:UState.t;prg_obligations:obligations;prg_deps:Id.tlist;prg_possible_guard:Pretyping.possible_guardoption(* None = not recursive *);prg_reduce:constr->constr}openObligationletmake~info~cinfo~opaque~reduce~deps~uctx~body~possible_guard?obl_hook?usingobls=letobls',body=matchbodywith|None->assert(Int.equal(Array.lengthobls)0);letn=Nameops.add_suffixcinfo.CInfo.name"_obligation"in([|{obl_name=n;obl_body=None;obl_location=Loc.tagEvar_kinds.InternalHole;obl_type=cinfo.CInfo.typ;obl_status=(false,Evar_kinds.Expand);obl_deps=Int.Set.empty;obl_tac=None}|],mkVarn)|Someb->(Array.mapi(funi(n,t,l,o,d,tac)->{obl_name=n;obl_body=None;obl_location=l;obl_type=t;obl_status=o;obl_deps=d;obl_tac=tac})obls,b)inletprg_uctx=UState.make_flexible_nonalgebraicuctxin{prg_cinfo={cinfowithCInfo.typ=reducecinfo.CInfo.typ};prg_info=info;prg_using=using;prg_hook=obl_hook;prg_opaque=opaque;prg_body=body;prg_uctx;prg_obligations={obls=obls';remaining=Array.lengthobls'};prg_deps=deps;prg_possible_guard=possible_guard;prg_reduce=reduce}letshowprg=let{CInfo.name;typ;_}=prg.prg_cinfoinletenv=Global.env()inletsigma=Evd.from_envenvinId.printname++spc()++str":"++spc()++Printer.pr_constr_envenvsigmatyp++spc()++str":="++fnl()++Printer.pr_constr_envenvsigmaprg.prg_bodymoduleInternal=structletget_nameprg=prg.prg_cinfo.CInfo.nameletget_uctxprg=prg.prg_uctxletset_uctx~uctxprg={prgwithprg_uctx=uctx}letget_polyprg=prg.prg_info.Info.polyletget_obligationsprg=prg.prg_obligationsletget_usingprg=prg.prg_usingendendopenObligationopenProgramDecl(* Saving an obligation *)(* XXX: Is this the right place for this? *)letit_mkLambda_or_LetIn_or_cleantctx=letopenContext.Rel.Declarationinletfoldtdecl=ifis_local_assumdeclthenTerm.mkLambda_or_LetIndecltelseifVars.noccurn1tthenVars.subst1mkProptelseTerm.mkLambda_or_LetIndecltinContext.Rel.fold_insidefoldctx~init:t(* XXX: Is this the right place for this? *)letdecompose_lam_prodcty=letopenContext.Rel.Declarationinletrecauxctxcty=match(Constr.kindc,Constr.kindty)with|LetIn(x,b,t,c),LetIn(x',b',t',ty)whenConstr.equalbb'&&Constr.equaltt'->letctx'=Context.Rel.add(LocalDef(x,b',t'))ctxinauxctx'cty|_,LetIn(x',b',t',ty)->letctx'=Context.Rel.add(LocalDef(x',b',t'))ctxinauxctx'(lift1c)ty|LetIn(x,b,t,c),_->letctx'=Context.Rel.add(LocalDef(x,b,t))ctxinauxctx'c(lift1ty)|Lambda(x,b,t),Prod(x',b',t')(* By invariant, must be convertible *)->letctx'=Context.Rel.add(LocalAssum(x,b'))ctxinauxctx'tt'|Cast(c,_,_),_->auxctxcty|_,_->(ctx,c,ty)inauxContext.Rel.emptycty(* XXX: What's the relation of this with Abstract.shrink ? *)letshrink_bodycty=letctx,b,ty=matchtywith|None->letctx,b=Term.decompose_lambda_declscin(ctx,b,None)|Somety->letctx,b,ty=decompose_lam_prodctyin(ctx,b,Somety)inletb',ty',n,args=List.fold_left(fun(b,ty,i,args)decl->ifVars.noccurn1b&&Option.cata(Vars.noccurn1)truetythen(Vars.subst1mkPropb,Option.map(Vars.subst1mkProp)ty,succi,args)elseletopenContext.Rel.Declarationinletargs=ifis_local_assumdeclthenmkReli::argselseargsin(Term.mkLambda_or_LetIndeclb,Option.map(Term.mkProd_or_LetIndecl)ty,succi,args))(b,ty,1,[])ctxin(ctx,b',ty',Array.of_listargs)(***********************************************************************)(* Saving an obligation *)(***********************************************************************)letuniverses_of_declbodytyp=letunivs_typ=matchtypwithNone->Univ.Level.Set.empty|Somety->Vars.universes_of_constrtyinletunivs_body=Vars.universes_of_constrbodyinUniv.Level.Set.unionunivs_bodyunivs_typletcurrent_obligation_uctxprguctxvars=letuctx=UState.restrictuctxvarsinifprg.prg_info.Info.polythenuctxelse(* We let the first obligation declare the monomorphic universe
context of the main constant (goes together with
update_global_obligation_uctx) *)UState.unionprg.prg_uctxuctxletupdate_global_obligation_uctxprguctx=letuctx=ifprg.prg_info.Info.polythen(* Accumulate the polymorphic constraints *)UState.unionprg.prg_uctxuctxelse(* The monomorphic universe context of the main constant has
been declared by the first obligation; it is now in the
global env and we now remove it for the further
declarations *)UState.Internal.reboot(Global.env())prg.prg_uctxinProgramDecl.Internal.set_uctx~uctxprgletinstance_of_univs=function|UState.Polymorphic_entryuctx,_->UVars.UContext.instanceuctx|UState.Monomorphic_entry_,_->UVars.Instance.emptyletdeclare_obligationprgobl~uctx~types~body=letbody=prg.prg_reducebodyinlettypes=Option.mapprg.prg_reducetypesinmatchobl.obl_statuswith|_,Evar_kinds.Expand->letprg_uctx=UState.unionprg.prg_uctxuctxinletprg=ProgramDecl.Internal.set_uctx~uctx:prg_uctxprgin(prg,{oblwithobl_body=Some(TermOblbody)},[])|force,Evar_kinds.Defineopaque->letopaque=(notforce)&&opaqueinletpoly=prg.prg_info.Info.polyinletctx,body,ty,args=ifnotpolythenshrink_bodybodytypeselse([],body,types,[||])inletuctx'=current_obligation_uctxprguctx(universes_of_declbodytypes)inletunivs=UState.univ_entry~polyuctx'inletinst=instance_of_univsunivsinletce=definition_entry?types:ty~opaque~univsbodyin(* ppedrot: seems legit to have obligations as local *)letconstant=declare_constant~name:obl.obl_name~typing_flags:prg.prg_info.Info.typing_flags~local:Locality.ImportNeedQualified~kind:Decls.(IsProofProperty)(DefinitionEntryce)indefinition_messageobl.obl_name;letprg=update_global_obligation_uctxprguctxinletbody=ifpolythenDefinedObl(constant,inst)elseletconst=mkConstU(constant,inst)inTermObl(it_mkLambda_or_LetIn_or_clean(mkApp(const,args))ctx)in(prg,{oblwithobl_body=Somebody},[GlobRef.ConstRefconstant])(* Updating the obligation meta-info on close *)letnot_transp_msg=Pp.(str"Obligation should be transparent but was declared opaque."++spc()++str"Use 'Defined' instead.")leterr_not_transp()=CErrors.user_errnot_transp_msgmoduleProgMap=Id.MapmoduleState=structtypet=prg_hookProgramDecl.tCEphemeron.keyProgMap.tandprg_hook=PrgHookoftHook.gletcall_prg_hook{prg_hook=hook}xpm=lethook=Option.map(fun(PrgHookh)->h)hookinHook.call_g?hookxpmletempty=ProgMap.emptyletpendingpm=ProgMap.filter(fun_v->(CEphemeron.getv).prg_obligations.remaining>0)pmletnum_pendingpm=pendingpm|>ProgMap.cardinalletfirst_pendingpm=pendingpm|>ProgMap.choose_opt|>Option.map(fun(_,v)->CEphemeron.getv)letget_unique_open_progpmname:(_,Id.tlist)result=matchnamewith|Somen->Option.cata(funp->Ok(CEphemeron.getp))(Error[])(ProgMap.find_optnpm)|None->(letn=num_pendingpminmatchnwith|0->Error[]|1->Option.cata(funp->Okp)(Error[])(first_pendingpm)|_->letprogs=Id.Set.elements(ProgMap.domainpm)inErrorprogs)letaddtkeyprg=ProgMap.addkey(CEphemeron.createprg)tletfoldt~f~init=letfkvacc=fk(CEphemeron.getv)accinProgMap.foldftinitletallpm=ProgMap.bindingspm|>List.map(fun(_,v)->CEphemeron.getv)letfindmt=ProgMap.find_opttm|>Option.mapCEphemeron.getmoduleView=structmoduleObl=structtypet={name:Id.t;loc:Loc.toption;status:bool*Evar_kinds.obligation_definition_status;solved:bool}letmake(o:Obligation.t)=let{obl_name;obl_location;obl_status;obl_body;_}=oin{name=obl_name;loc=fstobl_location;status=obl_status;solved=Option.has_someobl_body}endtypet={opaque:bool;remaining:int;obligations:Obl.tarray}letmake{prg_opaque;prg_obligations;_}={opaque=prg_opaque;remaining=prg_obligations.remaining;obligations=Array.mapObl.makeprg_obligations.obls}letmakeeph=CEphemeron.geteph|>makeendletviews=Id.Map.mapView.makesend(* In all cases, the use of the map is read-only so we don't expose the ref *)letmap_non_empty_keysis_emptym=ProgMap.fold(funkprgl->ifis_emptyprgthenlelsek::l)m[]letcheck_solved_obligationsis_empty~pm~what_for:unit=ifnot(ProgMap.is_emptypm)thenletkeys=map_non_empty_keysis_emptypminlethave_string=ifInt.equal(List.lengthkeys)1then" has "else" have "inCErrors.user_errPp.(str"Unsolved obligations when closing "++what_for++str":"++spc()++prlist_with_sepspc(funx->Id.printx)keys++strhave_string++str"unsolved obligations.")letmap_replacekvm=ProgMap.addk(CEphemeron.createv)(ProgMap.removekm)letprogmap_removepmprg=ProgMap.removeprg.prg_cinfo.CInfo.namepmletprogmap_replaceprg'pm=map_replaceprg'.prg_cinfo.CInfo.nameprg'pmletobligations_solvedprg=Int.equalprg.prg_obligations.remaining0letobligations_messagerem=Format.asprintf"%s %s remaining"(ifrem>0thenstring_of_intremelse"No more")(CString.pluralrem"obligation")|>Pp.str|>Flags.if_verboseFeedback.msg_infoletget_obligation_bodyexpandobl=matchobl.obl_bodywith|None->None|Somec->(ifexpand&&sndobl.obl_status==Evar_kinds.Expandthenmatchcwith|DefinedOblpc->Some(Environ.constant_value_in(Global.env())pc)|TermOblc->SomecelsematchcwithDefinedOblpc->Some(mkConstUpc)|TermOblc->Somec)letobl_substitutionexpandoblsdeps=Int.Set.fold(funxacc->letxobl=obls.(x)inmatchget_obligation_bodyexpandxoblwith|None->acc|Someoblb->(xobl.obl_name,(xobl.obl_type,oblb))::acc)deps[]letrecintset_to=function|-1->Int.Set.empty|n->Int.Set.addn(intset_to(predn))letobligation_substitutionexpandprg=letobls=prg.prg_obligations.oblsinletints=intset_to(pred(Array.lengthobls))inobl_substitutionexpandoblsintsletsubst_progsubstprg=letsubst'=List.map(fun(n,(_,b))->(n,b))substin(Vars.replace_varssubst'prg.prg_body,Vars.replace_varssubst'(* Termops.refresh_universes *)prg.prg_cinfo.CInfo.typ)letdeclare_definition~pmprg=letvarsubst=obligation_substitutiontrueprginletsigma=Evd.from_ctxprg.prg_uctxinletbody,types=subst_progvarsubstprginletbody,types=EConstr.(of_constrbody,of_constrtypes)inletcinfo={prg.prg_cinfowithCInfo.typ=Sometypes}inletname,info,opaque,using=prg.prg_cinfo.CInfo.name,prg.prg_info,prg.prg_opaque,prg.prg_usinginletobls=List.map(fun(id,(_,c))->(id,c))varsubstin(* XXX: This is doing normalization twice *)letkn,uctx=declare_definition_core~cinfo~info~obls~body~opaque?usingsigmain(* XXX: We call the obligation hook here, by consistency with the
previous imperative behaviour, however I'm not sure this is right *)letpm=State.call_prg_hookprg{Hook.S.uctx;obls;scope=prg.prg_info.Info.scope;dref=kn}pminletpm=progmap_removepmprginpm,knletdeclare_mutual_definitions~pml=letfirst=List.hdlinletdefoblx=letoblsubst=obligation_substitutiontruexinletsubs,typ=subst_progoblsubstxinletenv=Global.env()inletsigma=Evd.from_ctxx.prg_uctxinletr=Retyping.relevance_of_typeenvsigma(EConstr.of_constrtyp)inletterm=EConstr.of_constrsubsinlettyp=EConstr.of_constrtypinletterm=EConstr.to_constrsigmaterminlettyp=EConstr.to_constrsigmatypinletr=EConstr.ERelevance.kindsigmarinletdef=(x.prg_reduceterm,r,x.prg_reducetyp,x.prg_cinfo.CInfo.impargs)inletoblsubst=List.map(fun(id,(_,c))->(id,c))oblsubstin(def,oblsubst)inletdefs,obls=List.split(List.mapdefobll)inletobls=List.flattenoblsinletfixitems=List.map2(fun(d,relevance,typ,impargs)name->CInfo.make~name~typ~impargs())defsfirst.prg_depsinletfixdefs,fixrs,fixtypes,_=List.split4defsinletpossible_guard=Option.getfirst.prg_possible_guardin(* Declare the recursive definitions *)letkns=declare_mutual_definitions~info:first.prg_info~uctx:first.prg_uctx~bodies:(fixdefs,fixrs)~possible_guard~opaque:first.prg_opaque~cinfo:fixitems?using:first.prg_using()in(* Only for the first constant *)letdref=List.hdknsinletscope=first.prg_info.Info.scopeinlets_hook={Hook.S.uctx=first.prg_uctx;obls;scope;dref}inHook.call?hook:first.prg_info.Info.hooks_hook;(* XXX: We call the obligation hook here, by consistency with the
previous imperative behaviour, however I'm not sure this is right *)letpm=State.call_prg_hookfirsts_hookpminletpm=List.fold_leftprogmap_removepmlinpm,drefletupdate_obls~pmprgoblsrem=letprg_obligations={obls;remaining=rem}inletprg'={prgwithprg_obligations}inletpm=progmap_replaceprg'pminobligations_messagerem;ifrem>0thenpm,Remainremelsematchprg'.prg_depswith|[]->letpm,kn=declare_definition~pmprg'inpm,Definedkn|l->letprogs=List.map(funx->CEphemeron.get(ProgMap.findxpm))prg'.prg_depsinifList.for_all(funx->obligations_solvedx)progsthenletpm,kn=declare_mutual_definitions~pmprogsinpm,Definedknelsepm,Dependentletdependenciesoblsn=letres=refInt.Set.emptyinArray.iteri(funiobl->if(not(Int.equalin))&&Int.Set.memnobl.obl_depsthenres:=Int.Set.addi!res)obls;!resletupdate_program_decl_on_defined~pmprgoblsnumoblrem~auto=letobls=Array.copyoblsinlet()=obls.(num)<-oblinletpm,_progress=update_obls~pmprgobls(predrem)inletpm=ifpredrem>0thenletdeps=dependenciesoblsnuminifnot(Int.Set.is_emptydeps)thenletpm,_progress=auto~pm(Someprg.prg_cinfo.CInfo.name)depsNoneinpmelsepmelsepminpmtypeobligation_resolver=pm:State.t->Id.toption->Int.Set.t->unitProofview.tacticoption->State.t*progresstypeobl_check_final=AllFinal|SpecificFinalofId.ttypeobligation_qed_info={name:Id.t;num:int;auto:obligation_resolver;check_final:obl_check_finaloption;}letnot_final_obligationn=letmsg=matchnwith|AllFinal->str"This obligation is not final."|SpecificFinaln->str"This obligation is not final for program "++Id.printn++str"."inCErrors.user_errmsgletdo_check_final~pm=function|None->()|Somecheck_final->letfinal=matchcheck_finalwith|AllFinal->beginmatchState.first_pendingpmwith|Some_->false|None->trueend|SpecificFinaln->beginmatchState.get_unique_open_progpm(Somen)with|Error_->true|Ok_->falseendinifnotfinalthennot_final_obligationcheck_finalletobligation_terminator~pm~entry~uctx~oinfo:{name;num;auto;check_final}=letenv=Global.env()inletty=entry.proof_entry_typeinletbody,uctx=inline_private_constants~uctxenventryinletsigma=Evd.from_ctxuctxinInductiveops.control_only_guard(Global.env())sigma(EConstr.of_constrbody);(* Declare the obligation ourselves and drop the hook *)letprg=Option.get(State.findpmname)inlet{obls;remaining=rem}=prg.prg_obligationsinletobl=obls.(num)inletstatus=match(obl.obl_status,entry.proof_entry_opaque)with|(_,Evar_kinds.Expand),true->err_not_transp()|(true,_),true->err_not_transp()|(false,_),true->Evar_kinds.Definetrue|(_,Evar_kinds.Definetrue),false->Evar_kinds.Definefalse|(_,status),false->statusinletobl={oblwithobl_status=(false,status)}inletprg,obl,cst=declare_obligationprgobl~body~types:ty~uctxinletpm=update_program_decl_on_defined~pmprgoblsnumoblrem~autoinlet()=do_check_final~pmcheck_finalinpm,cst(* Similar to the terminator but for the admitted path; this assumes
the admitted constant was already declared.
FIXME: There is duplication of this code with obligation_terminator
and Obligations.admit_obligations *)letobligation_admitted_terminator~pmtyp{name;num;auto;check_final}declare_funuctx=letprg=Option.get(State.findpmname)inlet{obls;remaining=rem}=prg.prg_obligationsinletobl=obls.(num)inlet()=matchobl.obl_statuswith|true,Evar_kinds.Expand|true,Evar_kinds.Definetrue->err_not_transp()|_->()inletuctx'=current_obligation_uctxprguctx(Vars.universes_of_constrtyp)inletsec_vars=Nonein(* Not using "using" for obligations *)letunivs=UState.univ_entry~poly:prg.prg_info.Info.polyuctx'inletcst=declare_fun~uctx~sec_vars~univsinletinst=instance_of_univsunivsinletobl={oblwithobl_body=Some(DefinedObl(cst,inst))}inletprg=update_global_obligation_uctxprguctxinletpm=update_program_decl_on_defined~pmprgoblsnumoblrem~autoinlet()=do_check_final~pmcheck_finalinpmend(************************************************************************)(* Handling of interactive proofs *)(************************************************************************)moduleProof_ending=structtypet=|Regular|End_obligationofObls_.obligation_qed_info|End_deriveof{f:Id.t;name:Id.t}|End_equationsof{hook:pm:Obls_.State.t->Constant.tlist->Evd.evar_map->Obls_.State.t;i:Id.t;types:(Environ.env*Evar.t*Evd.undefinedEvd.evar_info*EConstr.named_context*Evd.econstr)list;sigma:Evd.evar_map}end(* Alias *)moduleProof=structmoduleProof_info=structtypet={cinfo:Constr.tCInfo.tlist(** cinfo contains each individual constant info in a mutual decl *);info:Info.t;proof_ending:Proof_ending.tCEphemeron.key(* This could be improved and the CEphemeron removed *);possible_guard:Pretyping.possible_guardoption(* None = not recursive *)(** thms and compute guard are specific only to
start_definition + regular terminator, so we
could make this per-proof kind *)}letmake~cinfo~info?possible_guard?(proof_ending=Proof_ending.Regular)()={cinfo;info;possible_guard;proof_ending=CEphemeron.createproof_ending}endtypet={endline_tactic:Genarg.glob_generic_argumentoption;using:Id.Set.toption;proof:Proof.t;initial_euctx:UState.t(** The initial universe context (for the statement) *);pinfo:Proof_info.t}(*** Proof Global manipulation ***)letgetps=ps.proofletget_nameps=(Proof.dataps.proof).Proof.nameletget_initial_euctxps=ps.initial_euctxletfold~fp=fp.proofletmap~fp={pwithproof=fp.proof}letmap_fold~fp=letproof,res=fp.proofin{pwithproof},resletmap_fold_endline~fps=letet=matchps.endline_tacticwith|None->Proofview.tclUNIT()|Sometac->letopenGeninterpinlet{Proof.poly}=Proof.dataps.proofinletist={lfun=Id.Map.empty;poly;extra=TacStore.empty}inletGenarg.GenArg(Genarg.Glbwittag,tac)=tacinlettac=Geninterp.interptagisttacinFtactic.runtac(fun_->Proofview.tclUNIT())inlet(newpr,ret)=fetps.proofinletps={pswithproof=newpr}inps,retletcompactpf=map~f:Proof.compactpf(* Sets the tactic to be used when a tactic line is closed with [...] *)letset_endline_tactictacps={pswithendline_tactic=Sometac}letinitialize_named_context_for_proof()=letsign=Global.named_context()inList.fold_right(fundsignv->letid=NamedDecl.get_iddinletd=ifDecls.variable_opacityidthenNamedDecl.drop_bodydelsedinEnviron.push_named_context_valdsignv)signEnviron.empty_named_context_valletstart_proof_core~name~typ~pinfo?(sign=initialize_named_context_for_proof())?usingsigma=(* In ?sign, we remove the bodies of variables in the named context
marked "opaque", this is a hack tho, see #10446, and
build_constant_by_tactic uses a different method that would break
program_inference_hook *)let{Proof_info.info={Info.poly;typing_flags;_};_}=pinfoinletgoals=[Global.env_of_contextsign,typ]inletproof=Proof.start~name~poly?typing_flagssigmagoalsinletinitial_euctx=Evd.evar_universe_contextProof.((dataproof).sigma)in{proof;endline_tactic=None;using;initial_euctx;pinfo}(** [start_proof ~info ~cinfo sigma] starts a proof of [cinfo].
The proof is started in the evar map [sigma] (which
can typically contain universe constraints) *)letstart_core~info~cinfo?proof_ending?usingsigma=let{CInfo.name;typ;_}=cinfoincheck_existsname;letcinfo=[{cinfowithCInfo.typ=EConstr.Unsafe.to_constrcinfo.CInfo.typ}]inletpinfo=Proof_info.make~cinfo~info?proof_ending()instart_proof_core~name~typ~pinfo?sign:None?usingsigmaletstart=start_core?proof_ending:Noneletstart_dependent~info~name~proof_endinggoals=let{Info.poly;typing_flags;_}=infoinletproof=Proof.dependent_start~name~poly?typing_flagsgoalsinletinitial_euctx=Evd.evar_universe_contextProof.((dataproof).sigma)inletcinfo=[]inletpinfo=Proof_info.make~info~cinfo~proof_ending()in{proof;endline_tactic=None;using=None;initial_euctx;pinfo}letstart_derive~f~name~infogoals=letproof_ending=Proof_ending.End_derive{f;name}instart_dependent~info~name~proof_endinggoalsletstart_equations~name~info~hook~typessigmagoals=letproof_ending=Proof_ending.End_equations{hook;i=name;types;sigma}instart_dependent~name~info~proof_endinggoalsletrec_tac_initializerPretyping.{possibly_cofix;possible_fix_indices}thms=ifpossibly_cofixthenmatchList.map(fun{CInfo.name;typ}->name,(EConstr.of_constrtyp))thmswith|(id,_)::l->Tactics.mutual_cofixidl0|_->assertfalseelse(* nl is set to its maximal possible value for the purpose of mutual_fix; it will then be recomputed at Qed-time *)letnl=List.mapsucc(List.mapList.lastpossible_fix_indices)inmatchList.map2(fun{CInfo.name;typ}n->(name,n,(EConstr.of_constrtyp)))thmsnlwith|(id,n,_)::l->Tactics.mutual_fixidnl0|_->assertfalseletstart_definition~info~cinfo?usingsigma=let{CInfo.name;typ;args}=cinfoinletinit_tac=Tactics.auto_intros_tacargsinletpinfo=Proof_info.make~cinfo:[cinfo]~info()inletenv=Global.env()inletusing=Option.map(interp_proof_using_cinfoenvsigma[cinfo])usinginletlemma=start_proof_core~name~typ:(EConstr.of_constrtyp)~pinfo?sign:None?usingsigmainmaplemma~f:(funp->pi1@@Proof.run_tacticGlobal.(env())init_tacp)letstart_mutual_definitions~info~cinfo?bodies~possible_guard?usingsigma=letintro_tac{CInfo.args;_}=Tactics.auto_intros_tacargsinletinit_tac=letrec_tac=rec_tac_initializerpossible_guardcinfoinletterm_tac=matchbodieswith|None->List.mapintro_taccinfo|Somebodies->(* This is the case for hybrid proof mode / definition
fixpoint, where terms for some constants are given with := *)lettacl=List.map(Option.cata(EConstr.of_constr%>Tactics.exact_no_check)Tacticals.tclIDTAC)bodiesinList.map2(funtacthm->Tacticals.tclTHENtac(intro_tacthm))taclcinfoinTacticals.tclTHENSrec_tacterm_tacinmatchcinfowith|[]->CErrors.anomaly(Pp.str"No proof to start.")|{CInfo.name;typ;_}::thms->letpinfo=Proof_info.make~cinfo~info~possible_guard()in(* start_lemma has the responsibility to add (name, impargs, typ)
to thms, once Info.t is more refined this won't be necessary *)lettyp=EConstr.of_constrtypinletenv=Global.env()inletusing=Option.map(interp_proof_using_cinfoenvsigmacinfo)usinginletlemma=start_proof_core~name~typ~pinfo?usingsigmainletlemma=maplemma~f:(funp->pi1@@Proof.run_tacticGlobal.(env())init_tacp)inlet()=(* Temporary declaration of notations for the time of the proofs *)letntn_env=(* We simulate the goal context in which the fixpoint bodies have to be proved (exact relevance does not matter) *)letmake_declCInfo.{name;typ}=Context.Named.Declaration.LocalAssum(Context.annotRname,typ)inEnviron.push_named_context(List.mapmake_declcinfo)(Global.env())inList.iter(Metasyntax.add_notation_interpretation~local:(info.scope=Locality.Discharge)ntn_env)info.ntnsinlemmaletget_used_variablespf=pf.usingletget_universe_declpf=pf.pinfo.Proof_info.info.Info.udeclletdefinition_scopeps=ps.pinfo.info.scopeletset_used_variablesps~using=letopenContext.Named.Declarationinletenv=Global.env()inletctx=Environ.keep_hypsenvusinginletctx_set=List.fold_rightId.Set.add(List.mapNamedDecl.get_idctx)Id.Set.emptyinletvars_of=Environ.global_vars_setinletauxenventry(ctx,all_safeasorig)=matchentrywith|LocalAssum({Context.binder_name=x},_)->ifId.Set.memxall_safethenorigelse(ctx,all_safe)|LocalDef({Context.binder_name=x},bo,ty)asdecl->ifId.Set.memxall_safethenorigelseletvars=Id.Set.union(vars_ofenvbo)(vars_ofenvty)inifId.Set.subsetvarsall_safethen(decl::ctx,Id.Set.addxall_safe)else(ctx,all_safe)inletctx,_=Environ.fold_named_contextauxenv~init:(ctx,ctx_set)inifnot(Option.is_emptyps.using)thenCErrors.user_errPp.(str"Used section variables can be declared only once");ctx,{pswithusing=Some(Context.Named.to_varsctx)}(* Interprets the expression in the current proof context, from vernacentries *)letget_recnamespf=ifOption.has_somepf.pinfo.Proof_info.possible_guardthenList.map(func->c.CInfo.name)pf.pinfo.Proof_info.cinfoelse[]letinterpret_proof_usingpstateusing=letenv=Global.env()inletpf=getpstateinletsigma,_=Proof.get_proof_contextpfinletfixnames=get_recnamespstateinletinitial_goalspf=Proofview.initial_goalsProof.((datapf).entry)inletterms=List.mappi3(initial_goals(getpstate))inProof_using.definition_usingenvsigma~fixnames~using~termsletset_proof_usingpstateusing=letusing=interpret_proof_usingpstateusinginset_used_variablespstate~usingletget_open_goalsps=letProof.{goals;stack;sigma}=Proof.dataps.proofinList.lengthgoals+List.fold_left(+)0(List.map(fun(l1,l2)->List.lengthl1+List.lengthl2)stack)+List.length(Evd.shelfsigma)typeproof_object={entries:proof_entrylist;uctx:UState.t;pinfo:Proof_info.t}let{Goptions.get=private_poly_univs}=Goptions.declare_bool_option_and_ref~key:["Private";"Polymorphic";"Universes"]~value:true()letwarn_remaining_shelved_goals=CWarnings.create~name:"remaining-shelved-goals"~category:CWarnings.CoreCategories.tactics(fun()->Pp.str"The proof has remaining shelved goals.")letwarn_given_up=CWarnings.create~name:"remaining-given-up"~category:CWarnings.CoreCategories.tactics(fun()->Pp.str"The proof has given up (admitted) goals.")letwarn_remaining_unresolved_evars=CWarnings.create~name:"remaining-unresolved-evars"~category:CWarnings.CoreCategories.tactics(fun()->Pp.str"The proof has unresolved variables.")typeopen_proof_kind=|OpenGoals|NonGroundResultofbool(* true = at least some of the evars in the proof term are given up *)exceptionOpenProofofNames.Id.t*open_proof_kindlet()=CErrors.register_handlerbeginfunction|OpenProof(pid,reason)->letopenPpinletppreason=matchreasonwith|OpenGoals->str"(there are remaining open goals)"|NonGroundResulthas_given_up->str"(the proof term is not complete"++(ifhas_given_upthenstr" because of given up (admitted) goals"elsemt())++str")"inlethow_to_admit=matchreasonwith|OpenGoals|NonGroundResultfalse->mt()|NonGroundResulttrue->fnl()++str"If this is really what you want to do, use Admitted in place of Qed."inSome(str" (in proof "++Names.Id.printpid++str"): "++str"Attempt to save an incomplete proof"++spc()++ppreason++str"."++how_to_admit)|_->Noneend(* XXX: This is still separate from close_proof below due to drop_pt in the STM *)letprepare_proof?(warn_incomplete=true){proof}=letProof.{name=pid;entry;poly;sigma=evd}=Proof.dataproofinletinitial_goals=Proofview.initial_goalsentryinlet()=ifnot@@Proof.is_doneproofthenraise(OpenProof(pid,OpenGoals))inlet_:Proof.t=(* checks that we closed all brackets ("}") *)Proof.unfocus_allproofinleteff=Evd.eval_side_effectsevdinletevd=Evd.minimize_universesevdinletto_constrc=matchEConstr.to_constr_optevdcwith|Somep->Vars.universes_of_constrp,p|None->lethas_given_up=letexceptionFoundinletrecauxc=let()=matchEConstr.kindevdcwith|Evar(e,_)->ifEvar.Set.meme(Evd.given_upevd)thenraiseFound|_->()inEConstr.iterevdauxcintryauxc;falsewithFound->trueinraise(OpenProof(pid,NonGroundResulthas_given_up))in(* ppedrot: FIXME, this is surely wrong. There is no reason to duplicate
side-effects... This may explain why one need to uniquize side-effects
thereafter... *)(* EJGA: actually side-effects de-duplication and this codepath is
unrelated. Duplicated side-effects arise from incorrect scheme
generation code, the main bulk of it was mostly fixed by #9836
but duplication can still happen because of rewriting schemes I
think; however the code below is mostly untested, the only
code-paths that generate several proof entries are derive and
equations and so far there is no code in the CI that will
actually call those and do a side-effect, TTBOMK *)(* EJGA: likely the right solution is to attach side effects to the first constant only? *)letproofs=List.map(fun(_,body,typ)->(to_constrbody,eff),to_constrtyp)initial_goalsinlet()=ifwarn_incompletethenbeginifEvd.has_shelvedevdthenwarn_remaining_shelved_goals()elseifEvd.has_given_upevdthenwarn_given_up()elseifEvd.has_undefinedevdthenwarn_remaining_unresolved_evars()endinproofs,Evd.evar_universe_contextevdletmake_univs_deferred~poly~initial_euctx~uctx~udecl(used_univs_typ,typ)(used_univs_body,body)=letused_univs=Univ.Level.Set.unionused_univs_bodyused_univs_typinletutyp=UState.univ_entry~polyinitial_euctxinletuctx=UState.constrain_variables(fst(UState.context_setinitial_euctx))uctxin(* For vi2vo compilation proofs are computed now but we need to
complement the univ constraints of the typ with the ones of
the body. So we keep the two sets distinct. *)letuctx_body=UState.restrictuctxused_univsinletubody=UState.check_mono_univ_decluctx_bodyudeclinutyp,ubodyletmake_univs_private_poly~poly~uctx~udecl(used_univs_typ,typ)(used_univs_body,body)=letused_univs=Univ.Level.Set.unionused_univs_bodyused_univs_typinletuctx=UState.restrictuctxused_univsinletuctx'=UState.restrictuctxused_univs_typinletutyp=UState.check_univ_decl~polyuctx'udeclinletubody=Univ.ContextSet.diff(UState.context_setuctx)(UState.context_setuctx')inutyp,ubodyletmake_univs~poly~uctx~udecleff(used_univs_typ,typ)(used_univs_body,body)=letused_univs=Univ.Level.Set.unionused_univs_bodyused_univs_typin(* Since the proof is computed now, we can simply have 1 set of
constraints in which we merge the ones for the body and the ones
for the typ. We recheck the declaration after restricting with
the actually used universes.
TODO: check if restrict is really necessary now. *)letuctx=UState.restrictuctxused_univsinletutyp=UState.check_univ_decl~polyuctxudeclinletutyp=matchfstutypwith|Polymorphic_entry_->utyp|Monomorphic_entryuctx->(* the constraints from the body may depend on universes from
the side effects, so merge it all together.
Example failure if we don't is "l1" in test-suite/success/rewrite.v.
Not sure if it makes more sense to merge them in the ustate
before restrict/check_univ_decl or here. Since we only do it
when monomorphic it shouldn't really matter. *)Monomorphic_entry(Univ.ContextSet.unionuctx(Safe_typing.universes_of_privateeff)),sndutypinutyp,Univ.ContextSet.emptyletclose_proof?warn_incomplete~opaque~keep_body_ucst_separateps=let{using;proof;initial_euctx;pinfo}=psinlet{Proof_info.info={Info.udecl}}=pinfoinlet{Proof.poly}=Proof.dataproofinletelist,uctx=prepare_proof?warn_incompletepsinletopaque=matchopaquewith|Vernacexpr.Opaque->true|Vernacexpr.Transparent->falseinletmake_entry((((_ub,body)asb),eff),((_ut,typ)ast))=letutyp,ubody=(* allow_deferred case *)ifnotpoly&&keep_body_ucst_separatethenmake_univs_deferred~initial_euctx~poly~uctx~udecltb(* private_poly_univs case *)elseifpoly&&opaque&&private_poly_univs()thenmake_univs_private_poly~poly~uctx~udecltbelsemake_univs~poly~uctx~udecleff.Evd.seff_privatetbindefinition_entry_core~opaque?using~univs:utyp~univsbody:ubody~types:typ~effbodyinletentries=CList.mapmake_entryelistin{entries;uctx;pinfo}typeclosed_proof_output=(Constr.t*Evd.side_effects)list*UState.tletclose_proof_delayed~feedback_idps(fpl:closed_proof_outputFuture.computation)=let{using;proof;initial_euctx;pinfo}=psinlet{Proof_info.info={Info.udecl}}=pinfoinlet{Proof.poly;entry;sigma}=Proof.dataproofin(* We don't allow poly = true in this path *)ifpolythenCErrors.anomaly(Pp.str"Cannot delay universe-polymorphic constants.");(* Because of dependent subgoals at the beginning of proofs, we could
have existential variables in the initial types of goals, we need to
normalise them for the kernel. *)letnf=Evarutil.nf_evars_universes(Evd.set_universe_contextsigmainitial_euctx)in(* We only support opaque proofs, this will be enforced by using
different entries soon *)letopaque=trueinletmake_entryi(_,_,types)=(* Already checked the univ_decl for the type universes when starting the proof. *)letunivs=UState.univ_entry~poly:falseinitial_euctxinlettypes=nf(EConstr.Unsafe.to_constrtypes)in(* NB: for Admitted proofs [fpl] is not valid (raises anomaly when forced) *)Future.chainfpl(fun(pf,uctx)->let(pt,eff)=List.nthpfiin(* Deferred proof, we already checked the universe declaration with
the initial universes, ensure that the final universes respect
the declaration as well. If the declaration is non-extensible,
this will prevent the body from adding universes and constraints. *)letuctx=UState.constrain_variables(fst(UState.context_setinitial_euctx))uctxinletused_univs=Univ.Level.Set.union(Vars.universes_of_constrtypes)(Vars.universes_of_constrpt)inletuctx=UState.restrictuctxused_univsinletuctx=UState.check_mono_univ_decluctxudeclin(pt,uctx),eff)|>delayed_definition_entry~opaque~feedback_id~using~univs~typesinletentries=CList.map_imake_entry0(Proofview.initial_goalsentry)in{entries;uctx=initial_euctx;pinfo}letclose_future_proof=close_proof_delayedletreturn_proofps=letp,uctx=prepare_proofpsinList.map(fun(((_ub,body),eff),_)->(body,eff))p,uctxletupdate_sigma_univsugraphp=map~f:(Proof.update_sigma_univsugraph)pletnext=letn=ref0infun()->incrn;!nletbytac=map_fold~f:(Proof.solve(Goal_select.SelectNth1)Nonetac)letbuild_constant_by_tactic~name?warn_incomplete?(opaque=Vernacexpr.Transparent)~sigma~sign~poly(typ:EConstr.t)tac=lettyp_=EConstr.Unsafe.to_constrtypinletcinfo=[CInfo.make~name~typ:typ_()]inletinfo=Info.make~poly()inletpinfo=Proof_info.make~cinfo~info()inletpf=start_proof_core~name~typ~pinfo~signsigmainletpf,status=bytacpfinlet{entries;uctx}=close_proof?warn_incomplete~opaque~keep_body_ucst_separate:falsepfinlet{Proof.sigma}=Proof.datapf.proofinletsigma=Evd.set_universe_contextsigmauctxinmatchentrieswith|[entry]->letentry=Internal.pmap_entry_body~f:Future.forceentryinentry,status,sigma|_->CErrors.anomalyPp.(str"[build_constant_by_tactic] close_proof returned more than one proof term")letbuild_by_tacticenv~uctx~poly~typtac=letname=Id.of_string("temporary_proof"^string_of_int(next()))inletsign=Environ.(val_of_named_context(named_contextenv))inletsigma=Evd.from_ctxuctxinletce,status,sigma=build_constant_by_tactic~name~sigma~sign~polytyptacinletuctx=Evd.evar_universe_contextsigmain(* ignore side effect universes:
we don't reset the global env in this code path so the side effects are still present
cf #13271 and discussion in #18874
(but due to #13324 we still want to inline them) *)letcb,_uctx=inline_private_constants~uctxenvceincb,ce.proof_entry_type,ce.proof_entry_universes,status,uctxletdeclare_abstract~name~poly~kind~sign~secsign~opaque~solve_tacsigmaconcl=let(const,safe,sigma')=trybuild_constant_by_tactic~warn_incomplete:false~name~opaque:Vernacexpr.Transparent~poly~sigma~sign:secsignconclsolve_tacwithLogic_monad.TacticFailureeassrc->(* if the tactic [tac] fails, it reports a [TacticFailure e],
which is an error irrelevant to the proof system (in fact it
means that [e] comes from [tac] failing to yield enough
success). Hence it reraises [e]. *)let(_,info)=Exninfo.capturesrcinExninfo.iraise(e,info)inletsigma=Evd.drop_new_defined~original:sigmasigma'inletbody,effs=const.proof_entry_bodyin(* We drop the side-effects from the entry, they already exist in the ambient environment *)letconst=Internal.pmap_entry_bodyconst~f:(fun_->body,())in(* EJGA: Hack related to the above call to
`build_constant_by_tactic` with `~opaque:Transparent`. Even if
the abstracted term is destined to be opaque, if we trigger the
`if poly && opaque && private_poly_univs ()` in `close_proof`
kernel will boom. This deserves more investigation. *)letconst=Internal.set_opacity~opaqueconstinletconst,args=Internal.shrink_entrysignconstinletcst()=(* do not compute the implicit arguments, it may be costly *)let()=Impargs.make_implicit_argsfalsein(* ppedrot: seems legit to have abstracted subproofs as local*)declare_private_constant~local:Locality.ImportNeedQualified~name~kindconstinletcst,eff=Impargs.with_implicit_protectioncst()inletinst=matchfstconst.proof_entry_universeswith|UState.Monomorphic_entry_->EConstr.EInstance.empty|UState.Polymorphic_entryctx->(* We mimic what the kernel does, that is ensuring that no additional
constraints appear in the body of polymorphic constants. Ideally this
should be enforced statically. *)let(_,body_uctx),_=const.proof_entry_bodyinlet()=assert(Univ.ContextSet.is_emptybody_uctx)inEConstr.EInstance.make(UVars.UContext.instancectx)inletargs=List.mapEConstr.of_constrargsinletlem=EConstr.mkConstU(cst,inst)inleteffs=Evd.concat_side_effectseffeffsineffs,sigma,lem,args,safeletget_goal_contextpfi=letp=getpfinProof.get_goal_context_genpiletget_current_goal_contextpf=letp=getpfintryProof.get_goal_context_genp1with|Proof.NoSuchGoal_->(* spiwack: returning empty evar_map, since if there is no goal,
under focus, there is no accessible evar either. EJGA: this
seems strange, as we have pf *)letenv=Global.env()inEvd.from_envenv,envletget_current_contextpf=letp=getpfinProof.get_proof_contextp(* Support for mutually proved theorems *)(* XXX: this should be unified with the code for non-interactive
mutuals previously on this file. *)moduleMutualEntry:sigvaldeclare_possibly_mutual_parameters:pinfo:Proof_info.t->uctx:UState.t->sec_vars:Id.Set.toption->univs:UState.named_universes_entry->Names.GlobRef.tlistvaldeclare_possibly_mutual_definitions(* Common to all recthms *):pinfo:Proof_info.t->uctx:UState.t->entry:proof_entry->Names.GlobRef.tlistend=struct(* XXX: Refactor this with the code in [Declare.declare_possibly_mutual_definitions] *)letguess_decreasingenvpossible_guard((body,ctx),eff)=letopenConstrinmatchConstr.kindbodywith|Fix(_,(_,_,fixdefsasfixdecls))|CoFix(_,(_,_,fixdefsasfixdecls))->letenv=Safe_typing.push_private_constantsenveff.Evd.seff_privateinletbody,_=make_recursive_bodyenvpossible_guardfixdeclsin(body,ctx),eff|_->assertfalseletupdate_mutual_entryientryuctxtyp={entrywithproof_entry_body=Future.chainentry.proof_entry_body(fun((body,uctx),eff)->((select_bodyibody,uctx),eff));proof_entry_type=Some(UState.nf_universesuctxtyp)}letdeclare_possibly_mutual_definitions~pinfo~uctx~entry=letentries=matchpinfo.Proof_info.possible_guardwith|None->(* Not a recursive statement *)[entry]|Somepossible_guard->(* Try all combinations... not optimal *)letenv=Global.env()inlettyping_flags=pinfo.Proof_info.info.Info.typing_flagsinletenv=Environ.update_typing_flags?typing_flagsenvinletentry=Internal.map_entry_bodyentry~f:(guess_decreasingenvpossible_guard)inList.map_i(funiCInfo.{typ}->update_mutual_entryientryuctxtyp)0pinfo.Proof_info.cinfoinlet{Proof_info.info={Info.hook;scope;clearbody;kind;typing_flags;user_warns;_}}=pinfoinletrefs=List.map2(funCInfo.{name;impargs}->declare_entry~name~scope~clearbody~kind?hook~impargs~typing_flags~user_warns~uctx)pinfo.Proof_info.cinfoentriesinlet()=(* We override the temporary notations used while proving, now using the global names *)letlocal=pinfo.info.scope=Locality.DischargeinCWarnings.with_warn("-"^Notation.warning_overridden_name)(List.iter(Metasyntax.add_notation_interpretation~local(Global.env())))pinfo.info.ntnsinrefsletdeclare_possibly_mutual_parameters~pinfo~uctx~sec_vars~univs=let{Info.scope;hook}=pinfo.Proof_info.infoinList.map_i(funi{CInfo.name;typ;impargs}->letpe={parameter_entry_secctx=sec_vars;parameter_entry_type=Evarutil.nf_evars_universes(Evd.from_ctxuctx)typ;parameter_entry_universes=univs;parameter_entry_inline_code=None;}indeclare_parameter~name~scope~hook~impargs~uctxpe)0pinfo.Proof_info.cinfoend(************************************************************************)(* Admitting a lemma-like constant *)(************************************************************************)(* Admitted *)let{Goptions.get=get_keep_admitted_vars}=Goptions.declare_bool_option_and_ref~key:["Keep";"Admitted";"Variables"]~value:true()letcompute_proof_using_for_admittedprooftypiproof=ifnot(get_keep_admitted_vars())||not(Lib.sections_are_opened())thenNoneelsematchget_used_variablesproofwith|Some_asx->x|None->matchProof.partial_proofiproofwith|pproof::_->letenv=Global.env()inletsigma=(Proof.dataiproof).Proof.sigmainletids_typ=Termops.global_vars_setenvsigmatypin(* [pproof] is evar-normalized by [partial_proof]. We don't
count variables appearing only in the type of evars. *)letids_def=Termops.global_vars_setenvsigmapproofinSome(Environ.really_neededenv(Id.Set.unionids_typids_def))|[]->Noneletfinish_admitted~pm~pinfo~uctx~sec_vars~univs=(* If the constant was an obligation we need to update the program map *)matchCEphemeron.defaultpinfo.Proof_info.proof_endingProof_ending.Regularwith|Proof_ending.End_obligationoinfo->letdeclare_fun~uctx~sec_vars~univs=matchMutualEntry.declare_possibly_mutual_parameters~pinfo~uctx~sec_vars~univswith|[GlobRef.ConstRefcst]->cst|_->assertfalseinlettyp=Evarutil.nf_evars_universes(Evd.from_ctxuctx)(List.hdpinfo.Proof_info.cinfo).CInfo.typinObls_.obligation_admitted_terminator~pmtypoinfodeclare_funuctx|_->let_cst=MutualEntry.declare_possibly_mutual_parameters~pinfo~uctx~sec_vars~univsinpmletsave_admitted~pm~proof=letudecl=get_universe_declproofinletProof.{poly;entry}=Proof.data(getproof)inlettyp=matchProofview.initial_goalsentrywith|[_,_,typ]->typ|_->CErrors.anomaly~label:"Lemmas.save_lemma_admitted"(Pp.str"more than one statement.")inletiproof=getproofinletsec_vars=compute_proof_using_for_admittedprooftypiproofinletuctx=get_initial_euctxproofinletunivs=UState.check_univ_decl~polyuctxudeclinfinish_admitted~pm~pinfo:proof.pinfo~uctx~sec_vars~univs(************************************************************************)(* Saving a lemma-like constant *)(************************************************************************)letfinish_derived~f~name~entries=(* [f] and [name] correspond to the proof of [f] and of [suchthat], respectively. *)letf_def,lemma_def=matchentrieswith|[_;f_def;lemma_def]->f_def,lemma_def|_->assertfalsein(* The opacity of [f_def] is adjusted to be [false], as it
must. Then [f] is declared in the global environment. *)letf_def=Internal.set_opacity~opaque:falsef_definletf_kind=Decls.(IsDefinitionDefinition)inletf_def=DefinitionEntryf_definletf_kn=declare_constant~name:f~kind:f_kindf_def~typing_flags:Nonein(* Derive does not support univ poly *)let()=assert(not(Global.is_polymorphic(ConstReff_kn)))inletf_kn_term=Constr.UnsafeMonomorphic.mkConstf_knin(* In the type and body of the proof of [suchthat] there can be
references to the variable [f]. It needs to be replaced by
references to the constant [f] declared above. This substitution
performs this precise action. *)letsubstfc=Vars.replace_vars[f,f_kn_term]cin(* Extracts the type of the proof of [suchthat]. *)letlemma_pretypetyp=matchtypwith|Somet->Some(substft)|None->assertfalse(* Declare always sets type here. *)in(* The references of [f] are subsituted appropriately. *)letlemma_def=Internal.map_entry_typelemma_def~f:lemma_pretypein(* The same is done in the body of the proof. *)letlemma_def=Internal.map_entry_bodylemma_def~f:(fun((b,ctx),fx)->(substfb,ctx),fx)inletlemma_def=DefinitionEntrylemma_definletct=declare_constant~name~typing_flags:None~kind:Decls.(IsProofProposition)lemma_defin[GlobRef.ConstReff_kn;GlobRef.ConstRefct]letfinish_proved_equations~pm~kind~hookiproof_objtypessigma0=letobls=ref1inletsigma,recobls=CList.fold_left2_map(funsigma(_evar_env,ev,_evi,local_context,_type)entry->letid=matchEvd.evar_identevsigma0with|Someid->id|None->letn=!oblsinincrobls;Nameops.add_suffixi("_obligation_"^string_of_intn)inletentry=Internal.pmap_entry_body~f:Future.forceentryinletentry,args=Internal.shrink_entrylocal_contextentryinletentry=Internal.pmap_entry_body~f:Future.from_valentryinletcst=declare_constant~name:id~kind~typing_flags:None(DefinitionEntryentry)inletsigma,app=Evd.fresh_global(Global.env())sigma(GlobRef.ConstRefcst)inletsigma=Evd.defineev(EConstr.applist(app,List.mapEConstr.of_constrargs))sigmainsigma,cst)sigma0typesproof_obj.entriesinletpm=hook~pmrecoblssigmainpm,List.map(funcst->GlobRef.ConstRefcst)recoblsletcheck_single_entry{entries;uctx}label=matchentrieswith|[entry]->entry,uctx|_->CErrors.anomaly~labelPp.(str"close_proof returned more than one proof term")letfinish_proof~pmproof_objproof_info=letopenProof_endinginmatchCEphemeron.defaultproof_info.Proof_info.proof_endingRegularwith|Regular->letentry,uctx=check_single_entryproof_obj"Proof.save"inpm,MutualEntry.declare_possibly_mutual_definitions~entry~uctx~pinfo:proof_info|End_obligationoinfo->letentry,uctx=check_single_entryproof_obj"Obligation.save"inletentry=Internal.pmap_entry_body~f:Future.forceentryinObls_.obligation_terminator~pm~entry~uctx~oinfo|End_derive{f;name}->pm,finish_derived~f~name~entries:proof_obj.entries|End_equations{hook;i;types;sigma}->letkind=proof_info.Proof_info.info.Info.kindinfinish_proved_equations~pm~kind~hookiproof_objtypessigmaleterr_save_forbidden_in_place_of_qed()=CErrors.user_err(Pp.str"Cannot use Save with more than one constant or in this proof mode")letprocess_idopt_for_save~idoptinfo=matchidoptwith|None->info|Some{CAst.v=save_name}->(* Save foo was used; we override the info in the first theorem *)letcinfo=matchinfo.Proof_info.cinfo,CEphemeron.defaultinfo.Proof_info.proof_endingProof_ending.Regularwith|[{CInfo.name;_}asdecl],Proof_ending.Regular->[{declwithCInfo.name=save_name}]|_->err_save_forbidden_in_place_of_qed()in{infowithProof_info.cinfo}letsave~pm~proof~opaque~idopt=(* Env and sigma are just used for error printing in save_remaining_recthms *)letproof_obj=close_proof~opaque~keep_body_ucst_separate:falseproofinletproof_info=process_idopt_for_save~idoptproof.pinfoinfinish_proof~pmproof_objproof_infoletsave_regular~(proof:t)~opaque~idopt=letopenProof_endinginmatchCEphemeron.defaultproof.pinfo.Proof_info.proof_endingRegularwith|Regular->let(_,grs):Obls_.State.t*_=save~pm:Obls_.State.empty~proof~opaque~idoptingrs|_->CErrors.anomalyPp.(str"save_regular: unexpected proof ending")(***********************************************************************)(* Special case to close a lemma without forcing a proof *)(***********************************************************************)letsave_lemma_admitted_delayed~pm~proof=let{entries;uctx;pinfo}=proofinifList.lengthentries<>1thenCErrors.user_errPp.(str"Admitted does not support multiple statements");let{proof_entry_secctx;proof_entry_type;proof_entry_universes}=List.hdentriesinletpoly=matchfst(proof_entry_universes)with|UState.Monomorphic_entry_->false|UState.Polymorphic_entry_->trueinletunivs=UState.univ_entry~polyuctxinletsec_vars=ifget_keep_admitted_vars()thenproof_entry_secctxelseNoneinfinish_admitted~pm~uctx~pinfo~sec_vars~univsletsave_lemma_proved_delayed~pm~proof~idopt=(* vio2vo used to call this with invalid [pinfo], now it should work fine. *)letpinfo=process_idopt_for_save~idoptproof.pinfoinletpm,_=finish_proof~pmproofpinfoinpmend(* Proof module *)let_=Ind_tables.declare_definition_scheme:=declare_definition_schemelet_=Abstract.declare_abstract:=Proof.declare_abstractletbuild_by_tactic=Proof.build_by_tactic(* This module could be merged with Obl, and placed before [Proof],
however there is a single dependency on [Proof.start] for the interactive case *)moduleObls=struct(* For the records fields, opens should go away one these types are private *)openObls_openObls_.ObligationopenObls_.ProgramDeclletreducec=letenv=Global.env()inletsigma=Evd.from_envenvinEConstr.Unsafe.to_constr(Reductionops.clos_norm_flagsRedFlags.betaiotaenvsigma(EConstr.of_constrc))letexplain_no_obligations=functionSomeident->str"No obligations for program "++Id.printident|None->str"No obligations remaining"moduleError=structletno_obligationsn=CErrors.user_err(explain_no_obligationsn)letambiguous_programidids=CErrors.user_errPp.(str"More than one program with unsolved obligations: "++prlistId.printids++str"; use the \"of\" clause to specify, as in \"Obligation 1 of "++Id.printid++str"\"")letunknown_obligationnum=CErrors.user_err(Pp.str(Printf.sprintf"Unknown obligation number %i"(succnum)))letalready_solvednum=CErrors.user_errPp.(str"Obligation "++intnum++str" already solved.")letdependsnumrem=CErrors.user_err(str"Obligation "++intnum++str" depends on obligation(s) "++pr_sequence(funx->int(succx))rem)endletdefault_tactic=ref(Proofview.tclUNIT())letsubst_depsexpandoblsdepst=letosubst=Obls_.obl_substitutionexpandoblsdepsin(Vars.replace_vars(List.map(fun(n,(_,b))->n,b)osubst)t)letsubst_deps_obloblsobl=lett'=subst_depstrueoblsobl.obl_depsobl.obl_typeinObligation.set_type~typ:t'oblletis_definedoblsx=not(Option.is_emptyobls.(x).obl_body)letdeps_remainingoblsdeps=Int.Set.fold(funxacc->ifis_definedoblsxthenaccelsex::acc)deps[]letgoal_kind=Decls.(IsDefinitionDefinition)letgoal_proof_kind=Decls.(IsProofLemma)letkind_of_obligationo=matchowith|Evar_kinds.Definefalse|Evar_kinds.Expand->goal_kind|_->goal_proof_kind(* Solve an obligation using tactics, return the corresponding proof term *)letwarn_solve_errored=CWarnings.create~name:"solve_obligation_error"~category:CWarnings.CoreCategories.tactics(funerr->Pp.seq[str"Solve Obligations tactic returned error: ";err;fnl();str"This will become an error in the future"])letsolve_by_tacprgoblsitac=letobl=obls.(i)inletobl=subst_deps_obloblsoblinlettac=Option.(default!default_tactic(appendtacobl.obl_tac))inletuctx=Internal.get_uctxprginletuctx=UState.update_sigma_univsuctx(Global.universes())inletpoly=Internal.get_polyprgin(* the status of [build_by_tactic] is dropped. *)tryletenv=Global.env()inletbody,types,_univs,_,uctx=build_by_tacticenv~uctx~poly~typ:(EConstr.of_constrobl.obl_type)tacinInductiveops.control_only_guardenv(Evd.from_ctxuctx)(EConstr.of_constrbody);Some(body,types,uctx)with|Tacticals.FailError(_,s)asexn->let_=Exninfo.captureexninletloc=fstobl.obl_locationinCErrors.user_err?loc(Lazy.forces)(* If the proof is open we absorb the error and leave the obligation open *)|Proof.OpenProof_->None|ewhenCErrors.noncriticale->leterr=CErrors.printeinletloc=fstobl.obl_locationinwarn_solve_errored?locerr;Noneletsolve_and_declare_by_tacprgoblsitac=matchsolve_by_tacprgoblsitacwith|None->None|Some(t,ty,uctx)->letobl=obls.(i)inletprg,obl',_cst=declare_obligationprgobl~body:t~types:ty~uctxinobls.(i)<-obl';Someprgletsolve_obligation_by_tacprgoblsitac=letobl=obls.(i)inmatchobl.obl_bodywith|Some_->None|None->ifList.is_empty(deps_remainingoblsobl.obl_deps)thensolve_and_declare_by_tacprgoblsitacelseNoneletget_unique_prog~pmprg=matchState.get_unique_open_progpmprgwith|Okprg->prg|Error[]->Error.no_obligationsNone|Error((id::_)asids)->Error.ambiguous_programididsletsolve_prg_obligations~pmprg?oblsettac=let{obls;remaining}=Internal.get_obligationsprginletrem=refremaininginletobls'=Array.copyoblsinletset=refInt.Set.emptyinletp=matchoblsetwith|None->(fun_->true)|Somes->set:=s;(funi->Int.Set.memi!set)inletprg=Array.fold_left_i(funiprgx->ifpithen(matchsolve_obligation_by_tacprgobls'itacwith|None->prg|Someprg->letdeps=dependenciesoblsiinset:=Int.Set.union!setdeps;decrrem;prg)elseprg)prgobls'inupdate_obls~pmprgobls'!remletauto_solve_obligations~pmn?oblsettac:State.t*progress=Flags.if_verboseFeedback.msg_info(str"Solving obligations automatically...");letprg=get_unique_prog~pmninsolve_prg_obligations~pmprg?oblsettacletsolve_obligation?check_finalprgnumtac=letuser_num=succnuminlet{obls;remaining=rem}=Internal.get_obligationsprginletobl=obls.(num)inletremaining=deps_remainingoblsobl.obl_depsinlet()=ifnot(Option.is_emptyobl.obl_body)thenError.already_solveduser_num;ifnot(List.is_emptyremaining)thenError.dependsuser_numremaininginletobl=subst_deps_obloblsoblinletkind=kind_of_obligation(sndobl.obl_status)inletevd=Evd.from_ctx(Internal.get_uctxprg)inletevd=Evd.update_sigma_univs(Global.universes())evdinletauto~pmnoblsettac=auto_solve_obligations~pmn~oblsettacinletproof_ending=letname=Internal.get_nameprginProof_ending.End_obligation{name;num;auto;check_final}inletcinfo=CInfo.make~name:obl.obl_name~typ:(EConstr.of_constrobl.obl_type)()inletusing=letusing=Internal.get_usingprginletenv=Global.env()inletf{CInfo.name;typ;_}=name,[typ]inOption.map(interp_proof_using_genfenvevd[cinfo])usinginletpoly=Internal.get_polyprginletinfo=Info.make~kind~poly()inletlemma=Proof.start_core~cinfo~info~proof_ending?usingevdinletlemma=fst@@Proof.by!default_tacticlemmainletlemma=Option.cata(funtac->Proof.set_endline_tactictaclemma)lemmatacinlemmaletsolve_obligations~pmntac=letprg=get_unique_prog~pmninsolve_prg_obligations~pmprgtacletsolve_all_obligations~pmtac=State.foldpm~init:pm~f:(funkvpm->solve_prg_obligations~pmvtac|>fst)lettry_solve_obligations~pmntac=solve_obligations~pmntac|>fstletobligation(user_num,name,typ)~pmtac=letnum=preduser_numinletprg=get_unique_prog~pmnameinlet{obls;remaining}=Internal.get_obligationsprginifnum>=0&&num<Array.lengthoblsthenletobl=obls.(num)inmatchobl.obl_bodywith|None->solve_obligationprgnumtac|Somer->Error.already_solveduser_numelseError.unknown_obligationnumletshow_single_obligationinoblsx=letx=subst_deps_obloblsxinletenv=Global.env()inletsigma=Evd.from_envenvinletmsg=str"Obligation"++spc()++int(succi)++spc()++str"of"++spc()++Id.printn++str":"++spc()++hov1(Printer.pr_constr_envenvsigmax.obl_type++str"."++fnl())inFeedback.msg_infomsgletshow_obligations_of_prg?(msg=true)prg=letn=Internal.get_nameprginlet{obls;remaining}=Internal.get_obligationsprginletshowed=ref5inifmsgthenFeedback.msg_info(intremaining++str" obligation(s) remaining: ");Array.iteri(funix->matchx.obl_bodywith|None->if!showed>0thenbegindecrshowed;show_single_obligationinoblsxend|Some_->())oblsletshow_obligations~pm?(msg=true)n=letprogs=matchnwith|None->State.allpm|Somen->(matchState.findpmnwith|Someprg->[prg]|None->Error.no_obligations(Somen))inList.iter(funx->show_obligations_of_prg~msgx)progsletshow_term~pmn=letprg=get_unique_prog~pmninProgramDecl.showprgletmsg_generating_oblnameobls=letlen=Array.lengthoblsinletinfo=Id.printname++str" has type-checked"inFeedback.msg_info(iflen=0theninfo++str"."elseinfo++str", generating "++intlen++str(String.plurallen" obligation"))letadd_definition~pm~info~cinfo~opaque~uctx?body?tactic?(reduce=reduce)?using?obl_hookobls=letobl_hook=Option.map(funh->State.PrgHookh)obl_hookinletprg=ProgramDecl.make~info~cinfo~body~opaque~uctx~reduce~deps:[]~possible_guard:None?obl_hook?usingoblsinletname=CInfo.get_namecinfoinlet{obls;_}=Internal.get_obligationsprginifInt.equal(Array.lengthobls)0then(Flags.if_verbose(msg_generating_oblname)obls;letpm,cst=Obls_.declare_definition~pmprginpm,Definedcst)elselet()=Flags.if_verbose(msg_generating_oblname)oblsinletpm=State.addpmnameprginletpm,res=auto_solve_obligations~pm(Somename)tacticinmatchreswith|Remainrem->Flags.if_verbose(show_obligations~pm~msg:false)(Somename);pm,res|_->pm,resletadd_mutual_definitions~pm~info~cinfo~opaque~uctx~bodies~possible_guard?tactic?(reduce=reduce)?using?obl_hookobls=letobl_hook=Option.map(funh->State.PrgHookh)obl_hookinletdeps=List.mapCInfo.get_namecinfoinletpm=List.fold_left3(funpmcinfobodyobls->letprg=ProgramDecl.make~info~cinfo~opaque~body:(Somebody)~uctx~deps~possible_guard:(Somepossible_guard)~reduce?obl_hook?usingoblsinState.addpm(CInfo.get_namecinfo)prg)pmcinfobodiesoblsinletpm,_defined=List.fold_left(fun(pm,finished)x->iffinishedthen(pm,finished)elseletpm,res=auto_solve_obligations~pm(Somex)tacticinmatchreswith|Defined_->(* If one definition is turned into a constant,
the whole block is defined. *)(pm,true)|_->(pm,false))(pm,false)depsinpmletrecadmit_prog~pmprg=let{obls}=Internal.get_obligationsprginletis_open_x=Option.is_emptyx.obl_body&&List.is_empty(deps_remainingoblsx.obl_deps)inleti=matchArray.findiis_openoblswith|Somei->i|None->CErrors.anomaly(Pp.str"Could not find a solvable obligation.")inletproof=solve_obligationprgiNoneinletpm=Proof.save_admitted~pm~proofinmatchProgMap.find_opt(Internal.get_nameprg)pmwith|Someprg->admit_prog~pm(CEphemeron.getprg)|None->pmletrecadmit_all_obligations~pm=letprg=State.first_pendingpminmatchprgwith|None->pm|Someprg->letpm=admit_prog~pmprginadmit_all_obligations~pmletadmit_obligations~pmn=matchnwith|None->admit_all_obligations~pm|Some_->letprg=get_unique_prog~pmninletpm=admit_prog~pmprginpmletnext_obligation~pm?(final=false)ntac=letprg=matchnwith|None->beginmatchState.first_pendingpmwith|Someprg->prg|None->Error.no_obligationsNoneend|Some_->get_unique_prog~pmninlet{obls;remaining}=Internal.get_obligationsprginletis_open_x=Option.is_emptyx.obl_body&&List.is_empty(deps_remainingoblsx.obl_deps)inleti=matchArray.findiis_openoblswith|Somei->i|None->matchnwith|None->CErrors.anomaly(Pp.str"Could not find a solvable obligation.")|Somen->CErrors.user_err(str"No more obligations for "++Id.printn++str".")inletcheck_final=ifnotfinalthenNoneelsematchnwith|None->SomeAllFinal|Somen->Some(SpecificFinaln)insolve_obligation?check_finalprgitacletcheck_program_libraries()=Coqlib.check_required_libraryCoqlib.datatypes_module_name;Coqlib.check_required_library["Coq";"Init";"Specif"](* aliases *)letprepare_obligations=prepare_obligationsletcheck_solved_obligations=letis_emptyprg=letobls=(Internal.get_obligations(CEphemeron.getprg)).oblsinletis_openx=Option.is_emptyx.obl_body&&List.is_empty(deps_remainingoblsx.obl_deps)inArray.existsis_openoblsinObls_.check_solved_obligationsis_emptytypefixpoint_kind=Obls_.fixpoint_kind=|IsFixpointoflidentoptionlist|IsCoFixpointtypenonrecprogress=progress=|Remainofint|Dependent|DefinedofGlobRef.tendmoduleOblState=Obls_.Stateletdeclare_constant?local~name~kind?typing_flags=declare_constant?local~name~kind~typing_flagsletdeclare_entry~name?scope~kind?user_warns=declare_entry~name?scope~kind~typing_flags:None?clearbody:None~user_warns