Skip to content

Commit 0adbb91

Browse files
committed
refold before evar instantiation
Until now, the algorithm unfolded terms blindly and instantiated an evar with whatever term was on the other side. Now, we remember the terms from the initial unification problem, and whenever we reach a problem of the form `?e = t`, we replace `t` with its initial version.
1 parent eea0e40 commit 0adbb91

File tree

3 files changed

+65
-27
lines changed

3 files changed

+65
-27
lines changed

pretyping/evarconv.ml

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -704,10 +704,11 @@ let rec evar_conv_x flags env evd pbty term1 term2 =
704704
let term1 = apprec_nohdbeta flags env evd term1 in
705705
let term2 = apprec_nohdbeta flags env evd term2 in
706706
let default () =
707+
let hd1 = (whd_nored_state env evd (term1,Stack.empty)) in
708+
let hd2 = (whd_nored_state env evd (term2,Stack.empty)) in
707709
match
708710
evar_eqappr_x flags env evd pbty (Cs_keys_cache.empty ()) None
709-
(whd_nored_state env evd (term1,Stack.empty))
710-
(whd_nored_state env evd (term2,Stack.empty))
711+
(hd1, hd2) hd1 hd2
711712
with
712713
| UnifFailure _ as x ->
713714
if Retyping.is_term_irrelevant env evd term1 ||
@@ -743,8 +744,8 @@ let rec evar_conv_x flags env evd pbty term1 term2 =
743744

