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
open Util
open Names
module NamedDecl = Context.Named.Declaration
let refine_by_tactic ~name ~poly env sigma ty tac =
let eff = Evd.eval_side_effects sigma in
let old_len = Safe_typing.length_private @@ Evd.seff_private eff in
let sigma = Evd.push_future_goals sigma in
let prf = Proof.start ~name ~poly sigma [env, ty] in
let (prf, _, ()) =
try Proof.run_tactic env tac prf
with Logic_monad.TacticFailure e as src ->
let (_, info) = Exninfo.capture src in
Exninfo.iraise (e, info)
in
let Proof.{ goals; stack; sigma; entry } = Proof.data prf in
let () = assert (stack = []) in
let ans = match Proofview.initial_goals entry with
| [_, c, _] -> c
| _ -> assert false
in
let ans = EConstr.to_constr ~abort_on_undefined_evars:false sigma ans in
let neff = Evd.seff_private @@ Evd.eval_side_effects sigma in
let new_len = Safe_typing.length_private neff in
let neff, _ = Safe_typing.pop_private neff (new_len - old_len) in
let sigma = Evd.set_side_effects eff sigma in
let _goals, sigma = Evd.pop_future_goals sigma in
let sigma = List.fold_right Evd.declare_future_goal goals sigma in
let (ans, uctx) = Safe_typing.inline_private_constants env ((ans, Univ.ContextSet.empty), neff) in
let sigma = Evd.merge_universe_context_set ~sideff:true UState.UnivRigid sigma uctx in
EConstr.of_constr ans, sigma
exception OpenProof
let () = CErrors.register_handler begin function
| OpenProof ->
let open Pp in
Some (str "Attempt to save an incomplete proof.")
| _ -> None
end
let rec shrink ctx sign c t accu =
let open Constr in
let open Vars in
match ctx, sign with
| [], [] -> (c, t, accu)
| p :: ctx, decl :: sign ->
if noccurn 1 c && noccurn 1 t then
let c = subst1 mkProp c in
let t = subst1 mkProp t in
shrink ctx sign c t accu
else
let c = Term.mkLambda_or_LetIn p c in
let t = Term.mkProd_or_LetIn p t in
let accu = if Context.Rel.Declaration.is_local_assum p
then EConstr.mkVar (NamedDecl.get_id decl) :: accu
else accu
in
shrink ctx sign c t accu
| _ -> assert false
let shrink_entry sign body typ =
let (ctx, body, typ) = Term.decompose_lambda_prod_n_decls (List.length sign) body typ in
let (body, typ, args) = shrink ctx sign body typ [] in
body, typ, args
let build_constant_by_tactic ~name ~sigma ~env ~sign ~poly typ tac =
let pfenv = Environ.reset_with_named_context sign env in
let proof = Proof.start ~name ~poly sigma [pfenv, typ] in
let proof, status = Proof.solve env (Goal_select.select_nth 1) None tac proof in
let (body, typ, output_ustate) =
let Proof.{ entry; sigma = evd } = Proof.data proof in
let body, typ = match Proofview.initial_goals entry with
| [_, body, typ] -> body, typ
| _ -> assert false
in
let () = if not @@ Proof.is_done proof then raise OpenProof in
let evd = Evd.minimize_universes evd in
let to_constr c = match EConstr.to_constr_opt evd c with
| Some p -> p
| None -> raise OpenProof
in
let body = to_constr body in
let typ = to_constr typ in
(body, typ, Evd.ustate evd)
in
let univs =
let used_univs = Vars.universes_of_constr typ in
let used_univs = Vars.universes_of_constr body ~init:used_univs in
let uctx = UState.restrict output_ustate used_univs in
UState.check_univ_decl ~poly uctx UState.default_univ_decl
in
let { Proof.sigma } = Proof.data proof in
let sigma = Evd.set_universe_context sigma output_ustate in
(univs, body, typ), status, sigma
let build_by_tactic env ~uctx ~poly ~typ tac =
let name = Id.of_string "temporary_proof" in
let sign = Environ.(val_of_named_context (named_context env)) in
let sigma = Evd.from_ctx uctx in
let (univs, body, typ), status, sigma = build_constant_by_tactic ~name ~env ~sigma ~sign ~poly typ tac in
let uctx = Evd.ustate sigma in
let effs = Evd.seff_private @@ Evd.eval_side_effects sigma in
let body, ctx = Safe_typing.inline_private_constants env ((body, Univ.ContextSet.empty), effs) in
let _uctx = UState.merge_universe_context ~sideff:true Evd.univ_rigid uctx ctx in
body, typ, univs, status, uctx
let build_by_tactic_opt env ~uctx ~poly ~typ tac =
try Some (build_by_tactic env ~uctx ~poly ~typ tac)
with OpenProof -> None
let = function
| UState.Monomorphic_entry ctx ->
Entries.Monomorphic_entry, ctx
| UState.Polymorphic_entry uctx -> Entries.Polymorphic_entry uctx, Univ.ContextSet.empty
let declare_abstract ~name ~poly ~sign ~secsign ~opaque ~solve_tac env sigma concl =
let (const, safe, sigma') =
try build_constant_by_tactic ~name ~poly ~env ~sigma ~sign:secsign concl solve_tac
with Logic_monad.TacticFailure e as src ->
let (_, info) = Exninfo.capture src in
Exninfo.iraise (e, info)
in
let (univs, body, typ) = const in
let sigma = Evd.drop_new_defined ~original:sigma sigma' in
let body, typ, args = shrink_entry sign body typ in
let ts = Environ.oracle env in
let cst, effs =
let effs = Evd.eval_side_effects sigma in
let de, ctx =
let univ_entry, ctx = extract_monomorphic (fst univs) in
if not opaque then
Safe_typing.DefinitionEff { Entries.definition_entry_body = body;
definition_entry_secctx = None;
definition_entry_type = Some typ;
definition_entry_universes = univ_entry;
definition_entry_inline_code = false;
}, ctx
else
let secctx =
let env = Global.env () in
let hyps =
if List.is_empty (Environ.named_context env) then Id.Set.empty
else
let ids_typ = Environ.global_vars_set env typ in
let vars = Environ.global_vars_set env body in
Id.Set.union ids_typ vars
in
Environ.really_needed env hyps
in
Safe_typing.OpaqueEff { Entries.opaque_entry_body = body;
opaque_entry_secctx = secctx;
opaque_entry_type = typ;
opaque_entry_universes = univ_entry;
},
ctx
in
Evd.push_side_effects ~ts name de ctx effs
in
let sigma = Evd.emit_side_effects effs sigma in
let inst = match univs with
| UState.Monomorphic_entry _, _ -> UVars.Instance.empty
| UState.Polymorphic_entry uctx, _ -> UVars.UContext.instance uctx
in
let lem = EConstr.of_constr (Constr.mkConstU (cst, inst)) in
sigma, lem, args, safe