(************************************************************************) (* * The Rocq Prover / The Rocq 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) *) (************************************************************************)
open CErrors open Util open Pp open Names open Term open Constr open Context open Vars open Environ open Coercionops open Declare open Libobject
let strength_min l = ifList.mem `LOCAL l then `LOCAL else `GLOBAL
let loc_of_bool b = if b then `LOCAL else `GLOBAL
(* Errors *)
type coercion_error_kind =
| AlreadyExists
| NotAFunction
| NoSource of cl_typ option
| ForbiddenSourceClass of cl_typ
| NoTarget
| WrongTarget of cl_typ * cl_typ
| NotAClass of GlobRef.t
exception CoercionError of coercion_error_kind
let explain_coercion_error g = function
| AlreadyExists ->
(Printer.pr_global g ++ str" is already a coercion")
| NotAFunction ->
(Printer.pr_global g ++ str" is not a function")
| NoSource (Some cl) ->
(str "Cannot recognize " ++ pr_class cl ++ str " as a source class of "
++ Printer.pr_global g)
| NoSource None ->
(str ": cannot find the source class of " ++ Printer.pr_global g)
| ForbiddenSourceClass cl ->
pr_class cl ++ str " cannot be a source class"
| NoTarget ->
(str"Cannot find the target class")
| WrongTarget (clt,cl) ->
(str"Found target class " ++ pr_class cl ++
str " instead of " ++ pr_class clt)
| NotAClass ref ->
(str "Type of " ++ Printer.pr_global ref ++
str " does not end with a sort")
(* Verifications pour l'ajout d'une classe *)
let check_reference_arity ref = let env = Global.env () in let c, _ = Typeops.type_of_global_in_context env refin ifnot (Reductionops.is_arity env (Evd.from_env env) (EConstr.of_constr c)) (* FIXME *) then raise (CoercionError (NotAClass ref))
let check_arity = function
| CL_FUN | CL_SORT -> ()
| CL_CONST cst -> check_reference_arity (GlobRef.ConstRef cst)
| CL_PROJ p -> check_reference_arity (GlobRef.ConstRef (Projection.Repr.constant p))
| CL_SECVAR id -> check_reference_arity (GlobRef.VarRef id)
| CL_IND kn -> check_reference_arity (GlobRef.IndRef kn)
(* Coercions *)
(* check that the computed target is the provided one *) let check_target clt = function
| Some cl when not (cl_typ_eq cl clt) -> raise (CoercionError (WrongTarget(clt,cl)))
| _ -> ()
let class_of_global = function
| GlobRef.ConstRef sp ->
(match Structures.PrimitiveProjections.find_opt sp with
| Some p -> CL_PROJ p | None -> CL_CONST sp)
| GlobRef.IndRef sp -> CL_IND sp
| GlobRef.VarRef id -> CL_SECVAR id
| GlobRef.ConstructRef _ as c ->
user_err
(str "Constructors, such as " ++ Printer.pr_global c ++
str ", cannot be used as a class.")
let get_source env lp source = letopen Context.Rel.Declaration in match source with
| None -> (* Take the latest non let-in argument *) let rec aux = function
| [] -> raise Not_found
| LocalDef _ :: lt -> aux lt
| LocalAssum (_,t1) :: lt -> let cl1,u1,lv1 = find_class_type (push_rel_context lt env) Evd.empty (EConstr.of_constr t1) in
cl1,lt,lv1,1 in aux lp
| Some cl -> (* Take the first argument that matches *) let rec aux env acc = function
| [] -> raise Not_found
| LocalDef _ as decl :: lt -> aux (push_rel decl env) (decl::acc) lt
| LocalAssum (_,t1) as decl :: lt -> try let cl1,u1,lv1 = find_class_type env Evd.empty (EConstr.of_constr t1) in if cl_typ_eq cl cl1 then cl1,acc,lv1,Context.Rel.nhyps lt+1 elseraise Not_found with Not_found -> aux (push_rel decl env) (decl::acc) lt in aux env [] (List.rev lp)
let get_target env lp t ind = if (ind > 1) then
CL_FUN else match pi1 (find_class_type (push_rel_context lp env) Evd.empty (EConstr.of_constr t)) with
| CL_CONST p when Structures.PrimitiveProjections.mem p ->
CL_PROJ (Option.get @@ Structures.PrimitiveProjections.find_opt p)
| x -> x
let strength_of_cl = function
| CL_CONST kn -> `GLOBAL
| CL_SECVAR id -> `LOCAL
| _ -> `GLOBAL
let strength_of_global = function
| GlobRef.VarRef _ -> `LOCAL
| _ -> `GLOBAL
let get_strength stre ref cls clt = let stres = strength_of_cl cls in let stret = strength_of_cl clt in let stref = strength_of_global refin
strength_min [stre;stres;stret;stref]
let ident_key_of_class = function
| CL_FUN -> "Funclass"
| CL_SORT -> "Sortclass"
| CL_CONST sp -> Label.to_string (Constant.label sp)
| CL_PROJ sp -> Label.to_string (Projection.Repr.label sp)
| CL_IND (sp,_) -> Label.to_string (MutInd.label sp)
| CL_SECVAR id -> Id.to_string id
(* Identity coercion *)
let error_not_transparent source =
user_err
(pr_class source ++ str " must be a transparent constant.")
let build_id_coercion ?loc idf_opt source poly = let env = Global.env () in let sigma = Evd.from_env env in let sigma, vs = match source with
| CL_CONST sp -> Evd.fresh_global env sigma (GlobRef.ConstRef sp)
| _ -> error_not_transparent source in let vs = EConstr.Unsafe.to_constr vs in let c = match constant_opt_value_in env (destConst vs) with
| Some c -> c
| None -> error_not_transparent source in let lams,t = decompose_lambda_decls c in let val_f =
Term.it_mkLambda_or_LetIn
(mkLambda (make_annot (Name Namegen.default_dependent_ident) Sorts.Relevant,
applistc vs (Context.Rel.instance_list mkRel 0 lams),
mkRel 1))
lams in let typ_f = List.fold_left (fun d c -> Term.mkProd_wo_LetIn c d)
(mkProd (make_annot Anonymous Sorts.Relevant, applistc vs (Context.Rel.instance_list mkRel 0 lams), lift 1 t))
lams in (* juste pour verification *) let sigma, val_t = Typing.type_of env sigma (EConstr.of_constr val_f) in let () = ifnot (Reductionops.is_conv_leq env sigma val_t (EConstr.of_constr typ_f)) then
user_err (strbrk "Cannot be defined as coercion (maybe a bad number of arguments).") in let name = match idf_opt with
| Some idf -> idf
| None -> let cl,u,_ = find_class_type env sigma (EConstr.of_constr t) in
Id.of_string ("Id_"^(ident_key_of_class source)^"_"^
(ident_key_of_class cl)) in let univs = Evd.univ_entry ~poly sigma in let constr_entry = (* Cast is necessary to express [val_f] is identity *)
DefinitionEntry
(definition_entry ~types:typ_f ~univs
~inline:true (mkCast (val_f, DEFAULTcast, typ_f))) in let kind = Decls.(IsDefinition IdentityCoercion) in let kn = declare_constant ?loc ~name ~kind constr_entry in
GlobRef.ConstRef kn
let check_source = function
| Some (CL_FUN as s) -> raise (CoercionError (ForbiddenSourceClass s))
| _ -> ()
let cache_coercion ?(update=false) c = let env = Global.env () in let sigma = Evd.from_env env in
Coercionops.declare_coercion env sigma ~update c
let discharge_coercion c = if c.coe_local then None else let n = try Array.length (Global.section_instance c.coe_value) with Not_found -> 0 in let nc = { c with
coe_param = n + c.coe_param;
coe_is_projection = Option.map Global.discharge_proj_repr c.coe_is_projection;
} in
Some nc
let classify_coercion obj = if obj.coe_local then Dispose else Substitute
let warn_uniform_inheritance =
CWarnings.create ~name:"uniform-inheritance" ~category:CWarnings.CoreCategories.coercions
(fun g ->
Printer.pr_global g ++
strbrk" does not respect the uniform inheritance condition.")
let add_new_coercion_core coef stre ~reversible source target isid : unit =
check_source source; let env = Global.env () in let t, _ = Typeops.type_of_global_in_context env coef in if coercion_exists coef thenraise (CoercionError AlreadyExists); let lp,tg = decompose_prod_decls t in let llp = List.length lp in if Int.equal llp 0thenraise (CoercionError NotAFunction); let (cls,ctx,lvs,ind) = try
get_source env lp source with Not_found -> raise (CoercionError (NoSource source)) in
check_source (Some cls); ifnot (uniform_cond Evd.empty (* FIXME - for when possibly called with unresolved evars in the future *)
ctx lvs) then
warn_uniform_inheritance coef; let clt = try
get_target env lp tg ind with Not_found -> raise (CoercionError NoTarget) in
check_target clt target;
check_arity cls;
check_arity clt; let local = match get_strength stre coef cls clt with
| `LOCAL -> true
| `GLOBAL -> false in let params = List.length (Context.Rel.instance_list EConstr.mkRel 0 ctx) in
declare_coercion coef ~local ~reversible ~isid ~src:cls ~target:clt ~params ()
let try_add_new_coercion_core ref ~local c ~reversible d e = try add_new_coercion_core ref (loc_of_bool local) c ~reversible d e with CoercionError e ->
user_err
(explain_coercion_error ref e ++ str ".")
let add_coercion_hook reversible { Declare.Hook.S.scope; dref; _ } = letopen Locality in let local = match scope with
| Discharge -> assert false(* Local Coercion in section behaves like Local Definition *)
| Global ImportNeedQualified -> true
| Global ImportDefaultBehavior -> false in let () = try_add_new_coercion dref ~local ~reversible in let msg = Nametab.pr_global_env Id.Set.empty dref ++ str " is now a coercion"in
Flags.if_verbose Feedback.msg_info msg
let add_coercion_hook ~reversible =
Declare.Hook.make (add_coercion_hook reversible)
let add_subclass_hook ~poly { Declare.Hook.S.scope; dref; _ } = letopen Locality in let stre = match scope with
| Discharge -> assert false(* Local Subclass in section behaves like Local Definition *)
| Global ImportNeedQualified -> true
| Global ImportDefaultBehavior -> false in let cl = class_of_global dref in let loc = Nametab.cci_src_loc (TrueGlobal dref) in
try_add_new_coercion_subclass ?loc cl ~local:stre ~poly
let nonuniform = Attributes.bool_attribute ~name:"nonuniform"
let add_subclass_hook ~poly ~reversible =
Declare.Hook.make (add_subclass_hook ~poly ~reversible)
let warn_reverse_no_change =
CWarnings.create ~name:"reversible-no-change" ~category:CWarnings.CoreCategories.coercions
(fun () -> str "The reversible attribute is unchanged.")
let change_reverse ref ~reversible = ifnot (coercion_exists ref) then
user_err (Printer.pr_global ref ++ str" is not a coercion."); let coe_info = coercion_info refin if reversible = coe_info.coe_reversible then warn_reverse_no_change () else cache_coercion ~update:true { coe_info with coe_reversible = reversible }
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.