Skip to content

Commit e2f9a2c

Browse files
committed
[TC] local binders in evar scope during precompile + link.cs
1 parent ff98925 commit e2f9a2c

File tree

8 files changed

+262
-13
lines changed

8 files changed

+262
-13
lines changed

apps/tc/elpi/base.elpi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,8 @@ pred close-term-no-prune-ty i:(term -> list prop), i:term, o:list prop.
163163
close-term-no-prune-ty (x\ []) _ [] :- !.
164164
close-term-no-prune-ty (x\ [X x | Xs x]) Ty [@pi-decl `x` Ty x\ X x | Xs'] :- !,
165165
close-term-no-prune-ty Xs Ty Xs'.
166+
167+
pred close-term-no-prune-fun i:(term -> list term), i:term, o:list term.
168+
close-term-no-prune-fun (x\ []) _ [] :- !.
169+
close-term-no-prune-fun (x\ [X x | Xs x]) Ty [fun _ Ty X | Xs'] :-
170+
close-term-no-prune-fun Xs Ty Xs'.

apps/tc/elpi/ho_compile.elpi

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,15 @@ namespace tc {
2424
decompile-term-aux (sort _ as T) L T' L :- !, copy T T', !.
2525
decompile-term-aux (uvar as X) L X L :- !.
2626
decompile-term-aux (primitive _ as X) L X L :- !.
27+
decompile-term-aux (tc.coercion T S) (pr [X|Xs] L1) Y (pr Xs' L3) :- !,
28+
name Y X S,
29+
decompile-term-aux T (pr Xs L1) T' (pr Xs' L2),
30+
P = tc.link.cs Y T',
31+
L3 = [P | L2].
2732
decompile-term-aux (tc.canonical-projection T S _) (pr [X|Xs] L1) Y (pr Xs' L3) :- !,
2833
name Y X S,
2934
decompile-term-aux T (pr Xs L1) T' (pr Xs' L2),
30-
P = coq.unify-eq Y T' ok,
35+
P = tc.link.cs Y T',
3136
L3 = [P | L2].
3237

3338
decompile-term-aux (tc.maybe-eta-tm T S) (pr [X|XS] L1) Y (pr XS' [NL | L2]) :- !,
@@ -124,6 +129,7 @@ namespace tc {
124129
(pi t s r \ copy (tc.canonical-projection t s _) r :- !, copy t r, !) =>
125130
(pi t s r \ copy (tc.prod-range t s) r :- !, copy t r, !) =>
126131
(pi t s r \ copy (tc.maybe-llam-tm t s) r :- !, copy t r, !) =>
132+
(pi t s r \ copy (tc.coercion t s) r :- !, copy t r, !) =>
127133
std.assert! (copy A B) "[TC] clean-term error".
128134

129135
pred main
@@ -316,6 +322,8 @@ namespace tc {
316322

317323
% Type Var Cnt uvar-pair-list
318324
pred make-pairs-aux i:term, i:term, o:list prop.
325+
make-pairs-aux Ty (fun _ _ IBo) L' :- !,
326+
pi x\ make-pairs-aux Ty (IBo x) (L x), close-prop-no-prune L L'.
319327
make-pairs-aux (prod _ Ty Bo) V [pi x\ uvar-pair x Ty X' :- x == V, ! | L] :- !,
320328
pi x\ make-pairs-aux (Bo x) X' L.
321329
make-pairs-aux _ _ [].
@@ -335,11 +343,18 @@ namespace tc {
335343

336344
pred decompile-problematic-term i:term, i:list prop, o:term, o:list prop.
337345
decompile-problematic-term (primitive _ as C) A C A :- !.
338-
339-
decompile-problematic-term (tc.maybe-eta-tm T S) L V [tc.link.eta V T' | L2] :-
340-
prune V S, !, fold-map T L T' L2.
341346

342-
decompile-problematic-term (tc.prod-range T _) A T' A' :-
347+
% there is no need to decompile T since no precompilation is done inside coercions
348+
decompile-problematic-term (tc.coercion T S) L1 Y [tc.link.cs Y T|L1] :- !,
349+
prune Y S.
350+
% there is no need to decompile T since no precompilation is done inside CS
351+
decompile-problematic-term (tc.canonical-projection T S _) L1 Y [tc.link.cs Y T|L1] :- !,
352+
prune Y S.
353+
354+
decompile-problematic-term (tc.maybe-eta-tm T S) L V [tc.link.eta V T' | L2] :- !,
355+
prune V S, fold-map T L T' L2.
356+
357+
decompile-problematic-term (tc.prod-range T _) A T' A' :- !,
343358
fold-map T A T' A'.
344359

345360
decompile-problematic-term (tc.maybe-llam-tm (app [app[H|S] | NPF]) Sc) L Z [NL|L'] :- !,
@@ -399,6 +414,10 @@ namespace tc {
399414
build-eta-links-of-vars-aux Hd S L',
400415
build-eta-links-of-vars Vars L'',
401416
std.append L' L'' L.
417+
build-eta-links-of-vars [fun _ Ty Bo|Vars] L :-
418+
(pi x\ build-eta-links-of-vars [Bo x] (L' x), close-term-no-prune-ty L' Ty L''),
419+
build-eta-links-of-vars Vars L''',
420+
std.append L'' L''' L.
402421
}
403422

404423
% Goal Goal' Links

apps/tc/elpi/ho_link.elpi

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,34 @@ namespace tc {
130130
}
131131
}
132132

133+
namespace cs {
134+
pred cs i:term, i:term.
135+
% TODO: suspend link on vars in T
136+
cs V T :- var V, !, get-vars T Vars, declare_constraint (cs V T) [_, V | Vars].
137+
cs T1 T2 :- coq.unify-eq T1 T2 ok.
138+
139+
% pred unify-rebinding-names i:list prop, i:list prop, i:term, i:term.
140+
% unify-rebinding-names [] T1 [] T2 (unify-eq T1V T2) :- !, copy T1 T1V.
141+
% unify-rebinding-names [N|NS] T1 [V|VS] T2 C :- !, copy N V => unify-rebinding-names NS T1 VS T2 C.
142+
% unify-rebinding-names [] T1 VS T2 C :- !, unify-rebinding-names [] {coq.subst-prod VS T1} [] T2 C. % FIXME: reduction
143+
% unify-rebinding-names [_|NS] (prod _ _ F) [] T2 C :- !, % FIXME: reduction
144+
% assert! (pi x\ F x = F1) "restriction bug", unify-rebinding-names NS F1 [] T2 C.
145+
146+
pred unify-under-ctx i:list term, i:list term, i:term, i:term, i:term, i:term.
147+
unify-under-ctx [] [] A B V1 V2 :- copy A A', copy V1 V1', !, coq.unify-eq A' B ok, !, V1' = V2.
148+
unify-under-ctx [X|XS] [Y|YS] A B V1 V2:- (copy X Y :- !) => unify-under-ctx XS YS A B V1 V2.
149+
150+
% TODO: there could be two same variables suspended on non unifyable
151+
% terms, this should be detected and raise a failure.
152+
% An example of this is in test/canonical_struct.v
153+
constraint cache def decl coq.unify-eq ?- solve-cs cs {
154+
rule solve-cs \ (Ctx ?- cs A B) <=> (Ctx => coq.unify-eq A B ok).
155+
rule (Ctx1 ?- cs (uvar A L1 as X) T1) \ (Ctx2 ?- cs (uvar A L2 as Y) T2) <=>
156+
(Ctx2 => unify-under-ctx L1 L2 T1 T2 X Y).
157+
rule \ solve-cs.
158+
}
159+
}
160+
133161
pred eta i:term, o:term.
134162
eta A B :- eta.eta A B.
135163

@@ -141,5 +169,11 @@ namespace tc {
141169

142170
pred solve-llam.
143171
solve-llam :- declare_constraint solve-llam [_].
172+
173+
pred cs i:term, i:term.
174+
cs A B :- cs.cs A B.
175+
176+
pred solve-cs.
177+
solve-cs :- declare_constraint solve-cs [_].
144178
}
145179
}

apps/tc/elpi/ho_precompile.elpi

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ namespace tc {
106106
precompile-aux _ (pglobal _ _ as C) A C A :- !.
107107
precompile-aux _ (sort _ as C) A C A :- !.
108108
precompile-aux _ (primitive _ as C) A C A :- !.
109+
precompile-aux _ T A (tc.coercion T Scope) (s A) :- coq.safe-dest-app T HD _, tc.coercion-unify HD, !, free-var Scope.
109110
precompile-aux _ (app [global (const C) | _] as T) A (tc.canonical-projection T Scope N) (s A) :- coq.env.projection? C N, !, free-var Scope.
110111
precompile-aux _ (app [primitive (proj P _) | _] as T) A (tc.canonical-projection T Scope 0) (s A) :- coq.env.primitive-projection? P _, !, free-var Scope.
111112

@@ -229,12 +230,20 @@ namespace tc {
229230
precompile-aux (pglobal _ _ as C) A C A :- !.
230231
precompile-aux (sort _ as C) A C A :- !.
231232
precompile-aux (primitive _ as C) A C A :- !.
233+
234+
precompile-aux T A (tc.coercion T Scope) A :-
235+
coq.safe-dest-app T HD _, tc.coercion-unify HD, !, names Scope.
236+
precompile-aux (app [global (const C) | _] as T) A (tc.canonical-projection T Scope N) A :-
237+
coq.env.projection? C N, !, names Scope.
238+
precompile-aux (app [primitive (proj P _) | _] as T) A (tc.canonical-projection T Scope 0) A :-
239+
coq.env.primitive-projection? P _, !, names Scope.
240+
232241

233242
% Detect maybe-eta term
234243
precompile-aux (fun Name Ty B as T) N (tc.maybe-eta-tm (fun Name Ty' B') Scope) M :-
235244
maybe-eta T, !,
236245
names Scope,
237-
(pi x\ precompile-aux (B x) N (B' x) M'),
246+
std.assert! (pi x\ precompile-aux (B x) N (B' x) (MM x), close-term-no-prune-fun MM Ty M') "[TC] should not fail1",
238247
precompile-aux Ty M' Ty' M.
239248

240249
% Detect maybe-beta term
@@ -244,10 +253,9 @@ namespace tc {
244253
names Scope1,
245254
std.fold-map NPF N precompile-aux NPF1 M.
246255

247-
% In the goal there are
248256
precompile-aux (prod Name Ty B) N (tc.prod-range (prod Name Ty' B') (r-ar z MaxAr)) P :- !,
249257
count-prod Ty MaxAr,
250-
std.assert! (pi x\ precompile-aux (B x) N (B' x) M) "[TC] should not fail",
258+
std.assert! (pi x\ precompile-aux (B x) N (B' x) (MM x), close-term-no-prune-fun MM Ty M) "[TC] should not fail2",
251259
precompile-aux Ty M Ty' P.
252260

253261
% Working with fun

apps/tc/elpi/solver.elpi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ namespace tc {
3232
if-true print-compiled-goal (coq.say "[TC] the compiled goal is" Q), !,
3333
tc.time-it tc.oTC-time-instance-search (
3434
do PostProcess, Q,
35+
tc.link.solve-cs,
3536
tc.link.solve-eta, % Trigger eta links
3637
tc.link.solve-llam % Trigger llam links
3738
) "instance search".

apps/tc/elpi/tc_aux.elpi

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,12 @@ namespace tc {
219219
list term -> % The list of FV in the precomp subterm
220220
int ->
221221
term.
222+
223+
:index (5)
224+
pred coercion-unify i:term.
225+
226+
type coercion
227+
term ->
228+
list term ->
229+
term.
222230
}

apps/tc/tests/canonical_struct.v

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,133 @@ Module CS5.
9999
Unshelve.
100100
apply (ofe_any nat).
101101
Qed.
102-
End CS5.
102+
End CS5.
103+
104+
Module CS6.
105+
Structure ofe := Ofe { ofe_car :> Type; }.
106+
Structure cmra := Cmra { cmra_car :> Type; }.
107+
108+
Coercion cmra_ofeO (A : cmra) := Ofe A.
109+
110+
Elpi Accumulate tc.db lp:{{
111+
tc.coercion-unify {{cmra_ofeO}}.
112+
}}.
113+
114+
Canonical Structure ofe_nat := Ofe nat.
115+
Canonical Structure cmra_nat := Cmra nat.
116+
117+
Class C (i: ofe).
118+
119+
Instance i: forall (c : cmra), C (cmra_ofeO c) := {}.
120+
121+
Goal C ofe_nat.
122+
apply _.
123+
Qed.
124+
End CS6.
125+
126+
Module CS7.
127+
Structure ofe := Ofe { ofe_car :> Type; }.
128+
Structure cmra := Cmra { cmra_car :> Type; }.
129+
130+
Coercion cmra_ofeO (A : cmra) := Ofe A.
131+
132+
Elpi Accumulate tc.db lp:{{
133+
tc.coercion-unify {{cmra_ofeO}}.
134+
}}.
135+
136+
Canonical Structure ofe_bool := Ofe bool.
137+
Canonical Structure cmra_bool := Cmra bool.
138+
139+
Class C (i: ofe).
140+
141+
Class D (i: Type).
142+
Instance d : D bool := {}.
143+
144+
Instance i: forall (c : cmra), D (cmra_car c) -> C (cmra_ofeO c) := {}.
145+
Elpi Print TC.Solver.
146+
147+
Goal C ofe_bool.
148+
apply _.
149+
Qed.
150+
151+
Canonical Structure ofe_nat := Ofe nat.
152+
Canonical Structure cmra_nat := Cmra nat.
153+
154+
Goal exists a, C a.
155+
eexists.
156+
apply _.
157+
Qed.
158+
End CS7.
159+
160+
Module CS8.
161+
Structure ofe := Ofe { ofe_car :> Type; }.
162+
Canonical Structure ofe_bool := Ofe bool.
163+
Class C (i : Type).
164+
Instance i : C ofe_bool := {}.
165+
166+
(*
167+
Test for constraint activation using tc.link.solve-cs: After
168+
tc-instance-search, we have the suspended goal `tc.link.cs X ofe_bool` that
169+
must be activated. This activation need to load the context before the
170+
call to unify-eq since we need to load the type of `x`
171+
*)
172+
Goal forall (x: nat), exists X, C X.
173+
eexists. apply _.
174+
Qed.
175+
176+
(* TODO: error in llam link *)
177+
(* Goal forall (x: nat), exists X, C (X x).
178+
eexists.
179+
Elpi Trace Browser.
180+
(* Elpi TC Solver Deactivate TC.Solver. *)
181+
apply _.
182+
Qed *)
183+
End CS8.
184+
185+
Module CS9.
186+
Structure ofe := Ofe { ofe_car :> Type; }.
187+
Canonical Structure ofe_bool := Ofe bool.
188+
Canonical Structure ofe_nat := Ofe nat.
189+
190+
Class loop.
191+
Instance l : loop -> loop := {}.
192+
Class C (i : Type) (i : Type).
193+
Instance i : loop -> C ofe_bool ofe_nat := {}.
194+
195+
(*
196+
Here we have two suspended goal on X with cs links. The same variable
197+
is linked with ofe_bool and ofe_nat. Since they don't unfy, the instance
198+
`i` cannot be used.
199+
*)
200+
Goal exists X, C X X.
201+
eexists.
202+
Fail apply _.
203+
Abort.
204+
End CS9.
205+
206+
Module CS10.
207+
Structure ofe := Ofe { ofe_car :> Type; }.
208+
Canonical Structure ofe_bool := Ofe bool.
209+
210+
Class C (i : Type).
211+
Instance i : C bool := {}.
212+
213+
(* Here the projection is in the goal *)
214+
Goal C (ofe_car ofe_bool). apply _. Qed.
215+
End CS10.
216+
217+
Module CS11.
218+
Structure ofe := Ofe { ofe_car :> Type; }.
219+
Canonical Structure ofe_bool := Ofe bool.
220+
221+
Class D (i : ofe).
222+
Instance d : D (ofe_bool) := {}.
223+
224+
Class C (i : Type).
225+
Instance i X: D X -> C (ofe_car X) := {}.
226+
227+
(* Here the projection is in the goal *)
228+
Goal exists X, C (ofe_car X). eexists.
229+
apply _.
230+
Show Proof.
231+
Qed.

apps/tc/tests/test.v

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,54 @@ Module HO_10.
277277
Qed.
278278
End HO_10.
279279

280+
Module HO_11.
281+
Class Unit (i : Prop).
282+
Instance i F : Unit (forall (f : Prop), F f) := {}.
283+
Goal Unit (forall x, x).
284+
apply _.
285+
Qed.
286+
End HO_11.
287+
288+
Module HO_12.
289+
Class Unit (i : Prop).
290+
Instance i : Unit (forall x, x) := {}.
291+
Set Printing Existential Instances.
292+
Goal forall (y: Prop), exists (F: Prop -> Prop), Unit (forall x, F x).
293+
intros.
294+
eexists ?[F].
295+
Unshelve.
296+
2: { refine (fun x => _); shelve. }
297+
simpl.
298+
Set Printing Existential Instances.
299+
apply _.
300+
Qed.
301+
End HO_12.
302+
303+
Module HO_13.
304+
Class Unit (i : Prop).
305+
Class PP (i : Prop -> Prop -> Prop).
306+
Axiom f : Prop -> Prop -> Prop.
307+
Instance i F : PP (fun x y => F y x) -> Unit (forall (x y: Prop), F y x) := {}.
308+
Instance j : PP (fun x y => f y x) := {}.
309+
Check _ : (Unit (forall x y, _)).
310+
311+
Goal exists (X: Prop -> Prop -> Prop), Unit (forall x y, X x y).
312+
eexists.
313+
Unshelve.
314+
2: { refine (fun _ _ => _); shelve. }
315+
simpl.
316+
apply _.
317+
Qed.
318+
319+
Elpi Query TC.Solver lp:{{
320+
std.spy-do![Goal = {{Unit (forall x y, lp:(F x y))}},
321+
tc.build-query-from-goal Goal Proof Q PP,
322+
do PP, Q,
323+
std.assert! (Proof = {{i f j}}) "Error"].
324+
}}.
325+
End HO_13.
326+
327+
280328
Module HO_scope_check1.
281329
Axiom f : Type -> (Type -> Type) -> Type.
282330
Axiom g : Type -> Type -> Type.
@@ -565,7 +613,4 @@ Module CoqUvar4.
565613
do 1 eexists.
566614
apply _.
567615
Qed.
568-
End CoqUvar4.
569-
570-
(* TODO: add test with negative premise having a variable with type (M A) where M and A are coq uvar,
571-
this is in order to clean-term with llam *)
616+
End CoqUvar4.

0 commit comments

Comments
 (0)