123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539(************************************************************************)(* * 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) *)(************************************************************************)openUtilopenNamesletmaybe_error_many_udecls=function|({CAst.loc;v=id},Some_)->CErrors.user_err?locPp.(strbrk"When declaring multiple symbols in one command, "++strbrk"only the first is allowed a universe binder "++strbrk"(which will be shared by the whole block).")|(_,None)->()letpreprocess_symbolsl=letopenVernacexprinifGlobal.sections_are_opened()thenCErrors.user_errPp.(str"Declaring a symbol is not allowed in sections.");letudecl=matchlwith|(coe,((id,udecl)::rest,c))::rest'->List.itermaybe_error_many_udeclsrest;List.iter(fun(coe,(idl,c))->List.itermaybe_error_many_udeclsidl)rest';udecl|(_,([],_))::_|[]->assertfalseinletno_coercion_msg=Pp.(str"Cannot deal with coercions in symbols")inList.iter(functionAddCoercion,(({CAst.loc;_},_)::_,_)->CErrors.user_err?locno_coercion_msg|AddCoercion,_->assertfalse|_->())l;udecl,List.concat_map(fun(coe,(idl,c))->List.map(fun(id,_)->id,c)idl)lletdo_symbol~poly~unfold_fixudecl(id,typ)=ifDumpglob.dump()thenDumpglob.dump_definitionidfalse"symb";letid=id.CAst.vinletenv=Global.env()inletevd,udecl=Constrintern.interp_univ_decl_optenvudeclinletevd,(typ,impls)=Constrintern.(interp_type_evars_impls~impls:empty_internalization_env)envevdtypinPretyping.check_evars_are_solved~program_mode:falseenvevd;letevd=Evd.minimize_universesevdinlet_qvars,uvars=EConstr.universes_of_constrevdtypinletevd=Evd.restrict_universe_contextevduvarsinlettyp=EConstr.to_constrevdtypinletunivs=Evd.check_univ_decl~polyevdudeclinletentry=Declare.symbol_entry~univs~unfold_fixtypinletkn=Declare.declare_constant~name:id~kind:Decls.IsSymbol(Declare.SymbolEntryentry)inlet()=Impargs.maybe_declare_manual_implicitsfalse(GlobRef.ConstRefkn)implsinlet()=Declare.assumption_messageidin()letdo_symbols~poly~unfold_fixl=letenv=Global.env()inifnot@@Environ.rewrite_rules_allowedenvthenraiseEnviron.(RewriteRulesNotAllowedSymb);letudecl,l=preprocess_symbolslinList.iter(do_symbol~poly~unfold_fixudecl)lopenUtilopenConstropenDeclarationstypestate=(int*intEvar.Map.t)*(int*intInt.Map.t)*(int*intInt.Map.t)letrecis_rel_instk=function|SList.Nil->true|SList.Default_->false|SList.Cons(t,l)->kindt=Relk&&is_rel_inst(succk)lletupdate_invtbl~locenvevdevk(curvar,tbl)=curvar,(succcurvar,tbl|>Evar.Map.updateevk@@function|None->Somecurvar|Somekascwhenk=curvar->c|Somek->CErrors.user_err?locPp.(str"Variable "++Termops.pr_existential_keyenvevdevk++str" is bound multiple times in the pattern (holes number "++intk++str" and "++intcurvar++str")."))letupdate_invtblu1~locevdlvloldlvl(curvaru,tbl)=succcurvaru,tbl|>Int.Map.updatelvl@@function|None->Somecurvaru|Somekascwhenk=curvaru->c|Somek->CErrors.user_err?locPp.(str"Universe variable "++Termops.pr_evd_levelevdlvlold++str" is bound multiple times in the pattern (holes number "++intk++str" and "++intcurvaru++str").")letupdate_invtblq1~locevdqoldqvar(curvarq,tbl)=succcurvarq,tbl|>Int.Map.updateqvar@@function|None->Somecurvarq|Somekascwhenk=curvarq->c|Somek->CErrors.user_err?locPp.(str"Sort variable "++Sorts.Quality.pr(Termops.pr_evd_qvarevd)qold++str" is bound multiple times in the pattern (holes number "++intk++str" and "++intcurvarq++str").")letsafe_quality_pattern_of_quality~locevdqsubststateqq=matchSorts.Quality.(subst(subst_fnqsubst)q)with|QConstantqc->stateq,PQConstantqc|QVarqv->letqio=Sorts.QVar.var_indexqvinletstateq=Option.fold_right(update_invtblq1~locevdq)qiostateqinstateq,PQVarqioletupdate_invtblu~locevd(qsubst,usubst)(state,stateq,stateu:state)u:state*_=let(q,u)=u|>UVars.Instance.to_arrayinletstateq,maskq=Array.fold_left_map(safe_quality_pattern_of_quality~locevdqsubst)stateqqinletstateu,masku=Array.fold_left_map(funstateulvlold->letlvlnew=Univ.Level.var_index@@Univ.subst_univs_level_levelusubstlvloldinOption.fold_right(update_invtblu1~locevdlvlold)lvlnewstateu,lvlnew)stateuuin(state,stateq,stateu),(maskq,masku)letuniverse_level_subst_var_indexusubstu=matchUniv.Universe.leveluwith|None->None|Somelvlold->letlvl=Univ.subst_univs_level_levelusubstlvloldinOption.map(funlvl->lvlold,lvl)@@Univ.Level.var_indexlvlletsafe_sort_pattern_of_sort~locevd(qsubst,usubst)(st,sq,suasstate)s=letopenSortsinmatchswith|Typeu->beginmatchuniverse_level_subst_var_indexusubstuwith|None->state,PSTypeNone|Some(lvlold,lvl)->(st,sq,update_invtblu1~locevdlvloldlvlsu),PSType(Somelvl)end|SProp->state,PSSProp|Prop->state,PSProp|Set->state,PSSet|QSort(qold,u)->letsq,bq=matchSorts.Quality.(var_index@@subst_fnqsubstqold)with|Someq->update_invtblq1~locevd(QVarqold)qsq,Someq|None->sq,Noneinletsu,ba=matchuniverse_level_subst_var_indexusubstuwith|Some(lvlold,lvl)->update_invtblu1~locevdlvloldlvlsu,Somelvl|None->su,Nonein(st,sq,su),PSQSort(bq,ba)letwarn_irrelevant_pattern=CWarnings.create~name:"irrelevant-pattern"(fun()->Pp.(str"This subpattern is irrelevant and can never be matched against."))letwarn_eta_in_pattern=CWarnings.create~name:"eta-in-pattern"Fun.idletwarn_redex_in_rewrite_rules=CWarnings.create~name:"redex-in-rewrite-rules"(funredex->Pp.(str"This pattern contains a"++redex++str" which may prevent this rule from being triggered."))letreccheck_may_eta~locenvevdt=matchEConstr.kindevd(Reductionops.whd_allenvevdt)with|Prod_->warn_eta_in_pattern?locPp.(str"This subpattern has a product type, but pattern-matching is not done modulo eta, so this rule may not trigger at required times.")|Sort_->()|Ind(ind,u)->letspecif=Inductive.lookup_mind_specifenvindinifnot@@Inductive.is_primitive_recordspecifthen()elsewarn_eta_in_pattern?locPp.(str"This subpattern has a primitive record type, but pattern-matching is not done modulo eta, so this rule may not trigger at required times.")|App(i,_)->check_may_eta~locenvevdi|_->warn_eta_in_pattern?locPp.(str"This subpattern has a yet unknown type, which may be a product type, but pattern-matching is not done modulo eta, so this rule may not trigger at required times.")lettest_may_eta~locenvevdconstr=lett=Retyping.get_type_ofenvevdconstrinlet()=check_may_eta~locenvevdtin()letrecsafe_pattern_of_constr_aux~locenvevdusubstdepthstatet=Constr.kindt|>function|App(f,args)->letstate,(head,elims)=safe_pattern_of_constr_aux~locenvevdusubstdepthstatefinletstate,pargs=Array.fold_left_map(safe_arg_pattern_of_constr~locenvevdusubstdepth)stateargsinstate,(head,elims@[PEApppargs])|Case(ci,u,params,(ret,_),_,c,brs)->letmib,mip=Inductive.lookup_mind_specifenvci.ci_indinletstate,mask=update_invtblu~locevdusubststateuinletstate,(head,elims)=safe_pattern_of_constr_aux~locenvevdusubstdepthstatecinletparamdecl=Vars.subst_instance_contextumib.mind_params_ctxtinletparamsubst=Vars.subst_of_rel_context_instanceparamdeclparamsinletstate,pret=let(nas,p)=retinletrealdecls,_=List.chopmip.mind_nrealdeclsmip.mind_arity_ctxtinletself=letargs=Context.Rel.instancemkRel0mip.mind_arity_ctxtinletinst=UVars.Instance.(abstract_instance(lengthu))inmkApp(mkIndU(ci.ci_ind,inst),args)inletrealdecls=Context.Rel.Declaration.LocalAssum(Context.make_annotAnonymousmip.mind_relevance,self)::realdeclsinletrealdecls=Inductive.instantiate_contextuparamsubstnasrealdeclsinletp_env=Environ.push_rel_contextrealdeclsenvinsafe_arg_pattern_of_constr~locp_envevdusubst(depth+Array.lengthnas)statepinletdo_one_branchistate(nas,br)=let(ctx,cty)=mip.mind_nf_lc.(i)inletbctx,_=List.chopmip.mind_consnrealdecls.(i)ctxinletbctx=Inductive.instantiate_contextuparamsubstnasbctxinletbr_env=Environ.push_rel_contextbctxenvinsafe_arg_pattern_of_constr~locbr_envevdusubst(depth+Array.lengthnas)statebrinletstate,pbrs=Array.fold_left_map_ido_one_branchstatebrsinstate,(head,elims@[PECase(ci.ci_ind,mask,pret,pbrs)])|Proj(p,_,c)->letstate,(head,elims)=safe_pattern_of_constr_aux~locenvevdusubstdepthstatecinstate,(head,elims@[PEProjp])|_->letstate,head=safe_head_pattern_of_constr~locenvevdusubstdepthstatetinstate,(head,[])andsafe_pattern_of_constr~locenvevdusubstdepthstatet=beginmatchEConstr.ERelevance.kindevd@@Retyping.relevance_of_termenvevd(EConstr.of_constrt)with|Sorts.Irrelevant->warn_irrelevant_pattern?loc()|Sorts.RelevanceVar_->()(* FIXME *)|Sorts.Relevant->()end;safe_pattern_of_constr_aux~locenvevdusubstdepthstatetandsafe_head_pattern_of_constr~locenvevdusubstdepthstatet=Constr.kindt|>function|Const(c,u)whenEnviron.is_symbolenvc->letstate,mask=update_invtblu~locevdusubststateuinstate,PHSymbol(c,mask)|Reli->assert(i<=depth);state,PHReli|Sorts->letstate,ps=safe_sort_pattern_of_sort~locevdusubststatesinstate,PHSortps|Ind(ind,u)->letstate,mask=update_invtblu~locevdusubststateuinstate,PHInd(ind,mask)|Construct(c,u)->letstate,mask=update_invtblu~locevdusubststateuinstate,PHConstr(c,mask)|Inti->state,PHInti|Floatf->state,PHFloatf|Strings->state,PHStrings|Lambda_->let(ntys,b)=Term.decompose_lambdatinlettys=Array.rev_of_listntysinlet(state,env),ptys=Array.fold_left_map_i(funi(state,env)(na,ty)->letstate,p=safe_arg_pattern_of_constr~locenvevdusubst(depth+i)statetyin(state,Environ.push_rel(LocalAssum(na,ty))env),p)(state,env)tysinletstate,pbod=safe_arg_pattern_of_constr~locenvevdusubst(depth+Array.lengthtys)statebinstate,PHLambda(ptys,pbod)|Prod_->let(ntys,b)=Term.decompose_prodtinlettys=Array.rev_of_listntysinlet(state,env),ptys=Array.fold_left_map_i(funi(state,env)(na,ty)->letstate,p=safe_arg_pattern_of_constr~locenvevdusubst(depth+i)statetyin(state,Environ.push_rel(LocalAssum(na,ty))env),p)(state,env)tysinletstate,pbod=safe_arg_pattern_of_constr~locenvevdusubst(depth+Array.lengthtys)statebinstate,PHProd(ptys,pbod)|_->CErrors.user_err?locPp.(str"Subterm not recognised as pattern: "++Printer.safe_pr_lconstr_envenvevdt)andsafe_arg_pattern_of_constr~locenvevdusubstdepth(st,stateq,stateuasstate)t=Constr.kindt|>function|Evar(evk,inst)->letEvarInfoevi=Evd.findevdevkin(matchsnd(Evd.evar_sourceevi)with|Evar_kinds.MatchingVar(Evar_kinds.FirstOrderPatVarid)->letholei,st=update_invtbl~locenvevdevkstinifnot@@is_rel_inst1instthenCErrors.user_err?locPp.(str"In "++Printer.safe_pr_lconstr_envenvevd(of_kind(Evar(evk,inst)))++str", variable "++Termops.pr_existential_keyenvevdevk++str" appears with a non-trivial instantiation.");ifEvd.evar_hypsevi|>Environ.named_context_of_val|>Context.Named.length<>SList.lengthinstthenCErrors.user_err?locPp.(str"Pattern variable cannot access the whole context: "++Printer.safe_pr_lconstr_envenvevdt);(st,stateq,stateu),EHoleholei|Evar_kinds.NamedHole_->CErrors.user_err?locPp.(str"Named holes are not supported, you must use regular evars: "++Printer.safe_pr_lconstr_envenvevdt)|_->ifOption.is_empty@@Evd.evar_identevkevdthenstate,EHoleIgnoredelseCErrors.user_err?locPp.(str"Named evar in unsupported context: "++Printer.safe_pr_lconstr_envenvevdt))|_->test_may_eta~locenvevd(EConstr.of_constrt);letstate,p=safe_pattern_of_constr~locenvevdusubstdepthstatetinstate,ERigidp(* relocation of evars into de Bruijn indices *)letrecevar_substevmapevdkt=matchEConstr.kindevdtwith|Evar(evk,inst)->beginmatchEvar.Map.find_optevkevmapwith|None->t|Some(n,vars)->lethead=EConstr.mkRel(n+k)inletEvd.EvarInfoevi=Evd.findevdevkinletbody=EConstr.mkApp(head,vars)inletinst=inst|>SList.Smart.map(evar_substevmapevdk)inEvd.instantiate_evar_arrayevdevibodyinstend|_->EConstr.map_with_bindersevdsucc(evar_substevmapevd)ktlettest_projection_appsenvevd~locindargs=letspecif=Inductive.lookup_mind_specifenvindinifnot@@Inductive.is_primitive_recordspecifthen()elseifArray.for_all_i(funiarg->matchargwith|EHole_|EHoleIgnored->true|ERigid(_,[])->false|ERigid(_,elims)->matchList.lastelimswith|PEProjp->Ind.CanOrd.equal(Projection.inductivep)ind&&Projection.argp=i|_->false)0argsthenwarn_redex_in_rewrite_rules?locPp.(str" subpattern compatible with an eta-long form for "++Id.print(sndspecif).mind_typename++str",")letrectest_pattern_redexenvevd~loc=function|PHLambda_,PEApp_::_->warn_redex_in_rewrite_rules?loc(Pp.str" beta redex")|PHConstr_,(PECase_|PEProj_)::_->warn_redex_in_rewrite_rules?loc(Pp.str" iota redex")|PHConstr_,PEApp_::(PECase_|PEProj_)::_->warn_redex_in_rewrite_rules?loc(Pp.str" iota redex")|PHLambda_,_->warn_redex_in_rewrite_rules?loc(Pp.str" lambda pattern")|PHConstr(c,_)ashead,PEAppargs::elims->test_projection_appsenvevd~loc(fstc)args;Array.iter(test_pattern_redex_auxenvevd~loc)args;test_pattern_redexenvevd~loc(head,elims)|head,PEAppargs::elims->Array.iter(test_pattern_redex_auxenvevd~loc)args;test_pattern_redexenvevd~loc(head,elims)|head,PECase(_,_,ret,brs)::elims->test_pattern_redex_auxenvevd~locret;Array.iter(test_pattern_redex_auxenvevd~loc)brs;test_pattern_redexenvevd~loc(head,elims)|head,PEProj_::elims->test_pattern_redexenvevd~loc(head,elims)|PHProd(tys,bod),[]->Array.iter(test_pattern_redex_auxenvevd~loc)tys;test_pattern_redex_auxenvevd~locbod|(PHRel_|PHInt_|PHFloat_|PHString_|PHSort_|PHInd_|PHConstr_|PHSymbol_),[]->()andtest_pattern_redex_auxenvevd~loc=function|EHole_|EHoleIgnored->()|ERigidp->test_pattern_redexenvevd~locpletwarn_rewrite_rules_break_SR="rewrite-rules-break-SR"letrewrite_rules_break_SR_warning=CWarnings.create_warning~name:warn_rewrite_rules_break_SR~default:CWarnings.Enabled()letrewrite_rules_break_SR_msg=CWarnings.create_msgrewrite_rules_break_SR_warning()letwarn_rewrite_rules_break_SR~locreason=CWarnings.warnrewrite_rules_break_SR_msg?locreasonlet()=CWarnings.register_printerrewrite_rules_break_SR_msg(funreason->Pp.(str"This rewrite rule breaks subject reduction ("++reason++str")."))letinterp_rule(udecl,lhs,rhs:Constrexpr.universe_decl_exproption*_*_)=letenv=Global.env()inletevd=Evd.from_envenvin(* 1. Read universe level binders, leaving out the constraints for now *)(* Inlined the relevant part of Constrintern.interp_univ_decl *)letevd,udecl=letopenCAstinletopenUStateinmatchudeclwith|None->evd,default_univ_decl|Someudecl->letevd,qualities=List.fold_left_map(funevdlid->Evd.new_quality_variable?loc:lid.loc~name:lid.vevd)evdudecl.univdecl_qualitiesinletevd,instance=List.fold_left_map(funevdlid->Evd.new_univ_level_variable?loc:lid.locuniv_rigid~name:lid.vevd)evdudecl.univdecl_instanceinletcstrs=udecl.univdecl_constraints|>List.to_seq|>Seq.map(Constrintern.interp_univ_constraintevd)|>Univ.Constraints.of_seqinletdecl={univdecl_qualities=qualities;univdecl_extensible_qualities=udecl.univdecl_extensible_qualities;univdecl_instance=instance;univdecl_extensible_instance=udecl.univdecl_extensible_instance;univdecl_constraints=cstrs;univdecl_extensible_constraints=udecl.univdecl_extensible_constraints;}inevd,declinletnvarqs=List.lengthudecl.univdecl_qualitiesinletnvarus=List.lengthudecl.univdecl_instancein(* 2. Read left hand side, into a pattern *)(* The udecl constraints must be implied by the lhs (and not the reverse) *)letlhs_loc=lhs.CAst.locinletrhs_loc=rhs.CAst.locinletlhs=Constrintern.(intern_genWithoutTypeConstraintenvevdlhs)inletflags={Pretyping.no_classes_no_fail_inference_flagswithundeclared_evars_patvars=true;patvars_abstract=true;expand_evars=false;solve_unification_constraints=false}inletevd,lhs,typ=Pretyping.understand_tcc_ty~flagsenvevdlhsinletevd=Evd.minimize_universesevdinlet_qvars,uvars=EConstr.universes_of_constrevdlhsinletevd=Evd.restrict_universe_contextevduvarsinletuctx,uctx'=UState.check_univ_decl_rev(Evd.evar_universe_contextevd)udeclinletusubst=letinst,auctx=UVars.abstract_universesuctx'inUVars.make_instance_substinstinlet((nvars',invtbl),(nvarqs',invtblq),(nvarus',invtblu)),(head_pat,elims)=safe_pattern_of_constr~loc:lhs_locenvevdusubst0((1,Evar.Map.empty),(0,Int.Map.empty),(0,Int.Map.empty))(EConstr.Unsafe.to_constrlhs)inlet()=test_pattern_redexenvevd~loc:lhs_loc(head_pat,elims)inlethead_symbol,head_umask=matchhead_patwithPHSymbol(symb,mask)->symb,mask|_->CErrors.user_err?loc:lhs_locPp.(str"Head head-pattern is not a symbol.")inifnvarus<>nvarus'thenbeginassert(nvarus'<nvarus);CErrors.user_err?loc:lhs_locPp.(str"Not all universe level variables appear in the pattern.")end;ifnvarqs<>nvarqs'thenbeginassert(nvarqs'<nvarqs);CErrors.user_err?loc:lhs_locPp.(str"Not all sort variables appear in the pattern.")end;letupdate_invtblevdevkn=letEvd.EvarInfoevi=Evd.findevdevkinletvars=Evd.evar_hypsevi|>Environ.named_context_of_val|>Context.Named.instanceEConstr.mkVarin(n,vars)inletinvtbl=Evar.Map.mapi(update_invtblevd)invtblin(* 3. Read right hand side *)(* The udecl constraints (or, if none, the lhs constraints) must imply those of the rhs *)letevd=Evd.set_universe_contextevductxinletrhs=Constrintern.(intern_genWithoutTypeConstraintenvevdrhs)inletflags={Pretyping.no_classes_no_fail_inference_flagswithpatvars_abstract=true}inletevd',rhs=tryPretyping.understand_tcc~flagsenvevd~expected_type:(OfTypetyp)rhswithType_errors.TypeError_|Pretype_errors.PretypeError_->warn_rewrite_rules_break_SR~loc:rhs_loc(Pp.str"the replacement term doesn't have the type of the pattern");Pretyping.understand_tcc~flagsenvevdrhsinletevd'=Evd.minimize_universesevd'inlet_qvars',uvars'=EConstr.universes_of_constrevd'rhsinletevd'=Evd.restrict_universe_contextevd'(Univ.Level.Set.unionuvarsuvars')inletfailpp=warn_rewrite_rules_break_SR~loc:rhs_locPp.(str"universe inconsistency, missing constraints: "++pp)inlet()=UState.check_uctx_impl~fail(Evd.evar_universe_contextevd)(Evd.evar_universe_contextevd')inletevd=evd'inletrhs=letrhs'=evar_substinvtblevd0rhsinmatchEConstr.to_constr_optevdrhs'with|Somerhs->rhs|None->letpr_unresolved_evare=Pp.(hov2(str"- "++Printer.pr_existential_keyenvevde++str": "++Himsg.explain_pretype_errorenvevd(Pretype_errors.UnsolvableImplicit(e,None))))inCErrors.user_err?loc:rhs_locPp.(hov0beginstr"The replacement term contains unresolved implicit arguments:"++fnl()++str" "++Printer.pr_econstr_envenvevdrhs++fnl()++str"More precisely: "++fnl()++v0(prlist_with_sepcutpr_unresolved_evar(Evar.Set.elements(Evarutil.undefined_evars_of_termevdrhs')))end)inletrhs=Vars.subst_univs_level_construsubstrhsinlettest_qvarq=matchSorts.QVar.var_indexqwith|Some-1->CErrors.user_err?loc:rhs_locPp.(str"Sort variable "++Termops.pr_evd_qvarevdq++str" appears in the replacement but does not appear in the pattern.")|Somenwhenn<0||n>nvarqs'->CErrors.anomalyPp.(str"Unknown sort variable in rewrite rule.")|Some_->()|None->ifnot@@Sorts.QVar.Set.memq(evd|>Evd.sort_context_set|>fst|>fst)thenCErrors.user_err?loc:rhs_locPp.(str"Sort variable "++Termops.pr_evd_qvarevdq++str" appears in the replacement but does not appear in the pattern.")inlettest_level?(alg_ok=false)lvl=matchUniv.Level.var_indexlvlwith|Some-1->CErrors.user_err?loc:rhs_locPp.(str"Universe level variable "++Termops.pr_evd_levelevdlvl++str" appears in the replacement but does not appear in the pattern.")|Somenwhenn<0||n>nvarus'->CErrors.anomalyPp.(str"Unknown universe level variable in rewrite rule")|Some_->()|None->tryUGraph.check_declared_universes(Environ.universesenv)(Univ.Level.Set.singletonlvl)withUGraph.UndeclaredLevellvl->CErrors.user_err?loc:rhs_locPp.(str"Universe level "++Termops.pr_evd_levelevdlvl++str" appears in the replacement but does not appear in the pattern.")inlet()=letqs,us=Vars.sort_and_universes_of_constrrhsinSorts.QVar.Set.itertest_qvarqs;Univ.Level.Set.itertest_levelusinhead_symbol,{nvars=(nvars'-1,nvarqs',nvarus');lhs_pat=head_umask,elims;rhs}letdo_rulesidrules=letenv=Global.env()inifnot@@Environ.rewrite_rules_allowedenvthenraiseEnviron.(RewriteRulesNotAllowedRule);letbody={rewrules_rules=List.mapinterp_rulerules}inGlobal.add_rewrite_rulesidbody