744745
and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
745746
keys (* canonical structure keys cache *)
746-
lastUnfolded (* tells which side was last unfolded, if any *)
747-
(term1, sk1 as appr1) (term2, sk2 as appr2) =
747+
lastUnfolded (* tells which side was last unfolded, if any, where `true` means RHS. *)
748+
hds (term1, sk1 as appr1) (term2, sk2 as appr2) =
748749
let quick_fail i = (* not costly, loses info *)
749750
UnifFailure (i, NotSameHead)
750751
in
@@ -781,8 +782,8 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
781782
flags.open_ts env' evd (c'1, Stack.empty) in
782783
let out2 = whd_nored_state env' evd
783784
(lift 1 (Stack.zip evd (term', sk')), Stack.append_app [|EConstr.mkRel 1|] Stack.empty) in
784-
if onleft then evar_eqappr_x flags env' evd CONV keys None out1 out2
785-
else evar_eqappr_x flags env' evd CONV (Cs_keys_cache.flip keys) None out2 out1
785+
if onleft then evar_eqappr_x flags env' evd CONV keys None (out1, out2) out1 out2
786+
else evar_eqappr_x flags env' evd CONV (Cs_keys_cache.flip keys) None (out2, out1) out2 out1
786787
in
787788
let rigids env evd sk term sk' term' =
788789
let nargs = Stack.args_size sk in
@@ -822,8 +823,13 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
822823
3. reduce the redex into M and recursively solve E[?n[inst]] =? E'[M] *)
823824
let switch f a b = if l2r then f a b else f b a in
824825
let delta i =
825-
switch (evar_eqappr_x flags env i pbty keys None) apprF
826-
(whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vskM)
826+
let vskM = Option.get (eval_flexible_term flags.open_ts env evd (fst vskM) (snd vskM)) in
827+
let apprM' = whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vskM in
828+
(* We cheat here. Unfolding here means that we should not go back to the heads
829+
when rediscovering the problem ?e=t, so we put the unfolded term in place of the
830+
head. *)
831+
let hds = (apprM', apprM') in
832+
switch (evar_eqappr_x flags env i pbty keys None hds) apprF apprM'
827833
in
828834
let default i = ise_try i [miller l2r ev apprF apprM;
829835
consume l2r apprF apprM;
@@ -844,8 +850,12 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
844850
let apprM' =
845851
whd_betaiota_deltazeta_for_iota_state flags.open_ts env evd (termM',skM)
846852
in
853+
(* We cheat here. Unfolding here means that we should not go back to the heads
854+
when rediscovering the problem ?e=t, so we put the unfolded term in place of the
855+
head. *)
856+
let hds = if l2r then (fst hds, apprM') else (apprM', snd hds) in
847857
let delta' i =
848-
switch (evar_eqappr_x flags env i pbty keys None) apprF apprM'
858+
switch (evar_eqappr_x flags env i pbty keys None hds) apprF apprM'
849859
in
850860
fun i -> ise_try i [miller l2r ev apprF apprM';
851861
consume l2r apprF apprM'; delta']
@@ -900,7 +910,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
900910
UnifFailure (evd,OccurCheck (fst ev,tR)))])
901911
ev lF tR evd
902912
in
903-
let first_order env i t1 t2 sk1 sk2 =
913+
let first_order env i t1 t2 sk1 sk2 hds =
904914
(* Try first-order unification *)
905915
match ise_stack2 false env i (evar_conv_x flags) sk1 sk2 with
906916
| None, Success i' ->
@@ -912,7 +922,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
912922
(position_problem true pbty,destEvar i' ev1',term2)
913923
else
914924
(* HH: Why not to drop sk1 and sk2 since they unified *)
915-
evar_eqappr_x flags env evd pbty keys None
925+
evar_eqappr_x flags env evd pbty keys None hds
916926
(ev1', sk1) (term2, sk2)
917927
| Some (r,[]), Success i' ->
918928
(* We have sk1'[] = sk2[] for some sk1' s.t. sk1[]=sk1'[r[]] *)
@@ -922,7 +932,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
922932
solve_simple_eqn (conv_fun evar_conv_x) flags env i'
923933
(position_problem false pbty,destEvar i' ev2',Stack.zip i' (term1,r))
924934
else
925-
evar_eqappr_x flags env evd pbty keys None
935+
evar_eqappr_x flags env evd pbty keys None hds
926936
(ev2', sk1) (term2, sk2)
927937
| Some ([],r), Success i' ->
928938
(* Symmetrically *)
@@ -934,7 +944,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
934944
(position_problem true pbty,destEvar i' ev1',Stack.zip i' (term2,r))
935945
else
936946
(* HH: Why not to drop sk1 and sk2 since they unified *)
937-
evar_eqappr_x flags env evd pbty keys None
947+
evar_eqappr_x flags env evd pbty keys None hds
938948
(ev1', sk1) (term2, sk2)
939949
| None, (UnifFailure _ as x) ->
940950
(* sk1 and sk2 have no common outer part *)
@@ -1007,6 +1017,13 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10071017
match (flex_kind_of_term flags env evd term1 sk1,
10081018
flex_kind_of_term flags env evd term2 sk2) with
10091019
| Flexible (sp1,al1), Flexible (sp2,al2) ->
1020+
let k1 = if lastUnfolded = Some true then let (t, sk) = fst hds in flex_kind_of_term flags env evd t sk else Flexible (sp1, al1) in
1021+
let k2 = if lastUnfolded = Some false then let (t, sk) = snd hds in flex_kind_of_term flags env evd t sk else Flexible (sp2, al2) in
1022+
begin match (k1, k2) with
1023+
| Flexible ev1, MaybeFlexible v2 -> flex_maybeflex true ev1 appr1 (snd hds) (snd hds)
1024+
| MaybeFlexible v1, Flexible ev2 -> flex_maybeflex false ev2 appr2 (fst hds) (fst hds)
1025+
| _, Rigid | Rigid, _ -> anomaly (Pp.str "flexible terms cannot fold to rigid ones")
1026+
| _ ->
10101027
(* Notations:
10111028
- "sk" is a stack (or, more abstractly, an evaluation context, written E)
10121029
- "ev" is an evar "?ev", more precisely an evar ?n with an instance inst
@@ -1018,7 +1035,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10181035
1b'. if E₁=E₁'[E₁''] and E₁'=E₂ unifiable, recursively solve E₁''[?n₁[inst₁]] = ?n₂[inst₂]
10191036
recursively solve E2[?n[inst]] = E'2[redex]
10201037
2. fails if neither E₁ nor E₂ is a prefix of the other *)
1021-
let f1 i = first_order env i term1 term2 sk1 sk2
1038+
let f1 i = first_order env i term1 term2 sk1 sk2 hds
10221039
and f2 i =
10231040
if Evar.equal sp1 sp2 then
10241041
match ise_stack2 false env i (evar_conv_x flags) sk1 sk2 with
@@ -1046,12 +1063,13 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10461063
| UnifFailure _ -> quick_fail i
10471064
in
10481065
ise_try evd [f1; f2; f3; f4; f5]
1066+
end
10491067

10501068
| Flexible ev1, MaybeFlexible v2 ->
1051-
flex_maybeflex true ev1 appr1 appr2 v2
1069+
flex_maybeflex true ev1 appr1 appr2 (snd hds)
10521070

10531071
| MaybeFlexible vsk1, Flexible ev2 ->
1054-
flex_maybeflex false ev2 appr2 appr1 vsk1
1072+
flex_maybeflex false ev2 appr2 appr1 (fst hds)
10551073

10561074
| MaybeFlexible (v1', sk1' as vsk1'), MaybeFlexible (v2', sk2' as vsk2') -> begin
10571075
match EConstr.kind evd term1, EConstr.kind evd term2 with
@@ -1071,7 +1089,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10711089
and f2 i =
10721090
let out1 = whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vsk1'
10731091
and out2 = whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vsk2'
1074-
in evar_eqappr_x flags env i pbty keys None out1 out2
1092+
in evar_eqappr_x flags env i pbty keys None hds out1 out2
10751093
in
10761094
ise_try evd [f1; f2]
10771095

@@ -1083,7 +1101,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10831101
and f2 i =
10841102
let out1 = whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vsk1'
10851103
and out2 = whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vsk2'
1086-
in evar_eqappr_x flags env i pbty keys None out1 out2
1104+
in evar_eqappr_x flags env i pbty keys None hds out1 out2
10871105
in
10881106
ise_try evd [f1; f2]
10891107

@@ -1095,7 +1113,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10951113
in
10961114
(match res with
10971115
| Some (f1,args1) ->
1098-
evar_eqappr_x flags env evd pbty keys None (f1,Stack.append_app args1 sk1)
1116+
evar_eqappr_x flags env evd pbty keys None hds (f1,Stack.append_app args1 sk1)
10991117
appr2
11001118
| None -> UnifFailure (evd,NotSameHead))
11011119

@@ -1106,7 +1124,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
11061124
in
11071125
(match res with
11081126
| Some (f2,args2) ->
1109-
evar_eqappr_x flags env evd pbty keys None appr1 (f2,Stack.append_app args2 sk2)
1127+
evar_eqappr_x flags env evd pbty keys None hds appr1 (f2,Stack.append_app args2 sk2)
11101128
| None -> UnifFailure (evd,NotSameHead))
11111129

11121130
| _, _ ->
@@ -1169,14 +1187,14 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
11691187
ise_try i [
11701188
(fun i ->
11711189
if b || !no_cs1 then
1172-
evar_eqappr_x flags env i pbty keys (Some false)
1190+
evar_eqappr_x flags env i pbty keys (Some false) hds
11731191
(whd_betaiota_deltazeta_for_iota_state
11741192
flags.open_ts env i vsk1')
11751193
appr2
11761194
else quick_fail i);
11771195
fun i ->
11781196
if b then quick_fail i else
1179-
evar_eqappr_x flags env i pbty keys (Some true) appr1
1197+
evar_eqappr_x flags env i pbty keys (Some true) hds appr1
11801198
(whd_betaiota_deltazeta_for_iota_state
11811199
flags.open_ts env i vsk2')]
11821200
in
@@ -1195,8 +1213,20 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
11951213
(* When in modulo_betaiota = false case, lambda's are not reduced *)
11961214
(fun i -> exact_ise_stack2 env i (evar_conv_x flags) sk1 sk2)]
11971215

1198-
| Flexible ev1, Rigid -> flex_rigid true ev1 appr1 appr2
1199-
| Rigid, Flexible ev2 -> flex_rigid false ev2 appr2 appr1
1216+
| Flexible ev1, Rigid ->
1217+
let (t2, sk2) as appr2 = snd hds in
1218+
begin match flex_kind_of_term flags env evd t2 sk2 with
1219+
| Flexible ev2 -> anomaly (Pp.str "rigid terms can not fold to flexible ones")
1220+
| MaybeFlexible v2 -> flex_maybeflex true ev1 appr1 appr2 appr2
1221+
| Rigid -> flex_rigid true ev1 appr1 appr2
1222+
end
1223+
| Rigid, Flexible ev2 ->
1224+
let (t1, sk1) as appr1 = fst hds in
1225+
begin match flex_kind_of_term flags env evd t1 sk1 with
1226+
| Flexible ev1 -> anomaly (Pp.str "rigid terms can not fold to flexible ones")
1227+
| MaybeFlexible v1 -> flex_maybeflex false ev2 appr2 appr1 appr1
1228+
| Rigid -> flex_rigid false ev2 appr2 appr1
1229+
end
12001230

12011231
| MaybeFlexible vsk1', Rigid ->
12021232
let f3 i =
@@ -1206,7 +1236,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
12061236
| Inl x -> x
12071237
| Inr _ -> UnifFailure (i,NoCanonicalStructure)
12081238
and f4 i =
1209-
evar_eqappr_x flags env i pbty keys (Some false)
1239+
evar_eqappr_x flags env i pbty keys (Some false) hds
12101240
(whd_betaiota_deltazeta_for_iota_state
12111241
flags.open_ts env i vsk1')
12121242
appr2
@@ -1221,7 +1251,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
12211251
| Inl x -> x
12221252
| Inr _ -> UnifFailure (i,NoCanonicalStructure)
12231253
and f4 i =
1224-
evar_eqappr_x flags env i pbty keys (Some true) appr1
1254+
evar_eqappr_x flags env i pbty keys (Some true) hds appr1
12251255
(whd_betaiota_deltazeta_for_iota_state
12261256
flags.open_ts env i vsk2')
12271257
in

pretyping/evarconv.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ module Cs_keys_cache : sig type t end
159159
val evar_eqappr_x : ?rhs_is_already_stuck:bool -> unify_flags ->
160160
env -> evar_map -> conv_pb ->
161161
Cs_keys_cache.t ->
162-
bool option -> state -> state ->
162+
bool option -> (state * state) -> state -> state ->
163163
Evarsolve.unification_result
164164

165165
val occur_rigidly : Evarsolve.unify_flags ->

test-suite/success/evars.v

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,3 +433,11 @@ Fail Type let x := _ in
433433
let t := type of x in
434434
unify x (abs t);
435435
exact 0).
436+
437+
(* Check that evars are instantiated with least unfolded terms *)
438+
Module TestFold.
439+
Structure S := {T : Type}.
440+
Definition nat' : Type := nat.
441+
Canonical nat'_S := {| T := nat' |}.
442+
Check (eq_refl : (fun x => (id x, x)) _ = (nat', T _)).
443+
End TestFold.

0 commit comments

Comments
 (0)