1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * INRIA, CNRS and contributors - Copyright 1999-2019 *) (* <O___,, * (see CREDITS file for the list of authors) *) (* \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 Vars open Names open Context open Constrexpr_ops open Constrintern open Impargs open Pretyping open Entries module RelDecl = Context.Rel.Declaration (* 2| Variable/Hypothesis/Parameter/Axiom declarations *) let axiom_into_instance = ref false let () = let open Goptions in declare_bool_option { optdepr = true; optname = "automatically declare axioms whose type is a typeclass as instances"; optkey = ["Typeclasses";"Axioms";"Are";"Instances"]; optread = (fun _ -> !axiom_into_instance); optwrite = (:=) axiom_into_instance; } let should_axiom_into_instance = let open Decls in function | Context -> (* The typeclass behaviour of Variable and Context doesn't depend on section status *) true | Definitional | Logical | Conjectural -> !axiom_into_instance let declare_variable is_coe ~kind typ imps impl {CAst.v=name} = let kind = Decls.IsAssumption kind in let decl = Declare.SectionLocalAssum {typ; impl} in let () = Declare.declare_variable ~name ~kind decl in let () = Declare.assumption_message name in let r = GlobRef.VarRef name in let () = maybe_declare_manual_implicits true r imps in let env = Global.env () in let sigma = Evd.from_env env in let () = Classes.declare_instance env sigma None true r in let () = if is_coe then Class.try_add_new_coercion r ~local:true ~poly:false in () let instance_of_univ_entry = function | Polymorphic_entry (_, univs) -> Univ.UContext.instance univs | Monomorphic_entry _ -> Univ.Instance.empty let declare_axiom is_coe ~poly ~local ~kind typ (univs, pl) imps nl {CAst.v=name} = let do_instance = should_axiom_into_instance kind in let inl = let open Declaremods in match nl with | NoInline -> None | DefaultInline -> Some (Flags.get_inline_level()) | InlineAt i -> Some i in let kind = Decls.IsAssumption kind in let decl = Declare.ParameterEntry (None,(typ,univs),inl) in let kn = Declare.declare_constant ~name ~local ~kind decl in let gr = GlobRef.ConstRef kn in let () = maybe_declare_manual_implicits false gr imps in let () = DeclareUniv.declare_univ_binders gr pl in let () = Declare.assumption_message name in let env = Global.env () in let sigma = Evd.from_env env in let () = if do_instance then Classes.declare_instance env sigma None false gr in let local = match local with | Declare.ImportNeedQualified -> true | Declare.ImportDefaultBehavior -> false in let () = if is_coe then Class.try_add_new_coercion gr ~local ~poly in let inst = instance_of_univ_entry univs in (gr,inst) let interp_assumption ~program_mode sigma env impls c = let sigma, (ty, impls) = interp_type_evars_impls ~program_mode env sigma ~impls c in sigma, (ty, impls) (* When monomorphic the universe constraints and universe names are declared with the first declaration only. *) let next_univs = let empty_univs = Monomorphic_entry Univ.ContextSet.empty, UnivNames.empty_binders in function | Polymorphic_entry _, _ as univs -> univs | Monomorphic_entry _, _ -> empty_univs let context_set_of_entry = function | Polymorphic_entry (_,uctx) -> Univ.ContextSet.of_context uctx | Monomorphic_entry uctx -> uctx let declare_assumptions ~poly ~scope ~kind univs nl l = let open DeclareDef in let () = match scope with | Discharge -> (* declare universes separately for variables *) Declare.declare_universe_context ~poly (context_set_of_entry (fst univs)) | Global _ -> () in let _, _ = List.fold_left (fun (subst,univs) ((is_coe,idl),typ,imps) -> (* NB: here univs are ignored when scope=Discharge *) let typ = replace_vars subst typ in let univs,subst' = List.fold_left_map (fun univs id -> let refu = match scope with | Discharge -> declare_variable is_coe ~kind typ imps Glob_term.Explicit id; GlobRef.VarRef id.CAst.v, Univ.Instance.empty | Global local -> declare_axiom is_coe ~local ~poly ~kind typ univs imps nl id in next_univs univs, (id.CAst.v, Constr.mkRef refu)) univs idl in subst'@subst, next_univs univs) ([], univs) l in () let maybe_error_many_udecls = function | ({CAst.loc;v=id}, Some _) -> user_err ?loc ~hdr:"many_universe_declarations" Pp.(str "When declaring multiple axioms in one command, " ++ str "only the first is allowed a universe binder " ++ str "(which will be shared by the whole block).") | (_, None) -> () let process_assumptions_udecls ~scope l = let udecl, first_id = match l with | (coe, ((id, udecl)::rest, c))::rest' -> List.iter maybe_error_many_udecls rest; List.iter (fun (coe, (idl, c)) -> List.iter maybe_error_many_udecls idl) rest'; udecl, id | (_, ([], _))::_ | [] -> assert false in let open DeclareDef in let () = match scope, udecl with | Discharge, Some _ -> let loc = first_id.CAst.loc in let msg = Pp.str "Section variables cannot be polymorphic." in user_err ?loc msg | _ -> () in udecl, List.map (fun (coe, (idl, c)) -> coe, (List.map fst idl, c)) l let do_assumptions ~program_mode ~poly ~scope ~kind nl l = let open Context.Named.Declaration in let env = Global.env () in let udecl, l = process_assumptions_udecls ~scope l in let sigma, udecl = interp_univ_decl_opt env udecl in let l = if poly then (* Separate declarations so that A B : Type puts A and B in different levels. *) List.fold_right (fun (is_coe,(idl,c)) acc -> List.fold_right (fun id acc -> (is_coe, ([id], c)) :: acc) idl acc) l [] else l in (* We interpret all declarations in the same evar_map, i.e. as a telescope. *) let (sigma,_,_),l = List.fold_left_map (fun (sigma,env,ienv) (is_coe,(idl,c)) -> let sigma,(t,imps) = interp_assumption ~program_mode sigma env ienv c in let r = Retyping.relevance_of_type env sigma t in let env = EConstr.push_named_context (List.map (fun {CAst.v=id} -> LocalAssum (make_annot id r,t)) idl) env in let ienv = List.fold_right (fun {CAst.v=id} ienv -> let impls = compute_internalization_data env sigma Variable t imps in Id.Map.add id impls ienv) idl ienv in ((sigma,env,ienv),((is_coe,idl),t,imps))) (sigma,env,empty_internalization_env) l in let sigma = solve_remaining_evars all_and_fail_flags env sigma in (* The universe constraints come from the whole telescope. *) let sigma = Evd.minimize_universes sigma in let nf_evar c = EConstr.to_constr sigma c in let uvars, l = List.fold_left_map (fun uvars (coe,t,imps) -> let t = nf_evar t in let uvars = Univ.LSet.union uvars (Vars.universes_of_constr t) in uvars, (coe,t,imps)) Univ.LSet.empty l in (* XXX: Using `DeclareDef.prepare_parameter` here directly is not possible as we indeed declare several parameters; however, restrict_universe_context should be called in a centralized place IMO, thus I think we should adapt `prepare_parameter` to handle this case too. *) let sigma = Evd.restrict_universe_context sigma uvars in let univs = Evd.check_univ_decl ~poly sigma udecl in let ubinders = Evd.universe_binders sigma in declare_assumptions ~poly ~scope ~kind (univs,ubinders) nl l let context_subst subst (name,b,t,impl) = name, Option.map (Vars.substl subst) b, Vars.substl subst t, impl let context_insection sigma ~poly ctx = let uctx = Evd.universe_context_set sigma in let () = Declare.declare_universe_context ~poly uctx in let fn subst (name,_,_,_ as d) = let d = context_subst subst d in let () = match d with | name, None, t, impl -> let kind = Decls.Context in declare_variable false ~kind t [] impl (CAst.make name) | name, Some b, t, impl -> (* We need to get poly right for check_same_poly *) let univs = if poly then Polymorphic_entry ([| |], Univ.UContext.empty) else Monomorphic_entry Univ.ContextSet.empty in let entry = Declare.definition_entry ~univs ~types:t b in let _ : GlobRef.t = DeclareDef.declare_definition ~name ~scope:DeclareDef.Discharge ~kind:Decls.(IsDefinition Definition) UnivNames.empty_binders entry [] in () in Constr.mkVar name :: subst in let _ : Vars.substl = List.fold_left fn [] ctx in () let context_nosection sigma ~poly ctx = let univs = match ctx, poly with | [_], _ | _, true -> Evd.univ_entry ~poly sigma | _, false -> (* Multiple monomorphic axioms: declare universes separately to avoid redeclaring them. *) let uctx = Evd.universe_context_set sigma in let () = Declare.declare_universe_context ~poly uctx in Monomorphic_entry Univ.ContextSet.empty in let fn subst d = let (name,b,t,_impl) = context_subst subst d in let kind = Decls.(IsAssumption Logical) in let decl = match b with | None -> Declare.ParameterEntry (None,(t,univs),None) | Some b -> let entry = Declare.definition_entry ~univs ~types:t b in Declare.DefinitionEntry entry in let local = if Lib.is_modtype () then Declare.ImportDefaultBehavior else Declare.ImportNeedQualified in let cst = Declare.declare_constant ~name ~kind ~local decl in let () = Declare.assumption_message name in let env = Global.env () in (* why local when is_modtype? *) let () = if Lib.is_modtype() || Option.is_empty b then Classes.declare_instance env sigma None (Lib.is_modtype()) (GlobRef.ConstRef cst) in Constr.mkConstU (cst,instance_of_univ_entry univs) :: subst in let _ : Vars.substl = List.fold_left fn [] ctx in () let context ~poly l = let env = Global.env() in let sigma = Evd.from_env env in let sigma, (_, ((_env, ctx), impls)) = interp_context_evars ~program_mode:false env sigma l in (* Note, we must use the normalized evar from now on! *) let sigma = Evd.minimize_universes sigma in let ce t = Pretyping.check_evars env (Evd.from_env env) sigma t in let () = List.iter (fun decl -> Context.Rel.Declaration.iter_constr ce decl) ctx in (* reorder, evar-normalize and add implicit status *) let ctx = List.rev_map (fun d -> let {binder_name=name}, b, t = RelDecl.to_tuple d in let name = match name with | Anonymous -> user_err Pp.(str "Anonymous variables not allowed in contexts.") | Name id -> id in let b = Option.map (EConstr.to_constr sigma) b in let t = EConstr.to_constr sigma t in let test x = match x.CAst.v with | Some (Name id',_) -> Id.equal name id' | _ -> false in let impl = Glob_term.(if List.exists test impls then Implicit else Explicit) in name,b,t,impl) ctx in if Global.sections_are_opened () then context_insection sigma ~poly ctx else context_nosection sigma ~poly ctx (* Deprecated *) let declare_assumption is_coe ~poly ~scope ~kind typ univs pl imps impl nl name = let open DeclareDef in match scope with | Discharge -> let univs = match univs with | Monomorphic_entry univs -> univs | Polymorphic_entry (_, univs) -> Univ.ContextSet.of_context univs in let () = Declare.declare_universe_context ~poly univs in declare_variable is_coe ~kind typ imps impl name; GlobRef.VarRef name.CAst.v, Univ.Instance.empty | Global local -> declare_axiom is_coe ~poly ~local ~kind typ (univs, pl) imps nl name