123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864(************************************************************************)(* * 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) *)(************************************************************************)openCErrorsopenPpopenUtilopenNamesopenConstropenGlobnamesopenGlob_termopenDeclarationsopenLibobjectopenEConstropenReductionopsopenConstrexprletwhd_prodenvsigmatyp=letopenCClosureinletinfos=Evarutil.create_clos_infosenvsigmaRedFlags.allinlettab=create_tab()inlettyp=inject(EConstr.Unsafe.to_constrtyp)inlettyp,stk=whd_stackinfostabtyp[]inmatchfterm_oftypwith|FProd(na,c1,c2,e)->letc1=EConstr.of_constr@@term_of_fconstrc1inletc2=EConstr.of_constr@@term_of_fconstr(mk_clos(CClosure.usubs_lifte)c2)inSome(EConstr.of_binder_annotna,c1,c2)|_->NonemoduleNamedDecl=Context.Named.Declaration(*s Flags governing the computation of implicit arguments *)typeimplicits_flags={auto:bool;(* automatic or manual only *)strict:bool;(* true = strict *)strongly_strict:bool;(* true = strongly strict *)reversible_pattern:bool;contextual:bool;(* true = contextual *)maximal:bool}letimplicit_args=ref{auto=false;strict=true;strongly_strict=false;reversible_pattern=false;contextual=false;maximal=false;}letmake_implicit_argsflag=implicit_args:={!implicit_argswithauto=flag}letmake_strict_implicit_argsflag=implicit_args:={!implicit_argswithstrict=flag}letmake_strongly_strict_implicit_argsflag=implicit_args:={!implicit_argswithstrongly_strict=flag}letmake_reversible_pattern_implicit_argsflag=implicit_args:={!implicit_argswithreversible_pattern=flag}letmake_contextual_implicit_argsflag=implicit_args:={!implicit_argswithcontextual=flag}letmake_maximal_implicit_argsflag=implicit_args:={!implicit_argswithmaximal=flag}letis_implicit_args()=!implicit_args.autoletis_strict_implicit_args()=!implicit_args.strictletis_strongly_strict_implicit_args()=!implicit_args.strongly_strictletis_reversible_pattern_implicit_args()=!implicit_args.reversible_patternletis_contextual_implicit_args()=!implicit_args.contextualletis_maximal_implicit_args()=!implicit_args.maximalletwith_implicit_protectionfx=letoflags=!implicit_argsintryletrslt=fxinimplicit_args:=oflags;rsltwithreraise->letreraise=Exninfo.capturereraiseinlet()=implicit_args:=oflagsinExninfo.iraisereraisetypeon_trailing_implicit=Error|Info|Silentletmsg_trailing_implicit(fail:on_trailing_implicit)nai=letpos=matchnawith|Anonymous->"number "^string_of_inti|Nameid->Names.Id.to_stringidinletstr1="Argument "^pos^" is a trailing implicit, "inmatchfailwith|Error->user_err(strbrk(str1^"so it can't be declared non maximal. Please use { } instead of [ ]."))|Info->Flags.if_verboseFeedback.msg_info(strbrk(str1^"so it has been declared maximally inserted."))|Silent->()letset_maximalityfailnaiimpsb=(* Force maximal insertion on ending implicits (compatibility) *)b||(letis_setx=matchxwithNone->false|_->trueinletb'=List.for_allis_setimpsinifb'thenmsg_trailing_implicitfailnai;b')(*s Computation of implicit arguments *)(* We remember various information about why an argument is
inferable as implicit
- [DepRigid] means that the implicit argument can be found by
unification along a rigid path (we do not print the arguments of
this kind if there is enough arguments to infer them)
- [DepFlex] means that the implicit argument can be found by unification
along a collapsible path only (e.g. as x in (P x) where P is another
argument) (we do (defensively) print the arguments of this kind)
- [DepFlexAndRigid] means that the least argument from which the
implicit argument can be inferred is following a collapsible path
but there is a greater argument from where the implicit argument is
inferable following a rigid path (useful to know how to print a
partial application)
- [Manual] means the argument has been explicitly set as implicit.
We also consider arguments inferable from the conclusion but it is
operational only if [conclusion_matters] is true.
*)typeargument_position=|Conclusion|Hypofintletargument_position_eqp1p2=matchp1,p2with|Conclusion,Conclusion->true|Hyph1,Hyph2->Int.equalh1h2|_->falsetypeimplicit_explanation=|DepRigidofargument_position|DepFlexofargument_position|DepFlexAndRigidof(*flex*)argument_position*(*rig*)argument_position|Manualletargument_less=function|Hypn,Hypn'->n<n'|Hyp_,Conclusion->true|Conclusion,_->falseletupdateposrigst=lete=ifrigthenmatchstwith|None->DepRigidpos|Some(DepRigidnasx)->ifargument_less(pos,n)thenDepRigidposelsex|Some(DepFlexAndRigid(fpos,rpos)asx)->ifargument_less(pos,fpos)||argument_position_eqposfposthenDepRigidposelseifargument_less(pos,rpos)thenDepFlexAndRigid(fpos,pos)elsex|Some(DepFlexfpos)->ifargument_less(pos,fpos)||argument_position_eqposfposthenDepRigidposelseDepFlexAndRigid(fpos,pos)|SomeManual->assertfalseelsematchstwith|None->DepFlexpos|Some(DepRigidrposasx)->ifargument_less(pos,rpos)thenDepFlexAndRigid(pos,rpos)elsex|Some(DepFlexAndRigid(fpos,rpos)asx)->ifargument_less(pos,fpos)thenDepFlexAndRigid(pos,rpos)elsex|Some(DepFlexfposasx)->ifargument_less(pos,fpos)thenDepFlexposelsex|SomeManual->assertfalseinSomee(* modified is_rigid_reference with a truncated env *)letis_flexible_referenceenvsigmabounddepthf=matchkindsigmafwith|Relnwhenn>=bound+depth->(* inductive type *)false|Relnwhenn>=depth->(* previous argument *)true|Reln->(* since local definitions have been expanded *)false|Const(kn,_)->letcb=Environ.lookup_constantknenvin(matchcb.const_bodywithDef_->true|_->false)|Varid->env|>Environ.lookup_namedid|>NamedDecl.is_local_def|Ind_|Construct_->false|_->trueletpush_liftd(e,n)=(push_relde,n+1)letis_reversible_patternsigmabounddepthfl=isRelsigmaf&&letn=destRelsigmafin(n<bound+depth)&&(n>=depth)&&Array.for_all(func->isRelsigmac&&destRelsigmac<depth)l&&Array.distinctl(* Precondition: rels in env are for inductive types only *)letadd_free_rels_untilstrictstrongly_strictrevpatboundenvsigmamposacc=letrecfrecrig(env,depthased)c=lethd=ifstrictthenReductionops.clos_whd_flagsRedFlags.allenvsigmacelsecinletc=ifstrongly_strictthenhdelsecinmatchkindsigmahdwith|Relnwhen(n<bound+depth)&&(n>=depth)->leti=bound+depth-n-1inacc.(i)<-updateposrigacc.(i)|App(f,l)whenrevpat&&is_reversible_patternsigmabounddepthfl->leti=bound+depth-EConstr.destRelsigmaf-1inacc.(i)<-updateposrigacc.(i)|App(f,_)whenrig&&is_flexible_referenceenvsigmabounddepthf->ifstrictthen()elseiter_with_full_bindersenvsigmapush_lift(frecfalse)edc|Proj(p,_,_)whenrig->ifstrictthen()elseiter_with_full_bindersenvsigmapush_lift(frecfalse)edc|Case_whenrig->ifstrictthen()elseiter_with_full_bindersenvsigmapush_lift(frecfalse)edc|Evar_->()|_->iter_with_full_bindersenvsigmapush_lift(frecrig)edcinlet()=ifnot(Vars.noccur_betweensigma1boundm)thenfrectrue(env,1)minacc(* compute the list of implicit arguments *)letrecis_rigid_headsigmat=matchkindsigmatwith|Rel_|Evar_->false|Ind_|Const_|Var_|Sort_->true|Case(_,_,_,_,_,f,_)->is_rigid_headsigmaf|Proj_->true|App(f,args)->(matchkindsigmafwith|Fix((fi,i),_)->is_rigid_headsigma(args.(fi.(i)))|_->is_rigid_headsigmaf)|Lambda_|LetIn_|Construct_|CoFix_|Fix_|Prod_|Meta_|Cast_|Int_|Float_|String_|Array_->assertfalseletis_rigidenvsigmat=letopenContext.Rel.Declarationinmatchwhd_prodenvsigmatwith|Some(na,a,b)->let(_,t)=whd_decompose_prod(push_rel(LocalAssum(na,a))env)sigmabinis_rigid_headsigmat|_->trueletcompute_implicits_namesenvsigmat=letopenContext.Rel.Declarationinletrecauxenvnamest=matchwhd_prodenvsigmatwith|Some(na,a,b)->letrels,ids=Termops.free_rels_and_unqualified_refssigmaainaux(push_rel(LocalAssum(na,a))env)((na.Context.binder_name,rels,ids)::names)b|None->letrels,ids=Termops.free_rels_and_unqualified_refssigmatinletrecset_names(allrels,ids)=function|[]->(1,1,[])|(na,rels',ids')::names->let(absolute_pos,nnondep,names)=set_names(rels'::allrels,Id.Set.unionidsids')namesinletisdep=List.exists_i(funirels->Int.Set.memirels)1allrelsinletnnondep',dep_pos=ifisdepthennnondep,Noneelsennondep+1,Somennondepin(absolute_pos+1,nnondep',(na,absolute_pos,dep_pos)::names)inlet_,_,names=set_names([rels],ids)namesinList.revnamesinauxenv[]tletcompute_implicits_explanation_genstrictstrongly_strictrevpatcontextualenvsigmat=letopenContext.Rel.Declarationinletrecauxenvnt=matchwhd_prodenvsigmatwith|Some(na,a,b)->add_free_rels_untilstrictstrongly_strictrevpatnenvsigmaa(Hyp(n+1))(aux(push_rel(LocalAssum(na,a))env)(n+1)b)|_->letv=Array.makenNoneinifcontextualthenadd_free_rels_untilstrictstrongly_strictrevpatnenvsigmatConclusionvelsevinmatchwhd_prodenvsigmatwith|Some(na,a,b)->letv=aux(push_rel(LocalAssum(na,a))env)1binArray.to_listv|_->[]letcompute_implicits_explanation_flagsenvsigmaft=compute_implicits_explanation_gen(f.strict||f.strongly_strict)f.strongly_strictf.reversible_patternf.contextualenvsigmatletcompute_implicits_flagsenvsigmaft=List.combine(compute_implicits_namesenvsigmat)(compute_implicits_explanation_flagsenvsigmaft)letcompute_auto_implicitsenvsigmaflagsenrichingt=List.combine(compute_implicits_namesenvsigmat)(ifenrichingthencompute_implicits_explanation_flagsenvsigmaflagstelsecompute_implicits_explanation_genfalsefalsefalsetrueenvsigmat)(* Extra information about implicit arguments *)typemaximal_insertion=bool(* true = maximal contextual insertion *)typeforce_inference=bool(* true = always infer, never turn into evar/subgoal *)typeimplicit_position=Name.t*int*intoptiontypeimplicit_status_info={impl_pos:implicit_position;impl_expl:implicit_explanation;impl_max:maximal_insertion;impl_force:force_inference;}typeimplicit_status=implicit_status_infooptiontypeimplicit_side_condition=DefaultImpArgs|LessArgsThanofinttypeimplicits_list=implicit_side_condition*implicit_statuslistletis_status_implicit=function|None->false|_->trueletname_of_posk=Id.of_string("arg_"^string_of_intk)letbinding_kind_of_status=function|Some{impl_max=false}->NonMaxImplicit|Some{impl_max=true}->MaxImplicit|None->Explicitletname_of_implicit=function|None->anomaly(Pp.str"Not an implicit argument.")|Some{impl_pos=(Nameid,_,_)}->id|Some{impl_pos=(Anonymous,k,_)}->name_of_poskletmatch_implicitimppos=matchimp,poswith|None,_->anomaly(Pp.str"Not an implicit argument.")|Some{impl_pos=(Nameid,_,_)},ExplByNameid'->Id.equalidid'|Some{impl_pos=(_,_,Somen)},ExplByPosn'->Int.equalnn'|Some{impl_pos=(_,n,_)},ExplByNameid->Id.equalid(name_of_posn)|_->falseletmaximal_insertion_of=function|Someimp->imp.impl_max|None->anomaly(Pp.str"Not an implicit argument.")letforce_inference_of=function|Someimp->imp.impl_force|None->anomaly(Pp.str"Not an implicit argument.")letis_nondep_implicitpimps=List.exists(functionSome{impl_pos=(_,_,Somep')}->Int.equalpp'|_->false)imps(* [in_ctx] means we know the expected type, [n] is the index of the argument *)letis_inferable_implicitin_ctxn=function|None->false|Some{impl_expl=DepRigid(Hypp)}->in_ctx||n>=p|Some{impl_expl=DepFlex(Hypp)}->false|Some{impl_expl=DepFlexAndRigid(_,Hypq)}->in_ctx||n>=q|Some{impl_expl=DepRigidConclusion}->in_ctx|Some{impl_expl=DepFlexConclusion}->false|Some{impl_expl=DepFlexAndRigid(_,Conclusion)}->in_ctx|Some{impl_expl=Manual}->trueletexplicitation=function|None->anomaly(Pp.str"not implicit")|Someimp->let(na,_,p)=imp.impl_posinmatchna,pwith|Nameid,_->ExplByNameid|_,Somep->ExplByPosp|_->anomaly(Pp.str"Implicit without a position")letpositions_of_implicits(_,impls)=letrecauxn=function[]->[]|Some_::l->n::aux(n+1)l|None::l->aux(n+1)linaux1impls(* Manage user-given implicit arguments *)letrecprepare_implicitsif=function|[]->[]|((na,_,_aspos),Someimp)::imps->letimps'=prepare_implicits(i+1)fimpsinletdata={impl_pos=pos;impl_expl=imp;impl_max=set_maximalitySilentnaiimps'f.maximal;impl_force=true}inSomedata::imps'|_::imps->None::prepare_implicits(i+1)fimpsletset_manual_implicitssilentflagsenrichingautoimpsl=(* Compare with automatic implicits to recover printing data and names *)letrecmergekautoimpsexplimps=matchautoimps,explimpswith|autoimp::autoimps,explimp::explimps->letimps'=merge(k+1)autoimpsexplimpsinbeginmatchautoimp,explimp.CAst.vwith|((Name_asna,_,_aspos),_),Some(_,max)->Some{impl_pos=pos;impl_expl=Manual;impl_max=set_maximality(ifsilentthenSilentelseError)nakimps'max;impl_force=true;}|((Anonymous,n1,n2),_),Some(na,max)->Some{impl_pos=(na,n1,n2);impl_expl=Manual;impl_max=max;impl_force=true;}|((na,_,_aspos),Someexp),Nonewhenenriching->Some{impl_pos=pos;impl_expl=exp;impl_max=set_maximality(ifsilentthenSilentelseInfo)nakimps'flags.maximal;impl_force=true;}|(pos,_),None->Noneend::imps'|[],[]->[]|[],_->assertfalse(* possibly more automatic than manual implicit arguments
when the conclusion is an unfoldable constant *)|autoimps,[]->mergekautoimps[CAst.makeNone]inmerge1autoimpslletcompute_semi_auto_implicitsenvsigmaft=ifnotf.autothen[DefaultImpArgs,[]]elseletl=compute_implicits_flagsenvsigmaftin[DefaultImpArgs,prepare_implicits1fl](*s Constants. *)letcompute_constant_implicitsflagscst=letenv=Global.env()inletsigma=Evd.from_envenvinletcb=Environ.lookup_constantcstenvinletty=of_constrcb.const_typeinletimpls=compute_semi_auto_implicitsenvsigmaflagstyinimpls(*s Inductives and constructors. Their implicit arguments are stored
in an array, indexed by the inductive number, of pairs $(i,v)$ where
$i$ are the implicit arguments of the inductive and $v$ the array of
implicit arguments of the constructors. *)letcompute_mib_implicitsflagskn=letenv=Global.env()inletsigma=Evd.from_envenvinletmib=Environ.lookup_mindknenvinletar=Array.to_list(Array.mapi(* No need to lift, arities contain no de Bruijn *)(funimip->(* No need to care about constraints here *)letty,_=Typeops.type_of_global_in_contextenv(GlobRef.IndRef(kn,i))inletr=(snd@@Inductive.lookup_mind_specifenv(kn,i)).mind_relevanceinContext.Rel.Declaration.LocalAssum(Context.make_annot(Namemip.mind_typename)r,ty))mib.mind_packets)inletenv_ar=Environ.push_rel_contextarenvinletimps_one_inductiveimip=letind=(kn,i)inletar,_=Typeops.type_of_global_in_contextenv(GlobRef.IndRefind)in((GlobRef.IndRefind,compute_semi_auto_implicitsenvsigmaflags(of_constrar)),Array.mapi(funj(ctx,cty)->letc=of_constr(Term.it_mkProd_or_LetInctyctx)in(GlobRef.ConstructRef(ind,j+1),compute_semi_auto_implicitsenv_arsigmaflagsc))mip.mind_nf_lc)inArray.mapiimps_one_inductivemib.mind_packetsletcompute_all_mib_implicitsflagskn=letimps=compute_mib_implicitsflagskninList.flatten(Array.map_to_list(fun(ind,cstrs)->ind::Array.to_listcstrs)imps)(*s Variables. *)letcompute_var_implicitsflagsid=letenv=Global.env()inletsigma=Evd.from_envenvincompute_semi_auto_implicitsenvsigmaflags(NamedDecl.get_type(lookup_namedidenv))(* Implicits of a global reference. *)letcompute_global_implicitsflags=letopenGlobRefinfunction|VarRefid->compute_var_implicitsflagsid|ConstRefkn->compute_constant_implicitsflagskn|IndRef(kn,i)->let((_,imps),_)=(compute_mib_implicitsflagskn).(i)inimps|ConstructRef((kn,i),j)->let(_,cimps)=(compute_mib_implicitsflagskn).(i)insndcimps.(j-1)(* Merge a manual implicit position with an implicit_status list *)letmerge_impls(cond,oldimpls)(_,newimpls)=letoldimpls,usersuffiximpls=List.chop(List.lengthnewimpls)oldimplsincond,(List.map2(funorigni->matchorigwith|Some{impl_expl=Manual}->orig|_->ni)oldimplsnewimpls)@usersuffiximpls(* Caching implicits *)typeimplicit_interactive_request=|ImplAuto|ImplManualofinttypeimplicit_discharge_request=|ImplLocal|ImplConstantofimplicits_flags|ImplMutualInductiveofMutInd.t*implicits_flags|ImplInteractiveofimplicits_flags*implicit_interactive_requestletimplicits_table=Summary.refGlobRef.Map.empty~name:"implicits"letimplicits_of_globalref=tryletl=GlobRef.Map.findref!implicits_tableintryletrename_l=Arguments_renaming.arguments_namesrefinletrecrenameimplicitsnames=matchimplicits,nameswith|[],_->[]|_,[]->implicits|Some({impl_pos=(_,n1,n2)}asimpl)::implicits,Nameid::names->Some{implwithimpl_pos=(Nameid,n1,n2)}::renameimplicitsnames|imp::implicits,_::names->imp::renameimplicitsnamesinList.map(fun(t,il)->t,renameilrename_l)lwithNot_found->lwithNot_found->[DefaultImpArgs,[]]letcache_implicits_decl(ref,imps)=implicits_table:=GlobRef.Map.addrefimps!implicits_tableletload_implicits_(_,l)=List.itercache_implicits_decllletcache_implicitso=load_implicits1oletsubst_implicits_declsubst(r,impsaso)=letr'=fst(subst_globalsubstr)inifr==r'thenoelse(r',imps)letsubst_implicits(subst,(req,l))=(ImplLocal,List.Smart.map(subst_implicits_declsubst)l)(* This was moved out of lib.ml, however it is not stored with regular
implicit data *)letsec_implicits=Summary.refId.Map.empty~name:"section-implicits"letimpls_of_contextvars=letmapnid=letimpl_pos=(Nameid,n,None)inmatchId.Map.getid!sec_implicitswith|NonMaxImplicit->Some{impl_pos;impl_expl=Manual;impl_max=false;impl_force=true}|MaxImplicit->Some{impl_pos;impl_expl=Manual;impl_max=true;impl_force=true}|Explicit->NoneinList.map_imap1varsletadjust_side_conditionp=function|LessArgsThann->LessArgsThan(n+p)|DefaultImpArgs->DefaultImpArgsletlift_argument_positionp=function|Conclusion->Conclusion|Hypq->Hyp(p+q)letlift_explanationp=function|DepRigide->DepRigid(lift_argument_positionpe)|DepFlexe->DepFlex(lift_argument_positionpe)|DepFlexAndRigid(e1,e2)->DepFlexAndRigid(lift_argument_positionpe1,lift_argument_positionpe2)|Manual->Manualletlift_implicitspimp=let(na,n1,o)=imp.impl_posin{impwithimpl_pos=(na,n1+p,o);impl_expl=lift_explanationpimp.impl_expl}letadd_section_implsvarsextra_impls(cond,impls)=letp=List.lengthvars-List.lengthextra_implsinadjust_side_conditionpcond,extra_impls@List.map(Option.map(lift_implicitsp))implsletdischarge_implicits(req,l)=matchreqwith|ImplLocal->None|ImplMutualInductive_|ImplInteractive_|ImplConstant_->letl'=tryList.map(fun(gr,l)->letvars=Array.map_to_listConstr.destVar(Lib.section_instancegr)inletextra_impls=impls_of_contextvarsinletnewimpls=List.map(add_section_implsvarsextra_impls)lin(gr,newimpls))lwithNot_found->linSome(req,l')letrebuild_implicits(req,l)=matchreqwith|ImplLocal->assertfalse|ImplConstantflags->letref,oldimpls=List.hdlinletnewimpls=compute_global_implicitsflagsrefinreq,[ref,List.map2merge_implsoldimplsnewimpls]|ImplMutualInductive(kn,flags)->letnewimpls=compute_all_mib_implicitsflagskninletrecauxoldsnews=matcholds,newswith|(_,oldimpls)::old,(gr,newimpls)::tl->(gr,List.map2merge_implsoldimplsnewimpls)::auxoldtl|[],[]->[]|_,_->assertfalseinreq,auxlnewimpls|ImplInteractive(flags,o)->letref,oldimpls=List.hdlin(ifisVarRefref&&Lib.is_in_sectionrefthenImplLocalelsereq),matchowith|ImplAuto->letnewimpls=compute_global_implicitsflagsrefin[ref,List.map2merge_implsoldimplsnewimpls]|ImplManualuserimplsize->ifflags.autothenletnewimpls=List.hd(compute_global_implicitsflagsref)inletp=List.length(sndnewimpls)-userimplsizeinletnewimpls=on_snd(List.firstnp)newimplsin[ref,List.map(funo->merge_implsonewimpls)oldimpls]else[ref,oldimpls]letclassify_implicits(req,_)=matchreqwith|ImplLocal->Dispose|_->Substitutetypeimplicits_obj=implicit_discharge_request*(GlobRef.t*implicits_listlist)listletinImplicits:implicits_obj->obj=declare_object{(default_object"IMPLICITS")withcache_function=cache_implicits;load_function=load_implicits;subst_function=subst_implicits;classify_function=classify_implicits;discharge_function=discharge_implicits;rebuild_function=rebuild_implicits}letis_locallocalref=local||isVarRefref&&Lib.is_in_sectionrefletdeclare_implicits_genreqflagsref=letimps=compute_global_implicitsflagsrefinLib.add_leaf(inImplicits(req,[ref,imps]))letdeclare_implicitslocalref=letflags={!implicit_argswithauto=true}inletreq=ifis_locallocalrefthenImplLocalelseImplInteractive(flags,ImplAuto)indeclare_implicits_genreqflagsrefletdeclare_var_implicitsid~impl=letflags=!implicit_argsinsec_implicits:=Id.Map.addidimpl!sec_implicits;declare_implicits_genImplLocalflags(GlobRef.VarRefid)letdeclare_constant_implicitscon=letflags=!implicit_argsindeclare_implicits_gen(ImplConstantflags)flags(GlobRef.ConstRefcon)letdeclare_mib_implicitskn=letflags=!implicit_argsinletimps=Array.map_to_list(fun(ind,cstrs)->ind::(Array.to_listcstrs))(compute_mib_implicitsflagskn)inLib.add_leaf(inImplicits(ImplMutualInductive(kn,flags),List.flattenimps))(* Declare manual implicits *)typemanual_implicits=(Name.t*bool)optionCAst.tlistletcompute_implicits_with_manualenvsigma?(silent=true)typenrichingl=letautoimpls=compute_auto_implicitsenvsigma!implicit_argsenrichingtypinset_manual_implicitssilent!implicit_argsenrichingautoimplslletcheck_inclusionl=(* Check strict inclusion *)letrecaux=function|n1::(n2::_asnl)->ifn1<=n2thenuser_errPp.(str"Sequences of implicit arguments must be of different lengths.");auxnl|_->()inaux(List.mapsndl)letcheck_rigidityisrigid=ifnotisrigidthenuser_err(strbrk"Multiple sequences of implicit arguments available only for references that cannot be applied to an arbitrarily large number of arguments.")letprojection_implicitsenvpimpls=letnpars=Projection.nparspinCList.skipn_at_bestnparsimplsletdeclare_manual_implicitslocalref?enrichingl=letflags=!implicit_argsinletenv=Global.env()inletsigma=Evd.from_envenvinlett,_=Typeops.type_of_global_in_contextenvrefinlett=of_constrtinletenriching=Option.defaultflags.autoenrichinginletautoimpls=compute_auto_implicitsenvsigmaflagsenrichingtinletl=[DefaultImpArgs,set_manual_implicitsfalseflagsenrichingautoimplsl]inletreq=ifis_locallocalrefthenImplLocalelseImplInteractive(flags,ImplManual(List.lengthautoimpls))inLib.add_leaf(inImplicits(req,[ref,l]))letmaybe_declare_manual_implicitslocalref?enrichingl=ifList.exists(funx->x.CAst.v<>None)lthendeclare_manual_implicitslocalref?enrichinglletset_name(na',x,yaspos)=function|Name_asna->(na,x,y)|Anonymous->posletcompute_implicit_statusesautoimpsl=letrecauxi=function|_::autoimps,(_,Explicit)::manualimps->None::aux(i+1)(autoimps,manualimps)|pos::autoimps,(na,MaxImplicit)::manualimps->letimp={impl_pos=set_nameposna;impl_expl=Manual;impl_max=true;impl_force=true;}inSomeimp::aux(i+1)(autoimps,manualimps)|pos::autoimps,(na,NonMaxImplicit)::manualimps->letimps'=aux(i+1)(autoimps,manualimps)inletmax=set_maximalityErrornaiimps'falseinletimp={impl_pos=set_nameposna;impl_expl=Manual;impl_max=max;impl_force=true;}inSomeimp::imps'|autoimps,[]->List.map(fun_->None)autoimps|[],_::_->assertfalseinaux1(autoimps,l)letset_implicitslocalrefl=letflags=!implicit_argsinletenv=Global.env()inletsigma=Evd.from_envenvinlett,_=Typeops.type_of_global_in_contextenvrefinlett=of_constrtinletautoimpls=compute_implicits_namesenvsigmatinletl'=matchlwith|[]->assertfalse|[l]->[DefaultImpArgs,compute_implicit_statusesautoimplsl]|_->check_rigidity(is_rigidenvsigmat);(* Sort by number of implicits, decreasing *)letis_implicit=function|_,Explicit->false|_->trueinletl=List.map(funimps->(imps,List.countis_implicitimps))linletl=List.sort(fun(_,n1)(_,n2)->n2-n1)lincheck_inclusionl;letnargs=List.lengthautoimplsinList.map(fun(imps,n)->(LessArgsThan(nargs-n),compute_implicit_statusesautoimplsimps))linletreq=ifis_locallocalrefthenImplLocalelseImplInteractive(flags,ImplManual(List.lengthautoimpls))inLib.add_leaf(inImplicits(req,[ref,l']))letextract_impargs_dataimpls=letrecauxp=function|(DefaultImpArgs,imps)::_->[None,imps]|(LessArgsThann,imps)::l->(Some(p,n),imps)::aux(n+1)l|[]->[]inaux0implsletmake_implicits_listl=[DefaultImpArgs,l]letrecdrop_first_implicitspl=ifInt.equalp0thenlelsematchlwith|_,[]asx->x|DefaultImpArgs,imp::impls->drop_first_implicits(p-1)(DefaultImpArgs,impls)|LessArgsThann,imp::impls->letn=ifis_status_implicitimpthennelsen-1indrop_first_implicits(p-1)(LessArgsThann,impls)letrecchop_and_adjustnl1l2=ifn=0then(List.revl1,l2)elsematchl2with|[]->chop_and_adjust(n-1)(None::l1)[]|a::l2->chop_and_adjust(n-1)(a::l1)l2letrecselect_impargs_sizen=function|[]->[](* Tolerance for (DefaultImpArgs,[]) *)|[_,impls]|(DefaultImpArgs,impls)::_->impls|(LessArgsThanp,impls)::l->ifn<=pthenimplselseselect_impargs_sizenlletselect_stronger_impargs=function|[]->[](* Tolerance for (DefaultImpArgs,[]) *)|(_,impls)::_->implsletselect_impargs_size_for_proj~nexpectedparams~ngivenparams~nextraargsimpls=letsplit_implicit_paramsimps=ifList.is_emptyimpsthen(nexpectedparams,[],[])elseletimps1,imps2=chop_and_adjustnexpectedparams[]impsinletimp,imps2=matchimps2withimp::imps2->[imp],imps2|_->[],[]inletnimps1=nexpectedparams-List.countis_status_implicitimps1in(* Force the main argument to be explicit *)(nimps1,imps1@[None],imps2)inletnallgivenargs=ngivenparams+nextraargs+1inletlittle_enough_all_implicit=function|(DefaultImpArgs,impls)->Some(split_implicit_paramsimpls)|(LessArgsThanr,impls)whennallgivenargs<=r->Some(split_implicit_paramsimpls)|_->Nonein(* Compute the implicit signatures with little enough implicit to
match the number of arguments *)letimpls=List.map_filterlittle_enough_all_implicitimplsin(* Compute those which matches the number of parameters given *)letimpls'=List.filter(fun(nimps1,_,_)->Int.equalnimps1ngivenparams)implsinmatchimpls'with|(_,imps1,imps2)::_->Inl(imps1,imps2)|[]->ifInt.equalngivenparamsnexpectedparamsthenInl([],[])elseInr(lazy(List.sort_uniqInt.compare(List.rev_mappi1impls)))letimpargs_for_proj~nexpectedparams~nextraargsimps=letimps1,imps2=tryList.chopnexpectedparamsimpswithFailure_->imps,[]inletimp,imps2=matchimps2withimp::imps2->imp,imps2|_->None,[]inletimps2=tryList.firstnnextraargsimps2withFailure_->[]inimps1@[None],imps2