123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619(************************************************************************)(* * 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) *)(************************************************************************)(*i*)openNamesopenEConstropenCErrorsopenUtilopenTypeclasses_errorsopenTypeclassesopenLibnamesopenGlobnamesopenConstrinternopenConstrexpropenContext.Rel.DeclarationopenClass_tacticsopenLibobjectmoduleRelDecl=Context.Rel.Declaration(*i*)letset_typeclass_transparency~localitycb=Hints.add_hints~locality[typeclasses_db](Hints.HintsTransparencyEntry(Hints.HintsReferencesc,b))letwarn_deprecated_tc_transparency_without_locality=CWarnings.create~name:"deprecated-typeclasses-transparency-without-locality"~category:Deprecation.Version.v8_15Pp.(fun()->strbrk"The default value for Typeclasses Opaque and Typeclasses \
Transparent locality is currently \"local\" in a section and \
\"global\" otherwise, but is scheduled to change in a future \
release. For the time being, adding typeclass transparency hints outside of \
sections without specifying an explicit locality attribute is \
therefore deprecated. It is recommended to use \"export\" whenever \
possible. Use the attributes #[local], #[global] and #[export] \
depending on your choice. For example: \"#[export] Typeclasses Transparent foo.\". \
This is supported since Coq 8.15.")letdefault_tc_transparency_locality()=ifLib.sections_are_opened()thenHints.Localelselet()=warn_deprecated_tc_transparency_without_locality()inHints.SuperGloballettc_transparency_locality=Attributes.hint_locality~default:default_tc_transparency_localityletset_typeclass_transparency_com~localityrefsb=letrefs=List.map(funx->Tacred.evaluable_of_global_reference(Global.env())(Smartlocate.global_with_aliasx))refsinset_typeclass_transparency~localityrefsbletadd_instance_hintinstpath~localityinfo=Flags.silently(fun()->Hints.add_hints~locality[typeclasses_db](Hints.HintsResolveEntry[info,false,Hints.PathHintspath,inst]))()(* short names without opening all Hints *)typelocality=Hints.hint_locality=Local|Export|SuperGlobaltypeinstance={class_name:GlobRef.t;instance:GlobRef.t;info:Typeclasses.hint_info;(* Sections where the instance should be redeclared,
None for discard, Some 0 for none. *)locality:Hints.hint_locality;}letadd_instance_baseinst=letlocality=matchinst.localitywith|Local->Local|SuperGlobal->(* i.e. in a section, declare the hint as local since discharge is managed
by rebuild_instance which calls again add_instance_hint; don't ask hints
to take discharge into account itself *)ifLib.sections_are_opened()thenLocalelseSuperGlobal|Export->(* Same as above for export *)ifLib.sections_are_opened()thenLocalelseExportinadd_instance_hint(Hints.hint_globrefinst.instance)[inst.instance]~localityinst.info(*
* instances persistent object
*)letperform_instancei=leti={is_class=i.class_name;is_info=i.info;is_impl=i.instance}inTypeclasses.load_instanceiletcache_instanceinst=perform_instanceinst;add_instance_baseinstletload_instance_inst=matchinst.localitywith|Local->assertfalse|SuperGlobal->perform_instanceinst|Export->()letopen_instanceiinst=matchinst.localitywith|Local->assertfalse|SuperGlobal->perform_instanceinst|Export->ifInt.equali1thenperform_instanceinstletsubst_instance(subst,inst)={instwithclass_name=fst(subst_globalsubstinst.class_name);instance=fst(subst_globalsubstinst.instance)}letdischarge_instanceinst=matchinst.localitywith|Local->None|SuperGlobal|Export->assert(not(isVarRefinst.instance));Someinstletclassify_instanceinst=matchinst.localitywith|Local->Dispose|SuperGlobal|Export->Substituteletinstance_input:instance->obj=declare_object{(default_object"type classes instances state")withcache_function=cache_instance;load_function=load_instance;open_function=simple_open~cat:Hints.hint_catopen_instance;classify_function=classify_instance;discharge_function=discharge_instance;subst_function=subst_instance}letdefault_locality()=ifLib.sections_are_opened()thenLocalelseExportletinstance_locality=Attributes.hint_locality~default:default_localitymoduleEvent=structtypet=|NewClassoftypeclass|NewInstanceofinstanceendtypeobserver=stringletobservers=refCString.Map.emptyletactive_observers=Summary.ref~name:"active typeclass observers"[]letregister_observer~name?(override=false)o=ifnotoverride&&CString.Map.memname!observersthenCErrors.anomalyPp.(str"Typeclass observer "++strname++str" already registered.");observers:=CString.Map.addnameo!observers;nameletdeactivate_observername=active_observers:=List.removeString.equalname!active_observersletactivate_observername=assert(CString.Map.memname!observers);deactivate_observername;active_observers:=name::!active_observersletobserveevent=List.iter(funname->(CString.Map.getname!observers)event)!active_observersletadd_instanceclinfoglobalimpl=let()=matchglobalwith|Local->()|SuperGlobal->ifLib.sections_are_opened()&&isVarRefimplthenCErrors.user_err(Pp.str"Cannot set Global an instance referring to a section variable.")|Export->ifLib.sections_are_opened()&&isVarRefimplthenCErrors.user_err(Pp.str"The export attribute cannot be applied to an instance referring to a section variable.")inleti={class_name=cl.cl_impl;info=info;locality=global;instance=impl;}inLib.add_leaf(instance_inputi);observe(Event.NewInstance{class_name=cl.cl_impl;instance=impl;info;locality=global})letwarning_not_a_class=CWarnings.create~name:"not-a-class"(fun(n,ty)->letenv=Global.env()inletevd=Evd.from_envenvinPp.(str"Ignored instance declaration for “"++Nametab.pr_global_envId.Set.emptyn++str"”: “"++Termops.Internal.print_constr_envenvevd(EConstr.of_constrty)++str"” is not a class"))letdeclare_instance?(warn=false)envsigmainfolocalglob=letty,_=Typeops.type_of_global_in_contextenvglobinletinfo=Option.default{hint_priority=None;hint_pattern=None}infoinmatchclass_of_constrenvsigma(EConstr.of_constrty)with|Some(rels,((tc,_),args)as_cl)->add_instancetcinfolocalglob|None->ifwarnthenwarning_not_a_class(glob,ty)(*
* classes persistent object
*)letcache_classc=load_classcletsubst_class(subst,cl)=letdo_subst_conc=Mod_subst.subst_constantsubstcanddo_substc=Mod_subst.subst_mpssubstcanddo_subst_grgr=fst(subst_globalsubstgr)inletdo_subst_ctx=List.Smart.map(RelDecl.map_constrdo_subst)inletdo_subst_methm=letc=Option.Smart.mapdo_subst_conm.meth_constinifc==m.meth_constthenmelse{meth_name=m.meth_name;meth_info=m.meth_info;meth_const=c;}inletdo_subst_projsprojs=List.Smart.mapdo_subst_methprojsin{cl_univs=cl.cl_univs;cl_impl=do_subst_grcl.cl_impl;cl_context=do_subst_ctxcl.cl_context;cl_props=do_subst_ctxcl.cl_props;cl_projs=do_subst_projscl.cl_projs;cl_strict=cl.cl_strict;cl_unique=cl.cl_unique}letdischarge_classcl=tryletinfo=Lib.section_segment_of_referencecl.cl_implinletinfo,_,cl_univs'=Cooking.lift_poly_univsinfocl.cl_univsinletnprops=List.lengthcl.cl_propsinletprops,context=List.chopnprops(Discharge.cook_rel_contextinfo(cl.cl_props@cl.cl_context))inletdischarge_projx=xin{cl_univs=cl_univs';cl_impl=cl.cl_impl;cl_context=context;cl_props=props;cl_projs=List.Smart.mapdischarge_projcl.cl_projs;cl_strict=cl.cl_strict;cl_unique=cl.cl_unique}withNot_found->(* not defined in the current section *)clletrebuild_classcl=tryletcst=Tacred.evaluable_of_global_reference(Global.env())cl.cl_implinset_typeclass_transparency~locality:Hints.Local[cst]false;clwithewhenCErrors.noncriticale->clletclass_input:typeclass->obj=declare_object{(default_object"type classes state")withcache_function=cache_class;load_function=(fun_->cache_class);classify_function=(funx->Substitute);discharge_function=(funa->Some(discharge_classa));rebuild_function=rebuild_class;subst_function=subst_class}letadd_classcl=Lib.add_leaf(class_inputcl);observe(Event.NewClasscl)letintern_info{hint_priority;hint_pattern}=letenv=Global.env()inletsigma=Evd.from_envenvinlethint_pattern=Option.map(Constrintern.intern_constr_patternenvsigma)hint_patternin{hint_priority;hint_pattern}(** TODO: add subinstances *)letexisting_instance?locglobcinfo=letinfo=Option.defaultHints.empty_hint_infoinfoinletinfo=intern_infoinfoinletenv=Global.env()inletsigma=Evd.from_envenvinletinstance,_=Typeops.type_of_global_in_contextenvcinletctx,r=Term.decompose_prod_declsinstanceinmatchclass_of_constr(Environ.push_rel_contextctxenv)sigma(EConstr.of_constrr)with|Some(_,((tc,u),_))->add_instancetcinfoglobc|None->user_err?loc(Pp.str"Constant does not build instances of a declared type class.")(* Declare everything in the parameters as implicit, and the class instance as well *)lettype_ctx_instance~program_modeenvsigmactxinstsubst=letopenVarsinletrecaux(sigma,subst,instctx)l=functiondecl::ctx->lett'=substlsubst(RelDecl.get_typedecl)inlet(sigma,c'),l=matchdeclwith|LocalAssum_->interp_casted_constr_evars~program_modeenvsigma(List.hdl)t',List.tll|LocalDef(_,b,_)->(sigma,substlsubstb),linletd=RelDecl.get_namedecl,Somec',t'inaux(sigma,c'::subst,d::instctx)lctx|[]->sigma,substinaux(sigma,subst,[])inst(List.revctx)letid_of_classcl=letopenGlobRefinmatchcl.cl_implwith|ConstRefkn->Label.to_id@@Constant.labelkn|IndRef(kn,i)->letmip=(Environ.lookup_mindkn(Global.env())).Declarations.mind_packetsinmip.(0).Declarations.mind_typename|_->assertfalseletinstance_hookinfoglobal?hookcst=letinfo=intern_infoinfoinletenv=Global.env()inletsigma=Evd.from_envenvindeclare_instanceenvsigma(Someinfo)globalcst;(matchhookwithSomeh->hcst|None->())letdeclare_instance_constantiinfoglobalimpargs?hooknameudeclpolysigmatermtermtype=letkind=Decls.(IsDefinitionInstance)inletcinfo=Declare.CInfo.make~name~impargs~typ:(Sometermtype)()inletinfo=Declare.Info.make~kind~poly~udecl()inletkn=Declare.declare_definition~cinfo~info~opaque:false~body:termsigmaininstance_hookiinfoglobal?hookknletdo_declare_instancesigma~locality~polykuctxctx'priudeclimpargssubstname=letsubst=List.fold_left2(funsubst'sdecl->ifis_local_assumdeclthens::subst'elsesubst')[]substk.cl_contextinlet(_,ty_constr)=instance_constructor(k,u)substinlettermtype=it_mkProd_or_LetInty_constr(ctx'@ctx)inletsigma,entry=Declare.prepare_parameter~polysigma~udecl~types:termtypeinletcst=Declare.declare_constant~name~kind:Decls.(IsAssumptionLogical)(Declare.ParameterEntryentry)inletcst=(GlobRef.ConstRefcst)inImpargs.maybe_declare_manual_implicitsfalsecstimpargs;instance_hookprilocalitycstletdeclare_instance_programpmenvsigma~locality~polynamepriimpargsudecltermtermtype=lethook{Declare.Hook.S.scope;dref;_}=letcst=matchdrefwithGlobRef.ConstRefkn->kn|_->assertfalseinletpri=intern_infopriinletenv=Global.env()inletsigma=Evd.from_envenvindeclare_instanceenvsigma(Somepri)locality(GlobRef.ConstRefcst)inletobls,_,term,typ=RetrieveObl.retrieve_obligationsenvnamesigma0termtermtypeinlethook=Declare.Hook.makehookinletuctx=Evd.evar_universe_contextsigmainletkind=Decls.IsDefinitionDecls.Instanceinletcinfo=Declare.CInfo.make~name~typ~impargs()inletinfo=Declare.Info.make~udecl~poly~kind~hook()inletpm,_=Declare.Obls.add_definition~pm~cinfo~info~term~uctxoblsinpmletdeclare_instance_opensigma?hook~tac~locality~polyidpriimpargsudeclidstermtermtype=(* spiwack: it is hard to reorder the actions to do
the pretyping after the proof has opened. As a
consequence, we use the low-level primitives to code
the refinement manually.*)letfuture_goals,sigma=Evd.pop_future_goalssigmainletgls=List.rev(Evd.FutureGoals.combfuture_goals)inletsigma=Evd.push_future_goalssigmainletkind=Decls.(IsDefinitionInstance)inlethook=Declare.Hook.(make(fun{S.dref;_}->instance_hookprilocality?hookdref))inletinfo=Declare.Info.make~hook~kind~udecl~poly()in(* XXX: We need to normalize the type, otherwise Admitted / Qed will fails!
This is due to a bug in proof_global :( *)lettermtype=Evarutil.nf_evarsigmatermtypeinletcinfo=Declare.CInfo.make~name:id~impargs~typ:termtype()inletlemma=Declare.Proof.start~cinfo~infosigmain(* spiwack: I don't know what to do with the status here. *)letlemma=matchtermwith|Someterm->letinit_refine=Tacticals.tclTHENLIST[Refine.refine~typecheck:false(funsigma->sigma,term);Proofview.Unsafe.tclNEWGOALS(CList.mapProofview.with_empty_stategls);Tactics.reduce_after_refine;]inletlemma,_=Declare.Proof.byinit_refinelemmainlemma|None->letlemma,_=Declare.Proof.by(Tactics.auto_intros_tacids)lemmainlemmainmatchtacwith|Sometac->letlemma,_=Declare.Proof.bytaclemmainlemma|None->lemmaletdo_instance_subst_constructor_and_tysubstkuctx=letsubst=List.fold_left2(funsubst'sdecl->ifis_local_assumdeclthens::subst'elsesubst')[]subst(k.cl_props@k.cl_context)inlet(app,ty_constr)=instance_constructor(k,u)substinlettermtype=it_mkProd_or_LetInty_constrctxinletterm=it_mkLambda_or_LetIn(Option.getapp)ctxinterm,termtypeletdo_instance_resolve_TCtermtypesigmaenv=letsigma=Evarutil.nf_evar_mapsigmainletsigma=Typeclasses.resolve_typeclasses~filter:Typeclasses.no_goals_or_obligations~fail:trueenvsigmain(* Try resolving fields that are typeclasses automatically. *)letsigma=Typeclasses.resolve_typeclasses~filter:Typeclasses.all_evars~fail:falseenvsigmainletsigma=Evarutil.nf_evar_map_undefinedsigmain(* Beware of this step, it is required as to minimize universes. *)letsigma=Evd.minimize_universessigmain(* Check that the type is free of evars now. *)Pretyping.check_evarsenvsigmatermtype;termtype,sigmaletdo_instance_type_ctx_instancepropskenv'ctx'sigma~program_modesubst=letget_idqid=CAst.make?loc:qid.CAst.loc@@qualid_basenameqidinletprops,rest=List.fold_left(fun(props,rest)decl->ifis_local_assumdeclthentryletis_id(id',_)=matchRelDecl.get_namedecl,get_idid'with|Nameid,{CAst.v=id'}->Id.equalidid'|Anonymous,_->falseinlet(loc_mid,c)=List.findis_idrestinletrest'=List.filter(funv->not(is_idv))restinlet{CAst.loc;v=mid}=get_idloc_midinList.iter(funm->ifName.equalm.meth_name(Namemid)thenOption.iter(funx->Dumpglob.add_glob?loc(GlobRef.ConstRefx))m.meth_const)k.cl_projs;c::props,rest'withNot_found->((CAst.make@@CHole(None(* Some Evar_kinds.GoalEvar *),Namegen.IntroAnonymous))::props),restelseprops,rest)([],props)k.cl_propsinmatchrestwith|(n,_)::_->unbound_methodenv'sigmak.cl_impl(get_idn)|_->letkcl_props=List.map(Termops.map_rel_declof_constr)k.cl_propsinletsigma,res=type_ctx_instance~program_mode(push_rel_contextctx'env')sigmakcl_propspropssubstinres,sigmaletinterp_props~program_modeenv'ctykuctxctx'substsigma=function|(true,{CAst.v=CRecordfs;loc})->check_duplicate?locfs;letsubst,sigma=do_instance_type_ctx_instancefskenv'ctx'sigma~program_modesubstinletterm,termtype=do_instance_subst_constructor_and_tysubstku(ctx'@ctx)interm,termtype,sigma|(_,term)->letsigma,def=interp_casted_constr_evars~program_modeenv'sigmatermctyinlettermtype=it_mkProd_or_LetInctyctxinletterm=it_mkLambda_or_LetIndefctxinterm,termtype,sigmaletdo_instance_interactiveenvenv'sigma?hook~tac~locality~polyctykuctxctx'prideclimpssubstidopt_props=letterm,termtype,sigma=matchopt_propswith|Someprops->on_pi1(funx->Somex)(interp_props~program_mode:falseenv'ctykuctxctx'substsigmaprops)|None->letterm,termtype=ifList.is_emptyk.cl_propsthenletterm,termtype=do_instance_subst_constructor_and_tysubstku(ctx'@ctx)inSometerm,termtypeelseNone,it_mkProd_or_LetInctyctxinlettermtype,sigma=do_instance_resolve_TCtermtypesigmaenvinterm,termtype,sigmainFlags.silently(fun()->declare_instance_opensigma?hook~tac~locality~polyidpriimpsdecl(List.mapRelDecl.get_namectx)termtermtype)()letdo_instanceenvenv'sigma?hook~locality~polyctykuctxctx'prideclimpssubstidprops=letterm,termtype,sigma=interp_props~program_mode:falseenv'ctykuctxctx'substsigmapropsinlettermtype,sigma=do_instance_resolve_TCtermtypesigmaenvinPretyping.check_evars_are_solved~program_mode:falseenvsigma;declare_instance_constantprilocalityimps?hookiddeclpolysigmatermtermtypeletdo_instance_program~pmenvenv'sigma?hook~locality~polyctykuctxctx'prideclimpssubstidopt_props=letterm,termtype,sigma=matchopt_propswith|Someprops->interp_props~program_mode:trueenv'ctykuctxctx'substsigmaprops|None->letsubst,sigma=do_instance_type_ctx_instance[]kenv'ctx'sigma~program_mode:truesubstinletterm,termtype=do_instance_subst_constructor_and_tysubstku(ctx'@ctx)interm,termtype,sigmainlettermtype,sigma=do_instance_resolve_TCtermtypesigmaenvinifnot(Evd.has_undefinedsigma)&¬(Option.is_emptyopt_props)thenlet()=declare_instance_constantprilocalityimps?hookiddeclpolysigmatermtermtypeinpmelsedeclare_instance_programpmenvsigma~locality~polyidpriimpsdecltermtermtypeletinterp_instance_context~program_modeenvctxpltclass=letsigma,decl=interp_univ_decl_optenvplinletsigma,(impls,((env',ctx),imps))=interp_context_evars~program_modeenvsigmactxinletflags=Pretyping.{all_no_fail_flagswithprogram_mode}inletsigma,(c',imps')=interp_type_evars_impls~flags~implsenv'sigmatclassinletimps=imps@imps'inletctx',c=decompose_prod_declssigmac'inletctx''=ctx'@ctxinlet(k,u),args=Typeclasses.dest_class_app(push_rel_contextctx''env)sigmacinletu_s=EInstance.kindsigmauinletcl=Typeclasses.typeclass_univ_instance(k,u_s)inletargs=List.mapof_constrargsinletcl_context=List.map(Termops.map_rel_declof_constr)cl.cl_contextinlet_,args=List.fold_right(fundecl(args,args')->matchdeclwith|LocalAssum_->(List.tlargs,List.hdargs::args')|LocalDef(_,b,_)->(args,Vars.substlargs'b::args'))cl_context(args,[])inletsigma=Evarutil.nf_evar_mapsigmainletsigma=resolve_typeclasses~filter:Typeclasses.all_evars~fail:trueenvsigmainsigma,cl,u,c',ctx',ctx,imps,args,declletnew_instance_common~program_modeenvinstidctxcl=let({CAst.loc;v=instid},pl)=instidinletsigma,k,u,cty,ctx',ctx,imps,subst,decl=interp_instance_context~program_modeenvctxplclin(* The name generator should not be here *)letid=matchinstidwith|Nameid->id|Anonymous->leti=Nameops.add_suffix(id_of_classk)"_instance_0"inNamegen.next_global_ident_awayi(Termops.vars_of_envenv)inletenv'=push_rel_contextctxenvinid,env',sigma,k,u,cty,ctx',ctx,imps,subst,declletnew_instance_interactive~locality~polyinstidctxcl?(tac:unitProofview.tacticoption)?hookpriopt_props=letenv=Global.env()inletid,env',sigma,k,u,cty,ctx',ctx,imps,subst,decl=new_instance_common~program_mode:falseenvinstidctxclinid,do_instance_interactiveenvenv'sigma?hook~tac~locality~polyctykuctxctx'prideclimpssubstidopt_propsletnew_instance_program~locality~pm~polyinstidctxclopt_props?hookpri=letenv=Global.env()inletid,env',sigma,k,u,cty,ctx',ctx,imps,subst,decl=new_instance_common~program_mode:trueenvinstidctxclinletpm=do_instance_program~pmenvenv'sigma?hook~locality~polyctykuctxctx'prideclimpssubstidopt_propsinpm,idletnew_instance~locality~polyinstidctxclprops?hookpri=letenv=Global.env()inletid,env',sigma,k,u,cty,ctx',ctx,imps,subst,decl=new_instance_common~program_mode:falseenvinstidctxclindo_instanceenvenv'sigma?hook~locality~polyctykuctxctx'prideclimpssubstidprops;idletdeclare_new_instance~locality~program_mode~polyinstidctxclpri=letenv=Global.env()inlet({CAst.loc;v=instid},pl)=instidinletsigma,k,u,cty,ctx',ctx,imps,subst,decl=interp_instance_context~program_modeenvctxplclindo_declare_instancesigma~locality~polykuctxctx'prideclimpssubstinstidletrefine_att=letopenAttributesinletopenNotationsinattribute_of_list["refine",single_key_parser~name:"refine"~key:"refine"()]>>=function|None->returnfalse|Some()->returntruemoduleInternal=structletadd_instance=add_instanceend