aboutsummaryrefslogtreecommitdiffhomepage
path: root/library
diff options
context:
space:
mode:
Diffstat (limited to 'library')
-rw-r--r--library/assumptions.ml8
-rw-r--r--library/declare.ml83
-rw-r--r--library/declare.mli10
-rw-r--r--library/decls.ml11
-rw-r--r--library/decls.mli5
-rw-r--r--library/global.ml48
-rw-r--r--library/global.mli24
-rw-r--r--library/globnames.ml49
-rw-r--r--library/globnames.mli10
-rw-r--r--library/heads.ml23
-rw-r--r--library/impargs.ml51
-rw-r--r--library/impargs.mli2
-rw-r--r--library/kindops.ml2
-rw-r--r--library/lib.ml41
-rw-r--r--library/lib.mli16
-rw-r--r--library/library.mllib1
-rw-r--r--library/universes.ml647
-rw-r--r--library/universes.mli170
18 files changed, 1074 insertions, 127 deletions
diff --git a/library/assumptions.ml b/library/assumptions.ml
index b1f133ac3..9cfe531ce 100644
--- a/library/assumptions.ml
+++ b/library/assumptions.ml
@@ -204,7 +204,7 @@ let assumptions ?(add_opaque=false) ?(add_transparent=false) st (* t *) =
| Case (_,e1,e2,e_array) -> (iter e1)**(iter e2)**(iter_array e_array)
| Fix (_,(_, e1_array, e2_array)) | CoFix (_,(_,e1_array, e2_array)) ->
(iter_array e1_array) ** (iter_array e2_array)
- | Const kn -> do_memoize_kn kn
+ | Const (kn,_) -> do_memoize_kn kn
| _ -> identity2 (* closed atomic types + rel *)
and iter_array a = Array.fold_right (fun e f -> (iter e)**f) a identity2
in iter t s acc
@@ -222,11 +222,7 @@ let assumptions ?(add_opaque=false) ?(add_transparent=false) st (* t *) =
and add_kn kn s acc =
let cb = lookup_constant kn in
let do_type cst =
- let ctype =
- match cb.Declarations.const_type with
- | PolymorphicArity (ctx,a) -> mkArity (ctx, Type a.poly_level)
- | NonPolymorphicType t -> t
- in
+ let ctype = cb.Declarations.const_type in
(s,ContextObjectMap.add cst ctype acc)
in
let (s,acc) =
diff --git a/library/declare.ml b/library/declare.ml
index c0c4dd571..452504bf0 100644
--- a/library/declare.ml
+++ b/library/declare.ml
@@ -44,36 +44,40 @@ let if_xml f x = if !Flags.xml_export then f x else ()
type section_variable_entry =
| SectionLocalDef of definition_entry
- | SectionLocalAssum of types * bool (* Implicit status *)
+ | SectionLocalAssum of types Univ.in_universe_context_set * polymorphic * bool (** Implicit status *)
type variable_declaration = DirPath.t * section_variable_entry * logical_kind
let cache_variable ((sp,_),o) =
match o with
- | Inl cst -> Global.add_constraints cst
+ | Inl ctx -> Global.push_context_set ctx
| Inr (id,(p,d,mk)) ->
(* Constr raisonne sur les noms courts *)
if variable_exists id then
alreadydeclared (pr_id id ++ str " already exists");
- let impl,opaq,cst = match d with (* Fails if not well-typed *)
- | SectionLocalAssum (ty, impl) ->
- let cst = Global.push_named_assum (id,ty) in
- let impl = if impl then Implicit else Explicit in
- impl, true, cst
- | SectionLocalDef de ->
- let cst = Global.push_named_def (id,de) in
- Explicit, de.const_entry_opaque, cst in
+
+ let impl,opaq,poly,ctx = match d with (* Fails if not well-typed *)
+ | SectionLocalAssum ((ty,ctx),poly,impl) ->
+ let () = Global.push_named_assum ((id,ty),ctx) in
+ let impl = if impl then Implicit else Explicit in
+ impl, true, poly, ctx
+ | SectionLocalDef (de) ->
+ let () = Global.push_named_def (id,de) in
+ Explicit, de.const_entry_opaque, de.const_entry_polymorphic,
+ (Univ.ContextSet.of_context de.const_entry_universes) in
Nametab.push (Nametab.Until 1) (restrict_path 0 sp) (VarRef id);
- add_section_variable id impl;
+ add_section_variable id impl poly ctx;
Dischargedhypsmap.set_discharged_hyps sp [];
- add_variable_data id (p,opaq,cst,mk)
+ add_variable_data id (p,opaq,ctx,poly,mk)
let discharge_variable (_,o) = match o with
- | Inr (id,_) -> Some (Inl (variable_constraints id))
+ | Inr (id,_) ->
+ if variable_polymorphic id then None
+ else Some (Inl (variable_context id))
| Inl _ -> Some o
type variable_obj =
- (Univ.constraints, Id.t * variable_declaration) union
+ (Univ.ContextSet.t, Id.t * variable_declaration) union
let inVariable : variable_obj -> obj =
declare_object { (default_object "VARIABLE") with
@@ -139,7 +143,8 @@ let cache_constant ((sp,kn), obj) =
let kn' = Global.add_constant dir id obj.cst_decl in
assert (eq_constant kn' (constant_of_kn kn));
Nametab.push (Nametab.Until 1) sp (ConstRef (constant_of_kn kn));
- add_section_constant kn' (Global.lookup_constant kn').const_hyps;
+ let cst = Global.lookup_constant kn' in
+ add_section_constant (cst.const_proj <> None) kn' cst.const_hyps;
Dischargedhypsmap.set_discharged_hyps sp obj.cst_hyps;
add_constant_kind (constant_of_kn kn) obj.cst_kind
@@ -150,16 +155,18 @@ let discharged_hyps kn sechyps =
let discharge_constant ((sp, kn), obj) =
let con = constant_of_kn kn in
+
let from = Global.lookup_constant con in
let modlist = replacement_context () in
- let hyps = section_segment_of_constant con in
+ let hyps,uctx = section_segment_of_constant con in
let new_hyps = (discharged_hyps kn hyps) @ obj.cst_hyps in
- let abstract = named_of_variable_context hyps in
+ let abstract = (named_of_variable_context hyps, uctx) in
let new_decl = GlobalRecipe{ from; info = { Opaqueproof.modlist; abstract}} in
Some { obj with cst_hyps = new_hyps; cst_decl = new_decl; }
(* Hack to reduce the size of .vo: we keep only what load/open needs *)
-let dummy_constant_entry = ConstantEntry (ParameterEntry (None,mkProp,None))
+let dummy_constant_entry =
+ ConstantEntry (ParameterEntry (None,false,(mkProp,Univ.UContext.empty),None))
let dummy_constant cst = {
cst_decl = dummy_constant_entry;
@@ -187,6 +194,18 @@ let declare_constant_common id cst =
Notation.declare_ref_arguments_scope (ConstRef c);
c
+let definition_entry ?(opaque=false) ?types
+ ?(poly=false) ?(univs=Univ.UContext.empty) body =
+ { const_entry_body = Future.from_val (body,Declareops.no_seff);
+ const_entry_secctx = None;
+ const_entry_type = types;
+ const_entry_proj = None;
+ const_entry_polymorphic = poly;
+ const_entry_universes = univs;
+ const_entry_opaque = opaque;
+ const_entry_feedback = None;
+ const_entry_inline_code = false}
+
let declare_scheme = ref (fun _ _ -> assert false)
let set_declare_scheme f = declare_scheme := f
let declare_sideff se =
@@ -203,8 +222,7 @@ let declare_sideff se =
in
let ty_of cb =
match cb.Declarations.const_type with
- | Declarations.NonPolymorphicType t -> Some t
- | _ -> None in
+ | (* Declarations.NonPolymorphicType *)t -> Some t in
let cst_of cb =
let pt, opaque = pt_opaque_of cb in
let ty = ty_of cb in
@@ -215,6 +233,9 @@ let declare_sideff se =
const_entry_opaque = opaque;
const_entry_inline_code = false;
const_entry_feedback = None;
+ const_entry_polymorphic = cb.const_polymorphic;
+ const_entry_universes = Future.join cb.const_universes;
+ const_entry_proj = None;
});
cst_hyps = [] ;
cst_kind = Decl_kinds.IsDefinition Decl_kinds.Definition;
@@ -252,16 +273,11 @@ let declare_constant ?(internal = UserVerbose) ?(local = false) id (cd, kind) =
let () = if_xml (Hook.get f_xml_declare_constant) (internal, kn) in
kn
-let declare_definition ?(internal=UserVerbose)
+let declare_definition ?(internal=UserVerbose)
?(opaque=false) ?(kind=Decl_kinds.Definition) ?(local = false)
- id ?types body =
+ ?(poly=false) id ?types (body,ctx) =
let cb =
- { Entries.const_entry_body = body;
- const_entry_type = types;
- const_entry_opaque = opaque;
- const_entry_inline_code = false;
- const_entry_secctx = None;
- const_entry_feedback = None }
+ definition_entry ?types ~poly ~univs:(Univ.ContextSet.to_context ctx) ~opaque body
in
declare_constant ~internal ~local id
(Entries.DefinitionEntry cb, Decl_kinds.IsDefinition kind)
@@ -311,7 +327,8 @@ let cache_inductive ((sp,kn),(dhyps,mie)) =
let _,dir,_ = repr_kn kn in
let kn' = Global.add_mind dir id mie in
assert (eq_mind kn' (mind_of_kn kn));
- add_section_kn kn' (Global.lookup_mind kn').mind_hyps;
+ let mind = Global.lookup_mind kn' in
+ add_section_kn kn' mind.mind_hyps;
Dischargedhypsmap.set_discharged_hyps sp dhyps;
List.iter (fun (sp, ref) -> Nametab.push (Nametab.Until 1) sp ref) names
@@ -319,9 +336,9 @@ let discharge_inductive ((sp,kn),(dhyps,mie)) =
let mind = Global.mind_of_delta_kn kn in
let mie = Global.lookup_mind mind in
let repl = replacement_context () in
- let sechyps = section_segment_of_mutual_inductive mind in
+ let sechyps,uctx = section_segment_of_mutual_inductive mind in
Some (discharged_hyps kn sechyps,
- Discharge.process_inductive (named_of_variable_context sechyps) repl mie)
+ Discharge.process_inductive (named_of_variable_context sechyps,uctx) repl mie)
let dummy_one_inductive_entry mie = {
mind_entry_typename = mie.mind_entry_typename;
@@ -335,7 +352,9 @@ let dummy_inductive_entry (_,m) = ([],{
mind_entry_params = [];
mind_entry_record = false;
mind_entry_finite = true;
- mind_entry_inds = List.map dummy_one_inductive_entry m.mind_entry_inds })
+ mind_entry_inds = List.map dummy_one_inductive_entry m.mind_entry_inds;
+ mind_entry_polymorphic = false;
+ mind_entry_universes = Univ.UContext.empty })
type inductive_obj = Dischargedhypsmap.discharged_hyps * mutual_inductive_entry
diff --git a/library/declare.mli b/library/declare.mli
index 663d240dc..848bab618 100644
--- a/library/declare.mli
+++ b/library/declare.mli
@@ -23,7 +23,7 @@ open Decl_kinds
type section_variable_entry =
| SectionLocalDef of definition_entry
- | SectionLocalAssum of types * bool (** Implicit status *)
+ | SectionLocalAssum of types Univ.in_universe_context_set * polymorphic * bool (** Implicit status *)
type variable_declaration = DirPath.t * section_variable_entry * logical_kind
@@ -47,12 +47,18 @@ type internal_flag =
| KernelSilent
| UserVerbose
+(* Defaut definition entries, transparent with no secctx or proj information *)
+val definition_entry : ?opaque:bool -> ?types:types ->
+ ?poly:polymorphic -> ?univs:Univ.universe_context ->
+ constr -> definition_entry
+
val declare_constant :
?internal:internal_flag -> ?local:bool -> Id.t -> constant_declaration -> constant
val declare_definition :
?internal:internal_flag -> ?opaque:bool -> ?kind:definition_object_kind ->
- ?local:bool -> Id.t -> ?types:constr -> Entries.const_entry_body -> constant
+ ?local:bool -> ?poly:polymorphic -> Id.t -> ?types:constr ->
+ constr Univ.in_universe_context_set -> constant
(** Since transparent constant's side effects are globally declared, we
* need that *)
diff --git a/library/decls.ml b/library/decls.ml
index 2d8807f80..811d09667 100644
--- a/library/decls.ml
+++ b/library/decls.ml
@@ -18,17 +18,18 @@ open Libnames
(** Datas associated to section variables and local definitions *)
type variable_data =
- DirPath.t * bool (* opacity *) * Univ.constraints * logical_kind
+ DirPath.t * bool (* opacity *) * Univ.universe_context_set * polymorphic * logical_kind
let vartab =
Summary.ref (Id.Map.empty : variable_data Id.Map.t) ~name:"VARIABLE"
let add_variable_data id o = vartab := Id.Map.add id o !vartab
-let variable_path id = let (p,_,_,_) = Id.Map.find id !vartab in p
-let variable_opacity id = let (_,opaq,_,_) = Id.Map.find id !vartab in opaq
-let variable_kind id = let (_,_,_,k) = Id.Map.find id !vartab in k
-let variable_constraints id = let (_,_,cst,_) = Id.Map.find id !vartab in cst
+let variable_path id = let (p,_,_,_,_) = Id.Map.find id !vartab in p
+let variable_opacity id = let (_,opaq,_,_,_) = Id.Map.find id !vartab in opaq
+let variable_kind id = let (_,_,_,_,k) = Id.Map.find id !vartab in k
+let variable_context id = let (_,_,ctx,_,_) = Id.Map.find id !vartab in ctx
+let variable_polymorphic id = let (_,_,_,p,_) = Id.Map.find id !vartab in p
let variable_secpath id =
let dir = drop_dirpath_prefix (Lib.library_dp()) (variable_path id) in
diff --git a/library/decls.mli b/library/decls.mli
index f45e4f121..6e9d4a4ab 100644
--- a/library/decls.mli
+++ b/library/decls.mli
@@ -17,14 +17,15 @@ open Decl_kinds
(** Registration and access to the table of variable *)
type variable_data =
- DirPath.t * bool (** opacity *) * Univ.constraints * logical_kind
+ DirPath.t * bool (** opacity *) * Univ.universe_context_set * polymorphic * logical_kind
val add_variable_data : variable -> variable_data -> unit
val variable_path : variable -> DirPath.t
val variable_secpath : variable -> qualid
val variable_kind : variable -> logical_kind
val variable_opacity : variable -> bool
-val variable_constraints : variable -> Univ.constraints
+val variable_context : variable -> Univ.universe_context_set
+val variable_polymorphic : variable -> polymorphic
val variable_exists : variable -> bool
(** Registration and access to the table of constants *)
diff --git a/library/global.ml b/library/global.ml
index a8121d15f..c56bc9e77 100644
--- a/library/global.ml
+++ b/library/global.ml
@@ -70,9 +70,12 @@ let globalize_with_summary fs f =
let i2l = Label.of_id
-let push_named_assum a = globalize (Safe_typing.push_named_assum a)
-let push_named_def d = globalize (Safe_typing.push_named_def d)
+let push_named_assum a = globalize0 (Safe_typing.push_named_assum a)
+let push_named_def d = globalize0 (Safe_typing.push_named_def d)
let add_constraints c = globalize0 (Safe_typing.add_constraints c)
+let push_context_set c = globalize0 (Safe_typing.push_context_set c)
+let push_context c = globalize0 (Safe_typing.push_context c)
+
let set_engagement c = globalize0 (Safe_typing.set_engagement c)
let add_constant dir id d = globalize (Safe_typing.add_constant dir (i2l id) d)
let add_mind dir id mie = globalize (Safe_typing.add_mind dir (i2l id) mie)
@@ -101,6 +104,7 @@ let named_context_val () = named_context_val (env())
let lookup_named id = lookup_named id (env())
let lookup_constant kn = lookup_constant kn (env())
let lookup_inductive ind = Inductive.lookup_mind_specif (env()) ind
+let lookup_pinductive (ind,_) = Inductive.lookup_mind_specif (env()) ind
let lookup_mind kn = lookup_mind kn (env())
let lookup_module mp = lookup_module mp (env())
@@ -139,19 +143,43 @@ let env_of_context hyps =
open Globnames
-let type_of_reference env = function
+(** Build a fresh instance for a given context, its associated substitution and
+ the instantiated constraints. *)
+
+let type_of_global_unsafe r =
+ let env = env() in
+ match r with
| VarRef id -> Environ.named_type id env
- | ConstRef c -> Typeops.type_of_constant env c
+ | ConstRef c ->
+ let cb = Environ.lookup_constant c env in cb.Declarations.const_type
+ | IndRef ind ->
+ let (mib, oib) = Inductive.lookup_mind_specif env ind in
+ oib.Declarations.mind_arity.Declarations.mind_user_arity
+ | ConstructRef cstr ->
+ let (mib,oib as specif) = Inductive.lookup_mind_specif env (inductive_of_constructor cstr) in
+ let inst = Univ.UContext.instance mib.Declarations.mind_universes in
+ Inductive.type_of_constructor (cstr,inst) specif
+
+
+let is_polymorphic r =
+ let env = env() in
+ match r with
+ | VarRef id -> false
+ | ConstRef c ->
+ let cb = Environ.lookup_constant c env in cb.Declarations.const_polymorphic
| IndRef ind ->
- let specif = Inductive.lookup_mind_specif env ind in
- Inductive.type_of_inductive env specif
+ let (mib, oib) = Inductive.lookup_mind_specif env ind in
+ mib.Declarations.mind_polymorphic
| ConstructRef cstr ->
- let specif =
- Inductive.lookup_mind_specif env (inductive_of_constructor cstr) in
- Inductive.type_of_constructor cstr specif
+ let (mib,oib as specif) = Inductive.lookup_mind_specif env (inductive_of_constructor cstr) in
+ mib.Declarations.mind_polymorphic
-let type_of_global t = type_of_reference (env ()) t
+let current_dirpath () =
+ Safe_typing.current_dirpath (safe_env ())
+let with_global f =
+ let (a, ctx) = f (env ()) (current_dirpath ()) in
+ push_context_set ctx; a
(* spiwack: register/unregister functions for retroknowledge *)
let register field value by_clause =
diff --git a/library/global.mli b/library/global.mli
index e11e1c017..b6825ffa5 100644
--- a/library/global.mli
+++ b/library/global.mli
@@ -33,13 +33,19 @@ val add_constraints : Univ.constraints -> unit
(** Variables, Local definitions, constants, inductive types *)
-val push_named_assum : (Id.t * Term.types) -> Univ.constraints
-val push_named_def : (Id.t * Entries.definition_entry) -> Univ.constraints
+val push_named_assum : (Id.t * Constr.types) Univ.in_universe_context_set -> unit
+val push_named_def : (Id.t * Entries.definition_entry) -> unit
+
val add_constant :
DirPath.t -> Id.t -> Safe_typing.global_declaration -> constant
val add_mind :
DirPath.t -> Id.t -> Entries.mutual_inductive_entry -> mutual_inductive
+val add_constraints : Univ.constraints -> unit
+
+val push_context : Univ.universe_context -> unit
+val push_context_set : Univ.universe_context_set -> unit
+
(** Non-interactive modules and module types *)
val add_module :
@@ -72,6 +78,8 @@ val lookup_named : variable -> Context.named_declaration
val lookup_constant : constant -> Declarations.constant_body
val lookup_inductive : inductive ->
Declarations.mutual_inductive_body * Declarations.one_inductive_body
+val lookup_pinductive : Constr.pinductive ->
+ Declarations.mutual_inductive_body * Declarations.one_inductive_body
val lookup_mind : mutual_inductive -> Declarations.mutual_inductive_body
val lookup_module : module_path -> Declarations.module_body
val lookup_modtype : module_path -> Declarations.module_type_body
@@ -94,11 +102,14 @@ val import :
(** Function to get an environment from the constants part of the global
* environment and a given context. *)
-val type_of_global : Globnames.global_reference -> Term.types
val env_of_context : Environ.named_context_val -> Environ.env
val join_safe_environment : unit -> unit
+val is_polymorphic : Globnames.global_reference -> bool
+
+(* val type_of_global : Globnames.global_reference -> types Univ.in_universe_context_set *)
+val type_of_global_unsafe : Globnames.global_reference -> Constr.types
(** {6 Retroknowledge } *)
@@ -109,5 +120,10 @@ val register_inline : constant -> unit
(** {6 Oracle } *)
-val set_strategy : 'a Names.tableKey -> Conv_oracle.level -> unit
+val set_strategy : Names.constant Names.tableKey -> Conv_oracle.level -> unit
+
+(* Modifies the global state, registering new universes *)
+
+val current_dirpath : unit -> Names.dir_path
+val with_global : (Environ.env -> Names.dir_path -> 'a Univ.in_universe_context_set) -> 'a
diff --git a/library/globnames.ml b/library/globnames.ml
index 8a9e99621..c881e797e 100644
--- a/library/globnames.ml
+++ b/library/globnames.ml
@@ -38,19 +38,31 @@ let destConstRef = function ConstRef ind -> ind | _ -> failwith "destConstRef"
let destIndRef = function IndRef ind -> ind | _ -> failwith "destIndRef"
let destConstructRef = function ConstructRef ind -> ind | _ -> failwith "destConstructRef"
-let subst_constructor subst ((kn,i),j as ref) =
- let kn' = subst_ind subst kn in
- if kn==kn' then ref, mkConstruct ref
- else ((kn',i),j), mkConstruct ((kn',i),j)
+let subst_constructor subst (ind,j as ref) =
+ let ind' = subst_ind subst ind in
+ if ind==ind' then ref, mkConstruct ref
+ else (ind',j), mkConstruct (ind',j)
+
+let subst_global_reference subst ref = match ref with
+ | VarRef var -> ref
+ | ConstRef kn ->
+ let kn' = subst_constant subst kn in
+ if kn==kn' then ref else ConstRef kn'
+ | IndRef ind ->
+ let ind' = subst_ind subst ind in
+ if ind==ind' then ref else IndRef ind'
+ | ConstructRef ((kn,i),j as c) ->
+ let c',t = subst_constructor subst c in
+ if c'==c then ref else ConstructRef c'
let subst_global subst ref = match ref with
| VarRef var -> ref, mkVar var
| ConstRef kn ->
- let kn',t = subst_con subst kn in
+ let kn',t = subst_con_kn subst kn in
if kn==kn' then ref, mkConst kn else ConstRef kn', t
- | IndRef (kn,i) ->
- let kn' = subst_ind subst kn in
- if kn==kn' then ref, mkInd (kn,i) else IndRef(kn',i), mkInd (kn',i)
+ | IndRef ind ->
+ let ind' = subst_ind subst ind in
+ if ind==ind' then ref, mkInd ind else IndRef ind', mkInd ind'
| ConstructRef ((kn,i),j as c) ->
let c',t = subst_constructor subst c in
if c'==c then ref,t else ConstructRef c', t
@@ -62,19 +74,26 @@ let canonical_gr = function
| VarRef id -> VarRef id
let global_of_constr c = match kind_of_term c with
- | Const sp -> ConstRef sp
- | Ind ind_sp -> IndRef ind_sp
- | Construct cstr_cp -> ConstructRef cstr_cp
+ | Const (sp,u) -> ConstRef sp
+ | Ind (ind_sp,u) -> IndRef ind_sp
+ | Construct (cstr_cp,u) -> ConstructRef cstr_cp
| Var id -> VarRef id
| _ -> raise Not_found
-let constr_of_global = function
+let is_global c t =
+ match c, kind_of_term t with
+ | ConstRef c, Const (c', _) -> eq_constant c c'
+ | IndRef i, Ind (i', _) -> eq_ind i i'
+ | ConstructRef i, Construct (i', _) -> eq_constructor i i'
+ | VarRef id, Var id' -> id_eq id id'
+ | _ -> false
+
+let printable_constr_of_global = function
| VarRef id -> mkVar id
| ConstRef sp -> mkConst sp
| ConstructRef sp -> mkConstruct sp
| IndRef sp -> mkInd sp
-let constr_of_reference = constr_of_global
let reference_of_constr = global_of_constr
let global_eq_gen eq_cst eq_ind eq_cons x y =
@@ -179,10 +198,6 @@ type global_reference_or_constr =
| IsGlobal of global_reference
| IsConstr of constr
-let constr_of_global_or_constr = function
- | IsConstr c -> c
- | IsGlobal gr -> constr_of_global gr
-
(** {6 Temporary function to brutally form kernel names from section paths } *)
let encode_mind dir id = MutInd.make2 (MPfile dir) (Label.of_id id)
diff --git a/library/globnames.mli b/library/globnames.mli
index 5d717965e..5ea0c9de0 100644
--- a/library/globnames.mli
+++ b/library/globnames.mli
@@ -31,19 +31,21 @@ val destConstRef : global_reference -> constant
val destIndRef : global_reference -> inductive
val destConstructRef : global_reference -> constructor
+val is_global : global_reference -> constr -> bool
val subst_constructor : substitution -> constructor -> constructor * constr
val subst_global : substitution -> global_reference -> global_reference * constr
+val subst_global_reference : substitution -> global_reference -> global_reference
-(** Turn a global reference into a construction *)
-val constr_of_global : global_reference -> constr
+(** This constr is not safe to be typechecked, universe polymorphism is not
+ handled here: just use for printing *)
+val printable_constr_of_global : global_reference -> constr
(** Turn a construction denoting a global reference into a global reference;
raise [Not_found] if not a global reference *)
val global_of_constr : constr -> global_reference
(** Obsolete synonyms for constr_of_global and global_of_constr *)
-val constr_of_reference : global_reference -> constr
val reference_of_constr : constr -> global_reference
module RefOrdered : sig
@@ -87,8 +89,6 @@ type global_reference_or_constr =
| IsGlobal of global_reference
| IsConstr of constr
-val constr_of_global_or_constr : global_reference_or_constr -> constr
-
(** {6 Temporary function to brutally form kernel names from section paths } *)
val encode_mind : DirPath.t -> Id.t -> mutual_inductive
diff --git a/library/heads.ml b/library/heads.ml
index f64cdb05a..0faad827e 100644
--- a/library/heads.ml
+++ b/library/heads.ml
@@ -58,7 +58,7 @@ let variable_head id = Evalrefmap.find (EvalVarRef id) !head_map
let constant_head cst = Evalrefmap.find (EvalConstRef cst) !head_map
let kind_of_head env t =
- let rec aux k l t b = match kind_of_term (Reduction.whd_betaiotazeta t) with
+ let rec aux k l t b = match kind_of_term (Reduction.whd_betaiotazeta env t) with
| Rel n when n > k -> NotImmediatelyComputableHead
| Rel n -> FlexibleHead (k,k+1-n,List.length l,b)
| Var id ->
@@ -68,7 +68,7 @@ let kind_of_head env t =
match pi2 (lookup_named id env) with
| Some c -> aux k l c b
| None -> NotImmediatelyComputableHead)
- | Const cst ->
+ | Const (cst,_) ->
(try on_subterm k l b (constant_head cst)
with Not_found -> assert false)
| Construct _ | CoFix _ ->
@@ -85,6 +85,10 @@ let kind_of_head env t =
| LetIn _ -> assert false
| Meta _ | Evar _ -> NotImmediatelyComputableHead
| App (c,al) -> aux k (Array.to_list al @ l) c b
+ | Proj (p,c) ->
+ (try on_subterm k (c :: l) b (constant_head p)
+ with Not_found -> assert false)
+
| Case (_,_,c,_) -> aux k [] c true
| Fix ((i,j),_) ->
let n = i.(j) in
@@ -113,11 +117,18 @@ let kind_of_head env t =
| x -> x
in aux 0 [] t false
+(* FIXME: maybe change interface here *)
let compute_head = function
| EvalConstRef cst ->
- (match constant_opt_value (Global.env()) cst with
+ let env = Global.env() in
+ let cb = Environ.lookup_constant cst env in
+ let body =
+ if cb.Declarations.const_proj = None
+ then Declareops.body_of_constant cb else None
+ in
+ (match body with
| None -> RigidHead (RigidParameter cst)
- | Some c -> kind_of_head (Global.env()) c)
+ | Some c -> kind_of_head env c)
| EvalVarRef id ->
(match pi2 (Global.lookup_named id) with
| Some c when not (Decls.variable_opacity id) ->
@@ -140,8 +151,8 @@ let cache_head o =
let subst_head_approximation subst = function
| RigidHead (RigidParameter cst) as k ->
- let cst,c = subst_con subst cst in
- if isConst c && eq_constant (destConst c) cst then
+ let cst,c = subst_con_kn subst cst in
+ if isConst c && eq_constant (fst (destConst c)) cst then
(* A change of the prefix of the constant *)
k
else
diff --git a/library/impargs.ml b/library/impargs.ml
index 1bcff8695..5a44b5bdb 100644
--- a/library/impargs.ml
+++ b/library/impargs.ml
@@ -169,7 +169,7 @@ let is_flexible_reference env bound depth f =
| Rel n when n >= bound+depth -> (* inductive type *) false
| Rel n when n >= depth -> (* previous argument *) true
| Rel n -> (* since local definitions have been expanded *) false
- | Const kn ->
+ | Const (kn,_) ->
let cb = Environ.lookup_constant kn env in
(match cb.const_body with Def _ -> true | _ -> false)
| Var id ->
@@ -214,6 +214,7 @@ let rec is_rigid_head t = match kind_of_term t with
| Rel _ | Evar _ -> false
| Ind _ | Const _ | Var _ | Sort _ -> true
| Case (_,_,f,_) -> is_rigid_head f
+ | Proj (p,c) -> true
| App (f,args) ->
(match kind_of_term f with
| Fix ((fi,i),_) -> is_rigid_head (args.(fi.(i)))
@@ -401,7 +402,14 @@ let compute_semi_auto_implicits env f manual t =
let compute_constant_implicits flags manual cst =
let env = Global.env () in
- compute_semi_auto_implicits env flags manual (Typeops.type_of_constant env cst)
+ let cb = Environ.lookup_constant cst env in
+ let ty = cb.const_type in
+ let impls = compute_semi_auto_implicits env flags manual ty in
+ impls
+ (* match cb.const_proj with *)
+ (* | None -> impls *)
+ (* | Some {proj_npars = n} -> *)
+ (* List.map (fun (x,args) -> x, CList.skipn_at_least n args) impls *)
(*s Inductives and constructors. Their implicit arguments are stored
in an array, indexed by the inductive number, of pairs $(i,v)$ where
@@ -413,14 +421,15 @@ let compute_mib_implicits flags manual kn =
let mib = lookup_mind kn env in
let ar =
Array.to_list
- (Array.map (* No need to lift, arities contain no de Bruijn *)
- (fun mip ->
- (Name mip.mind_typename, None, type_of_inductive env (mib,mip)))
+ (Array.mapi (* No need to lift, arities contain no de Bruijn *)
+ (fun i mip ->
+ (** No need to care about constraints here *)
+ (Name mip.mind_typename, None, Global.type_of_global_unsafe (IndRef (kn,i))))
mib.mind_packets) in
let env_ar = push_rel_context ar env in
let imps_one_inductive i mip =
let ind = (kn,i) in
- let ar = type_of_inductive env (mib,mip) in
+ let ar = Global.type_of_global_unsafe (IndRef ind) in
((IndRef ind,compute_semi_auto_implicits env flags manual ar),
Array.mapi (fun j c ->
(ConstructRef (ind,j+1),compute_semi_auto_implicits env_ar flags manual c))
@@ -517,7 +526,7 @@ let section_segment_of_reference = function
| ConstRef con -> section_segment_of_constant con
| IndRef (kn,_) | ConstructRef ((kn,_),_) ->
section_segment_of_mutual_inductive kn
- | _ -> []
+ | _ -> [], Univ.UContext.empty
let adjust_side_condition p = function
| LessArgsThan n -> LessArgsThan (n+p)
@@ -532,24 +541,36 @@ let discharge_implicits (_,(req,l)) =
| ImplLocal -> None
| ImplInteractive (ref,flags,exp) ->
(try
- let vars = section_segment_of_reference ref in
+ let vars,_ = section_segment_of_reference ref in
+ (* let isproj = *)
+ (* match ref with *)
+ (* | ConstRef cst -> is_projection cst (Global.env ()) *)
+ (* | _ -> false *)
+ (* in *)
let ref' = if isVarRef ref then ref else pop_global_reference ref in
let extra_impls = impls_of_context vars in
- let l' = [ref', List.map (add_section_impls vars extra_impls) (snd (List.hd l))] in
+ let l' =
+ (* if isproj then [ref',snd (List.hd l)] *)
+ (* else *)
+ [ref', List.map (add_section_impls vars extra_impls) (snd (List.hd l))] in
Some (ImplInteractive (ref',flags,exp),l')
with Not_found -> (* ref not defined in this section *) Some (req,l))
| ImplConstant (con,flags) ->
(try
let con' = pop_con con in
- let vars = section_segment_of_constant con in
+ let vars,_ = section_segment_of_constant con in
let extra_impls = impls_of_context vars in
- let l' = [ConstRef con',List.map (add_section_impls vars extra_impls) (snd (List.hd l))] in
+ let newimpls =
+ (* if is_projection con (Global.env()) then (snd (List.hd l)) *)
+ (* else *) List.map (add_section_impls vars extra_impls) (snd (List.hd l))
+ in
+ let l' = [ConstRef con',newimpls] in
Some (ImplConstant (con',flags),l')
with Not_found -> (* con not defined in this section *) Some (req,l))
| ImplMutualInductive (kn,flags) ->
(try
let l' = List.map (fun (gr, l) ->
- let vars = section_segment_of_reference gr in
+ let vars,_ = section_segment_of_reference gr in
let extra_impls = impls_of_context vars in
((if isVarRef gr then gr else pop_global_reference gr),
List.map (add_section_impls vars extra_impls) l)) l
@@ -659,10 +680,14 @@ let check_rigidity isrigid =
if not isrigid then
errorlabstrm "" (strbrk "Multiple sequences of implicit arguments available only for references that cannot be applied to an arbitrarily large number of arguments.")
+let projection_implicits env p (x, impls) =
+ let pb = Environ.lookup_projection p env in
+ x, CList.skipn_at_least pb.Declarations.proj_npars impls
+
let declare_manual_implicits local ref ?enriching l =
let flags = !implicit_args in
let env = Global.env () in
- let t = Global.type_of_global ref in
+ let t = Global.type_of_global_unsafe ref in
let enriching = Option.default flags.auto enriching in
let isrigid,autoimpls = compute_auto_implicits env flags enriching t in
let l' = match l with
diff --git a/library/impargs.mli b/library/impargs.mli
index e70cff838..8ad86bdff 100644
--- a/library/impargs.mli
+++ b/library/impargs.mli
@@ -129,6 +129,8 @@ val make_implicits_list : implicit_status list -> implicits_list list
val drop_first_implicits : int -> implicits_list -> implicits_list
+val projection_implicits : env -> projection -> implicits_list -> implicits_list
+
val select_impargs_size : int -> implicits_list list -> implicit_status list
val select_stronger_impargs : implicits_list list -> implicit_status list
diff --git a/library/kindops.ml b/library/kindops.ml
index 6e6c7527b..b8337f5d7 100644
--- a/library/kindops.ml
+++ b/library/kindops.ml
@@ -24,7 +24,7 @@ let string_of_theorem_kind = function
| Corollary -> "Corollary"
let string_of_definition_kind def =
- let (locality, kind) = def in
+ let (locality, poly, kind) = def in
let error () = Errors.anomaly (Pp.str "Internal definition kind") in
match kind with
| Definition ->
diff --git a/library/lib.ml b/library/lib.ml
index 331196565..31f983595 100644
--- a/library/lib.ml
+++ b/library/lib.ml
@@ -380,11 +380,14 @@ let find_opening_node id =
*)
type variable_info = Names.Id.t * Decl_kinds.binding_kind * Term.constr option * Term.types
+
type variable_context = variable_info list
-type abstr_list = variable_context Names.Cmap.t * variable_context Names.Mindmap.t
+type abstr_list = variable_context Univ.in_universe_context Names.Cmap.t *
+ variable_context Univ.in_universe_context Names.Mindmap.t
let sectab =
- Summary.ref ([] : ((Names.Id.t * Decl_kinds.binding_kind) list *
+ Summary.ref ([] : ((Names.Id.t * Decl_kinds.binding_kind *
+ Decl_kinds.polymorphic * Univ.universe_context_set) list *
Opaqueproof.work_list * abstr_list) list)
~name:"section-context"
@@ -392,18 +395,19 @@ let add_section () =
sectab := ([],(Names.Cmap.empty,Names.Mindmap.empty),
(Names.Cmap.empty,Names.Mindmap.empty)) :: !sectab
-let add_section_variable id impl =
+let add_section_variable id impl poly ctx =
match !sectab with
| [] -> () (* because (Co-)Fixpoint temporarily uses local vars *)
| (vars,repl,abs)::sl ->
- sectab := ((id,impl)::vars,repl,abs)::sl
+ sectab := ((id,impl,poly,ctx)::vars,repl,abs)::sl
let extract_hyps (secs,ohyps) =
let rec aux = function
- | ((id,impl)::idl,(id',b,t)::hyps) when Names.Id.equal id id' ->
- (id',impl,b,t) :: aux (idl,hyps)
+ | ((id,impl,poly,ctx)::idl,(id',b,t)::hyps) when Names.Id.equal id id' ->
+ let l, r = aux (idl,hyps) in
+ (id',impl,b,t) :: l, if poly then Univ.ContextSet.union r ctx else r
| (id::idl,hyps) -> aux (idl,hyps)
- | [], _ -> []
+ | [], _ -> [],Univ.ContextSet.empty
in aux (secs,ohyps)
let instance_from_variable_context sign =
@@ -413,23 +417,26 @@ let instance_from_variable_context sign =
| [] -> [] in
Array.of_list (inst_rec sign)
-let named_of_variable_context = List.map (fun (id,_,b,t) -> (id,b,t))
-
+let named_of_variable_context ctx = List.map (fun (id,_,b,t) -> (id,b,t)) ctx
+
let add_section_replacement f g hyps =
match !sectab with
| [] -> ()
| (vars,exps,abs)::sl ->
- let sechyps = extract_hyps (vars,hyps) in
+ let sechyps,ctx = extract_hyps (vars,hyps) in
+ let ctx = Univ.ContextSet.to_context ctx in
let args = instance_from_variable_context (List.rev sechyps) in
- sectab := (vars,f args exps,g sechyps abs)::sl
+ sectab := (vars,f (Univ.UContext.instance ctx,args) exps,g (sechyps,ctx) abs)::sl
let add_section_kn kn =
let f x (l1,l2) = (l1,Names.Mindmap.add kn x l2) in
add_section_replacement f f
-let add_section_constant kn =
+let add_section_constant is_projection kn =
+ (* let g x (l1,l2) = (Names.Cmap.add kn (Univ.Instance.empty,[||]) l1,l2) in *)
let f x (l1,l2) = (Names.Cmap.add kn x l1,l2) in
- add_section_replacement f f
+ (* if is_projection then add_section_replacement g f *)
+ (* else *) add_section_replacement f f
let replacement_context () = pi2 (List.hd !sectab)
@@ -445,7 +452,9 @@ let rec list_mem_assoc x = function
let section_instance = function
| VarRef id ->
- if list_mem_assoc id (pi1 (List.hd !sectab)) then [||]
+ if List.exists (fun (id',_,_,_) -> Names.id_eq id id')
+ (pi1 (List.hd !sectab))
+ then Univ.Instance.empty, [||]
else raise Not_found
| ConstRef con ->
Names.Cmap.find con (fst (pi2 (List.hd !sectab)))
@@ -459,8 +468,8 @@ let full_replacement_context () = List.map pi2 !sectab
let full_section_segment_of_constant con =
List.map (fun (vars,_,(x,_)) -> fun hyps ->
named_of_variable_context
- (try Names.Cmap.find con x
- with Not_found -> extract_hyps (vars, hyps))) !sectab
+ (try fst (Names.Cmap.find con x)
+ with Not_found -> fst (extract_hyps (vars, hyps)))) !sectab
(*************)
(* Sections. *)
diff --git a/library/lib.mli b/library/lib.mli
index 8975acd9a..759a1a135 100644
--- a/library/lib.mli
+++ b/library/lib.mli
@@ -161,23 +161,23 @@ val xml_close_section : (Names.Id.t -> unit) Hook.t
(** {6 Section management for discharge } *)
type variable_info = Names.Id.t * Decl_kinds.binding_kind *
Term.constr option * Term.types
-type variable_context = variable_info list
+type variable_context = variable_info list
val instance_from_variable_context : variable_context -> Names.Id.t array
val named_of_variable_context : variable_context -> Context.named_context
-val section_segment_of_constant : Names.constant -> variable_context
-val section_segment_of_mutual_inductive: Names.mutual_inductive -> variable_context
+val section_segment_of_constant : Names.constant -> variable_context Univ.in_universe_context
+val section_segment_of_mutual_inductive: Names.mutual_inductive -> variable_context Univ.in_universe_context
-val section_instance : Globnames.global_reference -> Names.Id.t array
+val section_instance : Globnames.global_reference -> Univ.universe_instance * Names.Id.t array
val is_in_section : Globnames.global_reference -> bool
-val add_section_variable : Names.Id.t -> Decl_kinds.binding_kind -> unit
+val add_section_variable : Names.Id.t -> Decl_kinds.binding_kind -> Decl_kinds.polymorphic -> Univ.universe_context_set -> unit
-val add_section_constant : Names.constant -> Context.named_context -> unit
+val add_section_constant : bool (* is_projection *) ->
+ Names.constant -> Context.named_context -> unit
val add_section_kn : Names.mutual_inductive -> Context.named_context -> unit
-val replacement_context : unit ->
- (Names.Id.t array Names.Cmap.t * Names.Id.t array Names.Mindmap.t)
+val replacement_context : unit -> Opaqueproof.work_list
(** {6 Discharge: decrease the section level if in the current section } *)
diff --git a/library/library.mllib b/library/library.mllib
index 2568bcc18..6a58a1057 100644
--- a/library/library.mllib
+++ b/library/library.mllib
@@ -5,6 +5,7 @@ Libobject
Summary
Nametab
Global
+Universes
Lib
Declaremods
Loadpath
diff --git a/library/universes.ml b/library/universes.ml
new file mode 100644
index 000000000..79286792d
--- /dev/null
+++ b/library/universes.ml
@@ -0,0 +1,647 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+open Util
+open Pp
+open Names
+open Term
+open Context
+open Environ
+open Locus
+open Univ
+
+(* Generator of levels *)
+let new_univ_level, set_remote_new_univ_level =
+ RemoteCounter.new_counter ~name:"Universes" 0 ~incr:((+) 1)
+ ~build:(fun n -> Univ.Level.make (Global.current_dirpath ()) n)
+
+let new_univ_level _ = new_univ_level ()
+ (* Univ.Level.make db (new_univ_level ()) *)
+
+let fresh_level () = new_univ_level (Global.current_dirpath ())
+
+(* TODO: remove *)
+let new_univ dp = Univ.Universe.make (new_univ_level dp)
+let new_Type dp = mkType (new_univ dp)
+let new_Type_sort dp = Type (new_univ dp)
+
+let fresh_universe_instance ctx =
+ Instance.subst_fn (fun _ -> new_univ_level (Global.current_dirpath ()))
+ (UContext.instance ctx)
+
+let fresh_instance_from_context ctx =
+ let inst = fresh_universe_instance ctx in
+ let subst = make_universe_subst inst ctx in
+ let constraints = instantiate_univ_context subst ctx in
+ (inst, subst), constraints
+
+let fresh_instance ctx =
+ let s = ref LSet.empty in
+ let inst =
+ Instance.subst_fn (fun _ ->
+ let u = new_univ_level (Global.current_dirpath ()) in
+ s := LSet.add u !s; u)
+ (UContext.instance ctx)
+ in !s, inst
+
+let fresh_instance_from ctx =
+ let ctx', inst = fresh_instance ctx in
+ let subst = make_universe_subst inst ctx in
+ let constraints = instantiate_univ_context subst ctx in
+ (inst, subst), (ctx', constraints)
+
+(** Fresh universe polymorphic construction *)
+
+let fresh_constant_instance env c =
+ let cb = lookup_constant c env in
+ if cb.Declarations.const_polymorphic then
+ let (inst,_), ctx = fresh_instance_from (Future.join cb.Declarations.const_universes) in
+ ((c, inst), ctx)
+ else ((c,Instance.empty), ContextSet.empty)
+
+let fresh_inductive_instance env ind =
+ let mib, mip = Inductive.lookup_mind_specif env ind in
+ if mib.Declarations.mind_polymorphic then
+ let (inst,_), ctx = fresh_instance_from mib.Declarations.mind_universes in
+ ((ind,inst), ctx)
+ else ((ind,Instance.empty), ContextSet.empty)
+
+let fresh_constructor_instance env (ind,i) =
+ let mib, mip = Inductive.lookup_mind_specif env ind in
+ if mib.Declarations.mind_polymorphic then
+ let (inst,_), ctx = fresh_instance_from mib.Declarations.mind_universes in
+ (((ind,i),inst), ctx)
+ else (((ind,i),Instance.empty), ContextSet.empty)
+
+open Globnames
+let fresh_global_instance env gr =
+ match gr with
+ | VarRef id -> mkVar id, ContextSet.empty
+ | ConstRef sp ->
+ let c, ctx = fresh_constant_instance env sp in
+ mkConstU c, ctx
+ | ConstructRef sp ->
+ let c, ctx = fresh_constructor_instance env sp in
+ mkConstructU c, ctx
+ | IndRef sp ->
+ let c, ctx = fresh_inductive_instance env sp in
+ mkIndU c, ctx
+
+let constr_of_global gr =
+ let c, ctx = fresh_global_instance (Global.env ()) gr in
+ Global.push_context_set ctx; c
+
+let constr_of_global_univ (gr,u) =
+ match gr with
+ | VarRef id -> mkVar id
+ | ConstRef sp -> mkConstU (sp,u)
+ | ConstructRef sp -> mkConstructU (sp,u)
+ | IndRef sp -> mkIndU (sp,u)
+
+let fresh_global_or_constr_instance env = function
+ | IsConstr c -> c, ContextSet.empty
+ | IsGlobal gr -> fresh_global_instance env gr
+
+let global_of_constr c =
+ match kind_of_term c with
+ | Const (c, u) -> ConstRef c, u
+ | Ind (i, u) -> IndRef i, u
+ | Construct (c, u) -> ConstructRef c, u
+ | Var id -> VarRef id, Instance.empty
+ | _ -> raise Not_found
+
+let global_app_of_constr c =
+ match kind_of_term c with
+ | Const (c, u) -> (ConstRef c, u), None
+ | Ind (i, u) -> (IndRef i, u), None
+ | Construct (c, u) -> (ConstructRef c, u), None
+ | Var id -> (VarRef id, Instance.empty), None
+ | Proj (p, c) -> (ConstRef p, Instance.empty), Some c
+ | _ -> raise Not_found
+
+open Declarations
+
+let type_of_reference env r =
+ match r with
+ | VarRef id -> Environ.named_type id env, ContextSet.empty
+ | ConstRef c ->
+ let cb = Environ.lookup_constant c env in
+ if cb.const_polymorphic then
+ let (inst, subst), ctx = fresh_instance_from (Future.join cb.const_universes) in
+ Vars.subst_univs_constr subst cb.const_type, ctx
+ else cb.const_type, ContextSet.empty
+
+ | IndRef ind ->
+ let (mib, oib) = Inductive.lookup_mind_specif env ind in
+ if mib.mind_polymorphic then
+ let (inst, subst), ctx = fresh_instance_from mib.mind_universes in
+ Vars.subst_univs_constr subst oib.mind_arity.mind_user_arity, ctx
+ else oib.mind_arity.mind_user_arity, ContextSet.empty
+ | ConstructRef cstr ->
+ let (mib,oib as specif) = Inductive.lookup_mind_specif env (inductive_of_constructor cstr) in
+ if mib.mind_polymorphic then
+ let (inst, subst), ctx = fresh_instance_from mib.mind_universes in
+ Inductive.type_of_constructor (cstr,inst) specif, ctx
+ else Inductive.type_of_constructor (cstr,Instance.empty) specif, ContextSet.empty
+
+let type_of_global t = type_of_reference (Global.env ()) t
+
+let fresh_sort_in_family env = function
+ | InProp -> prop_sort, ContextSet.empty
+ | InSet -> set_sort, ContextSet.empty
+ | InType ->
+ let u = fresh_level () in
+ Type (Univ.Universe.make u), ContextSet.singleton u
+
+let new_sort_in_family sf =
+ fst (fresh_sort_in_family (Global.env ()) sf)
+
+let extend_context (a, ctx) (ctx') =
+ (a, ContextSet.union ctx ctx')
+
+let new_global_univ () =
+ let u = fresh_level () in
+ (Univ.Universe.make u, ContextSet.singleton u)
+
+(** Simplification *)
+
+module LevelUnionFind = Unionfind.Make (Univ.LSet) (Univ.LMap)
+
+let remove_trivial_constraints cst =
+ Constraint.fold (fun (l,d,r as cstr) nontriv ->
+ if d != Lt && eq_levels l r then nontriv
+ else if d == Le && is_type0m_univ (Univ.Universe.make l) then nontriv
+ else Constraint.add cstr nontriv)
+ cst Constraint.empty
+
+let add_list_map u t map =
+ let l, d, r = LMap.split u map in
+ let d' = match d with None -> [t] | Some l -> t :: l in
+ let lr =
+ LMap.merge (fun k lm rm ->
+ match lm with Some t -> lm | None ->
+ match rm with Some t -> rm | None -> None) l r
+ in LMap.add u d' lr
+
+let find_list_map u map =
+ try LMap.find u map with Not_found -> []
+
+module UF = LevelUnionFind
+type universe_full_subst = (universe_level * universe) list
+
+(** Precondition: flexible <= ctx *)
+let choose_canonical ctx flexible algs s =
+ let global = LSet.diff s ctx in
+ let flexible, rigid = LSet.partition (fun x -> LMap.mem x flexible) (LSet.inter s ctx) in
+ (** If there is a global universe in the set, choose it *)
+ if not (LSet.is_empty global) then
+ let canon = LSet.choose global in
+ canon, (LSet.remove canon global, rigid, flexible)
+ else (** No global in the equivalence class, choose a rigid one *)
+ if not (LSet.is_empty rigid) then
+ let canon = LSet.choose rigid in
+ canon, (global, LSet.remove canon rigid, flexible)
+ else (** There are only flexible universes in the equivalence
+ class, choose a non-algebraic. *)
+ let algs, nonalgs = LSet.partition (fun x -> LSet.mem x algs) flexible in
+ if not (LSet.is_empty nonalgs) then
+ let canon = LSet.choose nonalgs in
+ canon, (global, rigid, LSet.remove canon flexible)
+ else
+ let canon = LSet.choose algs in
+ canon, (global, rigid, LSet.remove canon flexible)
+
+open Universe
+
+let subst_puniverses subst (c, u as cu) =
+ let u' = Instance.subst subst u in
+ if u' == u then cu else (c, u')
+
+let nf_evars_and_universes_local f subst =
+ let rec aux c =
+ match kind_of_term c with
+ | Evar (evdk, _ as ev) ->
+ (match f ev with
+ | None -> c
+ | Some c -> aux c)
+ | Const pu ->
+ let pu' = subst_puniverses subst pu in
+ if pu' == pu then c else mkConstU pu'
+ | Ind pu ->
+ let pu' = subst_puniverses subst pu in
+ if pu' == pu then c else mkIndU pu'
+ | Construct pu ->
+ let pu' = subst_puniverses subst pu in
+ if pu' == pu then c else mkConstructU pu'
+ | Sort (Type u) ->
+ let u' = Univ.subst_univs_level_universe subst u in
+ if u' == u then c else mkSort (sort_of_univ u')
+ | _ -> map_constr aux c
+ in aux
+
+let subst_univs_fn_puniverses lsubst (c, u as cu) =
+ let u' = Instance.subst_fn lsubst u in
+ if u' == u then cu else (c, u')
+
+let subst_univs_puniverses subst cu =
+ subst_univs_fn_puniverses (Univ.level_subst_of (Univ.make_subst subst)) cu
+
+let nf_evars_and_universes_gen f subst =
+ let lsubst = Univ.level_subst_of subst in
+ let rec aux c =
+ match kind_of_term c with
+ | Evar (evdk, _ as ev) ->
+ (match try f ev with Not_found -> None with
+ | None -> c
+ | Some c -> aux c)
+ | Const pu ->
+ let pu' = subst_univs_fn_puniverses lsubst pu in
+ if pu' == pu then c else mkConstU pu'
+ | Ind pu ->
+ let pu' = subst_univs_fn_puniverses lsubst pu in
+ if pu' == pu then c else mkIndU pu'
+ | Construct pu ->
+ let pu' = subst_univs_fn_puniverses lsubst pu in
+ if pu' == pu then c else mkConstructU pu'
+ | Sort (Type u) ->
+ let u' = Univ.subst_univs_universe subst u in
+ if u' == u then c else mkSort (sort_of_univ u')
+ | _ -> map_constr aux c
+ in aux
+
+let nf_evars_and_universes_subst f subst =
+ nf_evars_and_universes_gen f (Univ.make_subst subst)
+
+let nf_evars_and_universes_opt_subst f subst =
+ let subst = fun l -> match LMap.find l subst with None -> raise Not_found | Some l' -> l' in
+ nf_evars_and_universes_gen f subst
+
+let subst_univs_full_constr subst c =
+ nf_evars_and_universes_subst (fun _ -> None) subst c
+
+let fresh_universe_context_set_instance ctx =
+ if ContextSet.is_empty ctx then LMap.empty, ctx
+ else
+ let (univs, cst) = ContextSet.levels ctx, ContextSet.constraints ctx in
+ let univs',subst = LSet.fold
+ (fun u (univs',subst) ->
+ let u' = fresh_level () in
+ (LSet.add u' univs', LMap.add u u' subst))
+ univs (LSet.empty, LMap.empty)
+ in
+ let cst' = subst_univs_level_constraints subst cst in
+ subst, (univs', cst')
+
+let normalize_univ_variable ~find ~update =
+ let rec aux cur =
+ let b = find cur in
+ let b' = subst_univs_universe aux b in
+ if Universe.eq b' b then b
+ else update cur b'
+ in fun b -> try aux b with Not_found -> Universe.make b
+
+let normalize_univ_variable_opt_subst ectx =
+ let find l =
+ match Univ.LMap.find l !ectx with
+ | Some b -> b
+ | None -> raise Not_found
+ in
+ let update l b =
+ assert (match Universe.level b with Some l' -> not (Level.eq l l') | None -> true);
+ ectx := Univ.LMap.add l (Some b) !ectx; b
+ in normalize_univ_variable ~find ~update
+
+let normalize_univ_variable_subst subst =
+ let find l = Univ.LMap.find l !subst in
+ let update l b =
+ assert (match Universe.level b with Some l' -> not (Level.eq l l') | None -> true);
+ subst := Univ.LMap.add l b !subst; b in
+ normalize_univ_variable ~find ~update
+
+let normalize_universe_opt_subst subst =
+ let normlevel = normalize_univ_variable_opt_subst subst in
+ subst_univs_universe normlevel
+
+let normalize_universe_subst subst =
+ let normlevel = normalize_univ_variable_subst subst in
+ subst_univs_universe normlevel
+
+type universe_opt_subst = universe option universe_map
+
+let make_opt_subst s =
+ fun x ->
+ (match Univ.LMap.find x s with
+ | Some u -> u
+ | None -> raise Not_found)
+
+let subst_opt_univs_constr s =
+ let f = make_opt_subst s in
+ Vars.subst_univs_fn_constr f
+
+let normalize_univ_variables ctx =
+ let ectx = ref ctx in
+ let normalize = normalize_univ_variable_opt_subst ectx in
+ let _ = Univ.LMap.iter (fun u _ -> ignore(normalize u)) ctx in
+ let undef, def, subst =
+ Univ.LMap.fold (fun u v (undef, def, subst) ->
+ match v with
+ | None -> (Univ.LSet.add u undef, def, subst)
+ | Some b -> (undef, Univ.LSet.add u def, Univ.LMap.add u b subst))
+ !ectx (Univ.LSet.empty, Univ.LSet.empty, Univ.LMap.empty)
+ in !ectx, undef, def, subst
+
+let pr_universe_body = function
+ | None -> mt ()
+ | Some v -> str" := " ++ Univ.Universe.pr v
+
+let pr_universe_opt_subst = Univ.LMap.pr pr_universe_body
+
+let is_defined_var u l =
+ try
+ match LMap.find u l with
+ | Some _ -> true
+ | None -> false
+ with Not_found -> false
+
+let subst_univs_subst u l s =
+ LMap.add u l s
+
+exception Found of Level.t
+let find_inst insts v =
+ try LMap.iter (fun k (enf,alg,v') ->
+ if not alg && enf && Universe.eq v' v then raise (Found k))
+ insts; raise Not_found
+ with Found l -> l
+
+let add_inst u (enf,b,lbound) insts =
+ match lbound with
+ | Some v -> LMap.add u (enf,b,v) insts
+ | None -> insts
+
+exception Stays
+
+let compute_lbound left =
+ (** The universe variable was not fixed yet.
+ Compute its level using its lower bound. *)
+ if CList.is_empty left then None
+ else
+ let lbound = List.fold_left (fun lbound (d, l) ->
+ if d == Le (* l <= ?u *) then (Universe.sup l lbound)
+ else (* l < ?u *)
+ (assert (d == Lt);
+ (Universe.sup (Universe.super l) lbound)))
+ Universe.type0m left
+ in
+ Some lbound
+
+let maybe_enforce_leq lbound u cstrs =
+ match lbound with
+ | Some lbound -> enforce_leq lbound (Universe.make u) cstrs
+ | None -> cstrs
+
+let instantiate_with_lbound u lbound alg enforce (ctx, us, algs, insts, cstrs) =
+ if enforce then
+ let inst = Universe.make u in
+ let cstrs' = enforce_leq lbound inst cstrs in
+ (ctx, us, LSet.remove u algs,
+ LMap.add u (enforce,alg,lbound) insts, cstrs'), (enforce, alg, inst)
+ else (* Actually instantiate *)
+ (Univ.LSet.remove u ctx, Univ.LMap.add u (Some lbound) us, algs,
+ LMap.add u (enforce,alg,lbound) insts, cstrs), (enforce, alg, lbound)
+
+type constraints_map = (Univ.constraint_type * Univ.LMap.key) list Univ.LMap.t
+
+let pr_constraints_map cmap =
+ LMap.fold (fun l cstrs acc ->
+ Level.pr l ++ str " => " ++
+ prlist_with_sep spc (fun (d,r) -> pr_constraint_type d ++ Level.pr r) cstrs ++ fnl ()
+ ++ acc)
+ cmap (mt ())
+
+let minimize_univ_variables ctx us algs left right cstrs =
+ let left, lbounds =
+ Univ.LMap.fold (fun r lower (left, lbounds as acc) ->
+ if Univ.LMap.mem r us || not (Univ.LSet.mem r ctx) then acc
+ else (* Fixed universe, just compute its glb for sharing *)
+ let lbounds' =
+ match compute_lbound (List.map (fun (d,l) -> d, Universe.make l) lower) with
+ | None -> lbounds
+ | Some lbound -> LMap.add r (true, false, lbound) lbounds
+ in (Univ.LMap.remove r left, lbounds'))
+ left (left, Univ.LMap.empty)
+ in
+ let rec instance (ctx', us, algs, insts, cstrs as acc) u =
+ let acc, left =
+ try let l = LMap.find u left in
+ List.fold_left (fun (acc, left') (d, l) ->
+ let acc', (enf,alg,l') = aux acc l in
+ (* if alg then assert(not alg); *)
+ let l' =
+ if enf then Universe.make l
+ else l'
+ (* match Universe.level l' with Some _ -> l' | None -> Universe.make l *)
+ in
+ acc', (d, l') :: left') (acc, []) l
+ with Not_found -> acc, []
+ and right =
+ try Some (LMap.find u right)
+ with Not_found -> None
+ in
+ let instantiate_lbound lbound =
+ let alg = LSet.mem u algs in
+ if alg then
+ (* u is algebraic and has no upper bound constraints: we
+ instantiate it with it's lower bound, if any *)
+ instantiate_with_lbound u lbound true false acc
+ else (* u is non algebraic *)
+ match Universe.level lbound with
+ | Some l -> (* The lowerbound is directly a level *)
+ (* u is not algebraic but has no upper bounds,
+ we instantiate it with its lower bound if it is a
+ different level, otherwise we keep it. *)
+ if not (Level.eq l u) && not (LSet.mem l algs) then
+ (* if right = None then. Should check that u does not
+ have upper constraints that are not already in right *)
+ instantiate_with_lbound u lbound false false acc
+ (* else instantiate_with_lbound u lbound false true acc *)
+ else
+ (* assert false: l can't be alg *)
+ acc, (true, false, lbound)
+ | None ->
+ try
+ (* if right <> None then raise Not_found; *)
+ (* Another universe represents the same lower bound,
+ we can share them with no harm. *)
+ let can = find_inst insts lbound in
+ instantiate_with_lbound u (Universe.make can) false false acc
+ with Not_found ->
+ (* We set u as the canonical universe representing lbound *)
+ instantiate_with_lbound u lbound false true acc
+ in
+ let acc' acc =
+ match right with
+ | None -> acc
+ | Some cstrs ->
+ let dangling = List.filter (fun (d, r) -> not (LMap.mem r us)) cstrs in
+ if List.is_empty dangling then acc
+ else
+ let ((ctx', us, algs, insts, cstrs), (enf,_,inst as b)) = acc in
+ let cstrs' = List.fold_left (fun cstrs (d, r) ->
+ if d == Univ.Le then
+ enforce_leq inst (Universe.make r) cstrs
+ else
+ try let lev = Option.get (Universe.level inst) in
+ Constraint.add (lev, d, r) cstrs
+ with Option.IsNone -> assert false)
+ cstrs dangling
+ in
+ (ctx', us, algs, insts, cstrs'), b
+ in
+ if not (LSet.mem u ctx) then acc' (acc, (true, false, Universe.make u))
+ else
+ let lbound = compute_lbound left in
+ match lbound with
+ | None -> (* Nothing to do *)
+ acc' (acc, (true, false, Universe.make u))
+ | Some lbound ->
+ acc' (instantiate_lbound lbound)
+ and aux (ctx', us, algs, seen, cstrs as acc) u =
+ try acc, LMap.find u seen
+ with Not_found -> instance acc u
+ in
+ LMap.fold (fun u v (ctx', us, algs, seen, cstrs as acc) ->
+ if v == None then fst (aux acc u)
+ else LSet.remove u ctx', us, LSet.remove u algs, seen, cstrs)
+ us (ctx, us, algs, lbounds, cstrs)
+
+let normalize_context_set ctx us algs =
+ let (ctx, csts) = ContextSet.levels ctx, ContextSet.constraints ctx in
+ let uf = UF.create () in
+ let csts =
+ (* We first put constraints in a normal-form: all self-loops are collapsed
+ to equalities. *)
+ let g = Univ.merge_constraints csts Univ.empty_universes in
+ Univ.constraints_of_universes (Univ.normalize_universes g)
+ in
+ let noneqs =
+ Constraint.fold (fun (l,d,r) noneqs ->
+ if d == Eq then (UF.union l r uf; noneqs)
+ else Constraint.add (l,d,r) noneqs)
+ csts Constraint.empty
+ in
+ let partition = UF.partition uf in
+ let subst, eqs = List.fold_left (fun (subst, cstrs) s ->
+ let canon, (global, rigid, flexible) = choose_canonical ctx us algs s in
+ (* Add equalities for globals which can't be merged anymore. *)
+ let cstrs = LSet.fold (fun g cst ->
+ Constraint.add (canon, Univ.Eq, g) cst) global cstrs
+ in
+ (** Should this really happen? *)
+ let subst' = LSet.fold (fun f -> LMap.add f canon)
+ (LSet.union rigid flexible) LMap.empty
+ in
+ let subst = LMap.union subst' subst in
+ (subst, cstrs))
+ (LMap.empty, Constraint.empty) partition
+ in
+ (* Noneqs is now in canonical form w.r.t. equality constraints,
+ and contains only inequality constraints. *)
+ let noneqs = subst_univs_level_constraints subst noneqs in
+ let us =
+ LMap.subst_union (LMap.map (fun v -> Some (Universe.make v)) subst) us
+ in
+ (* Compute the left and right set of flexible variables, constraints
+ mentionning other variables remain in noneqs. *)
+ let noneqs, ucstrsl, ucstrsr =
+ Constraint.fold (fun (l,d,r as cstr) (noneq, ucstrsl, ucstrsr) ->
+ let lus = LMap.mem l us
+ and rus = LMap.mem r us
+ in
+ let ucstrsl' =
+ if lus then add_list_map l (d, r) ucstrsl
+ else ucstrsl
+ and ucstrsr' =
+ add_list_map r (d, l) ucstrsr
+ in
+ let noneqs =
+ if lus || rus then noneq
+ else Constraint.add cstr noneq
+ in (noneqs, ucstrsl', ucstrsr'))
+ noneqs (Constraint.empty, LMap.empty, LMap.empty)
+ in
+ (* Now we construct the instanciation of each variable. *)
+ let ctx', us, algs, inst, noneqs =
+ minimize_univ_variables ctx us algs ucstrsr ucstrsl noneqs
+ in
+ let us = ref us in
+ let norm = normalize_univ_variable_opt_subst us in
+ let _normalize_subst = LMap.iter (fun u v -> ignore(norm u)) !us in
+ (!us, algs), (ctx', Constraint.union noneqs eqs)
+
+(* let normalize_conkey = Profile.declare_profile "normalize_context_set" *)
+(* let normalize_context_set a b c = Profile.profile3 normalize_conkey normalize_context_set a b c *)
+
+let universes_of_constr c =
+ let rec aux s c =
+ match kind_of_term c with
+ | Const (_, u) | Ind (_, u) | Construct (_, u) ->
+ LSet.union (Instance.levels u) s
+ | Sort u ->
+ let u = univ_of_sort u in
+ LSet.union (Universe.levels u) s
+ | _ -> fold_constr aux s c
+ in aux LSet.empty c
+
+let shrink_universe_context (univs,csts) s =
+ let univs' = LSet.inter univs s in
+ Constraint.fold (fun (l,d,r as c) (univs',csts) ->
+ if LSet.mem l univs' then
+ let univs' = if LSet.mem r univs then LSet.add r univs' else univs' in
+ (univs', Constraint.add c csts)
+ else if LSet.mem r univs' then
+ let univs' = if LSet.mem l univs then LSet.add l univs' else univs' in
+ (univs', Constraint.add c csts)
+ else (univs', csts))
+ csts (univs',Constraint.empty)
+
+let restrict_universe_context (univs,csts) s =
+ let univs' = LSet.inter univs s in
+ (* Universes that are not necessary to typecheck the term.
+ E.g. univs introduced by tactics and not used in the proof term. *)
+ let diff = LSet.diff univs s in
+ let csts' =
+ Constraint.fold (fun (l,d,r as c) csts ->
+ if LSet.mem l diff || LSet.mem r diff then csts
+ else Constraint.add c csts)
+ csts Constraint.empty
+ in (univs', csts')
+
+let is_prop_leq (l,d,r) =
+ Level.eq Level.prop l && d == Univ.Le
+
+(* Prop < i <-> Set+1 <= i <-> Set < i *)
+let translate_cstr (l,d,r as cstr) =
+ if Level.eq Level.prop l && d == Univ.Lt then
+ (Level.set, d, r)
+ else cstr
+
+let refresh_constraints univs (ctx, cstrs) =
+ let cstrs', univs' =
+ Univ.Constraint.fold (fun c (cstrs', univs as acc) ->
+ let c = translate_cstr c in
+ if Univ.check_constraint univs c && not (is_prop_leq c) then acc
+ else (Univ.Constraint.add c cstrs', Univ.enforce_constraint c univs))
+ cstrs (Univ.Constraint.empty, univs)
+ in ((ctx, cstrs'), univs')
+
+let remove_trivial_constraints (ctx, cstrs) =
+ let cstrs' =
+ Univ.Constraint.fold (fun c acc ->
+ if is_prop_leq c then Univ.Constraint.remove c acc
+ else acc) cstrs cstrs
+ in (ctx, cstrs')
diff --git a/library/universes.mli b/library/universes.mli
new file mode 100644
index 000000000..47876269a
--- /dev/null
+++ b/library/universes.mli
@@ -0,0 +1,170 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+open Util
+open Pp
+open Names
+open Term
+open Context
+open Environ
+open Locus
+open Univ
+
+(** Universes *)
+val new_univ_level : Names.dir_path -> universe_level
+val set_remote_new_univ_level : universe_level RemoteCounter.installer
+val new_univ : Names.dir_path -> universe
+val new_Type : Names.dir_path -> types
+val new_Type_sort : Names.dir_path -> sorts
+
+(** Build a fresh instance for a given context, its associated substitution and
+ the instantiated constraints. *)
+
+val fresh_instance_from_context : universe_context ->
+ (universe_instance * universe_subst) constrained
+
+val fresh_instance_from : universe_context ->
+ (universe_instance * universe_subst) in_universe_context_set
+
+val new_global_univ : unit -> universe in_universe_context_set
+val new_sort_in_family : sorts_family -> sorts
+
+val fresh_sort_in_family : env -> sorts_family ->
+ sorts in_universe_context_set
+val fresh_constant_instance : env -> constant ->
+ pconstant in_universe_context_set
+val fresh_inductive_instance : env -> inductive ->
+ pinductive in_universe_context_set
+val fresh_constructor_instance : env -> constructor ->
+ pconstructor in_universe_context_set
+
+val fresh_global_instance : env -> Globnames.global_reference ->
+ constr in_universe_context_set
+
+val fresh_global_or_constr_instance : env -> Globnames.global_reference_or_constr ->
+ constr in_universe_context_set
+
+(** Raises [Not_found] if not a global reference. *)
+val global_of_constr : constr -> Globnames.global_reference puniverses
+
+val global_app_of_constr : constr -> Globnames.global_reference puniverses * constr option
+
+val constr_of_global_univ : Globnames.global_reference puniverses -> constr
+
+val extend_context : 'a in_universe_context_set -> universe_context_set ->
+ 'a in_universe_context_set
+
+(** Simplification and pruning of constraints:
+ [normalize_context_set ctx us]
+
+ - Instantiate the variables in [us] with their most precise
+ universe levels respecting the constraints.
+
+ - Normalizes the context [ctx] w.r.t. equality constraints,
+ choosing a canonical universe in each equivalence class
+ (a global one if there is one) and transitively saturate
+ the constraints w.r.t to the equalities. *)
+
+module UF : Unionfind.PartitionSig with type elt = universe_level
+
+type universe_opt_subst = universe option universe_map
+
+val make_opt_subst : universe_opt_subst -> universe_subst_fn
+
+val subst_opt_univs_constr : universe_opt_subst -> constr -> constr
+
+val choose_canonical : universe_set -> universe_opt_subst -> universe_set -> universe_set ->
+ universe_level * (universe_set * universe_set * universe_set)
+
+val instantiate_with_lbound :
+ Univ.LMap.key ->
+ Univ.universe ->
+ bool ->
+ bool ->
+ Univ.LSet.t * Univ.universe option Univ.LMap.t *
+ Univ.LSet.t *
+ (bool * bool * Univ.universe) Univ.LMap.t * Univ.constraints ->
+ (Univ.LSet.t * Univ.universe option Univ.LMap.t *
+ Univ.LSet.t *
+ (bool * bool * Univ.universe) Univ.LMap.t * Univ.constraints) *
+ (bool * bool * Univ.universe)
+
+val compute_lbound : (constraint_type * Univ.universe) list -> universe option
+
+type constraints_map = (Univ.constraint_type * Univ.LMap.key) list Univ.LMap.t
+
+val pr_constraints_map : constraints_map -> Pp.std_ppcmds
+
+val minimize_univ_variables :
+ Univ.LSet.t ->
+ Univ.universe option Univ.LMap.t ->
+ Univ.LSet.t ->
+ constraints_map -> constraints_map ->
+ Univ.constraints ->
+ Univ.LSet.t * Univ.universe option Univ.LMap.t *
+ Univ.LSet.t *
+ (bool * bool * Univ.universe) Univ.LMap.t * Univ.constraints
+
+
+val normalize_context_set : universe_context_set ->
+ universe_opt_subst (* The defined and undefined variables *) ->
+ universe_set (* univ variables that can be substituted by algebraics *) ->
+ (universe_opt_subst * universe_set) in_universe_context_set
+
+val normalize_univ_variables : universe_opt_subst ->
+ universe_opt_subst * universe_set * universe_set * universe_subst
+
+val normalize_univ_variable :
+ find:(universe_level -> universe) ->
+ update:(universe_level -> universe -> universe) ->
+ universe_level -> universe
+
+val normalize_univ_variable_opt_subst : universe_opt_subst ref ->
+ (universe_level -> universe)
+
+val normalize_univ_variable_subst : universe_subst ref ->
+ (universe_level -> universe)
+
+val normalize_universe_opt_subst : universe_opt_subst ref ->
+ (universe -> universe)
+
+val normalize_universe_subst : universe_subst ref ->
+ (universe -> universe)
+
+(** Create a fresh global in the global environment, shouldn't be done while
+ building polymorphic values as the constraints are added to the global
+ environment already. *)
+
+val constr_of_global : Globnames.global_reference -> constr
+
+val type_of_global : Globnames.global_reference -> types in_universe_context_set
+
+(** Full universes substitutions into terms *)
+
+val nf_evars_and_universes_local : (existential -> constr option) -> universe_level_subst ->
+ constr -> constr
+
+val nf_evars_and_universes_opt_subst : (existential -> constr option) ->
+ universe_opt_subst -> constr -> constr
+
+(** Get fresh variables for the universe context.
+ Useful to make tactics that manipulate constrs in universe contexts polymorphic. *)
+val fresh_universe_context_set_instance : universe_context_set ->
+ universe_level_subst * universe_context_set
+
+val pr_universe_opt_subst : universe_opt_subst -> Pp.std_ppcmds
+
+(** Shrink a universe context to a restricted set of variables *)
+
+val universes_of_constr : constr -> universe_set
+val shrink_universe_context : universe_context_set -> universe_set -> universe_context_set
+val restrict_universe_context : universe_context_set -> universe_set -> universe_context_set
+
+val refresh_constraints : universes -> universe_context_set -> universe_context_set * universes
+
+val remove_trivial_constraints : universe_context_set -> universe_context_set