Skip to content

Commit df2a00a

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 8e6284f commit df2a00a

File tree

3 files changed

+65
-28
lines changed

3 files changed

+65
-28
lines changed

pretyping/evarconv.ml

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -692,10 +692,11 @@ let rec evar_conv_x flags env evd pbty term1 term2 =
692692
let term1 = apprec_nohdbeta flags env evd term1 in
693693
let term2 = apprec_nohdbeta flags env evd term2 in
694694
let default () =
695+
let hd1 = (whd_nored_state env evd (term1,Stack.empty)) in
696+
let hd2 = (whd_nored_state env evd (term2,Stack.empty)) in
695697
match
696698
evar_eqappr_x flags env evd pbty (Cs_keys_cache.empty ()) None
697-
(whd_nored_state env evd (term1,Stack.empty))
698-
(whd_nored_state env evd (term2,Stack.empty))
699+
(hd1, hd2) hd1 hd2
699700
with
700701
| UnifFailure _ as x ->
701702
if Retyping.is_term_irrelevant env evd term1 ||
@@ -731,8 +732,8 @@ let rec evar_conv_x flags env evd pbty term1 term2 =
731732

732733
and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
733734
keys (* canonical structure keys cache *)
734-
lastUnfolded (* tells which side was last unfolded, if any *)
735-
(term1, sk1 as appr1) (term2, sk2 as appr2) =
735+
lastUnfolded (* tells which side was last unfolded, if any, where `true` means RHS. *)
736+
hds (term1, sk1 as appr1) (term2, sk2 as appr2) =
736737
let quick_fail i = (* not costly, loses info *)
737738
UnifFailure (i, NotSameHead)
738739
in
@@ -769,8 +770,8 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
769770
flags.open_ts env' evd (c'1, Stack.empty) in
770771
let out2 = whd_nored_state env' evd
771772
(lift 1 (Stack.zip evd (term', sk')), Stack.append_app [|EConstr.mkRel 1|] Stack.empty) in
772-
if onleft then evar_eqappr_x flags env' evd CONV keys None out1 out2
773-
else evar_eqappr_x flags env' evd CONV (Cs_keys_cache.flip keys) None out2 out1
773+
if onleft then evar_eqappr_x flags env' evd CONV keys None (out1, out2) out1 out2
774+
else evar_eqappr_x flags env' evd CONV (Cs_keys_cache.flip keys) None (out2, out1) out2 out1
774775
in
775776
let rigids env evd sk term sk' term' =
776777
let nargs = Stack.args_size sk in
@@ -809,9 +810,14 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
809810
recursively solve E2[?n[inst]] = E'2[redex]
810811
3. reduce the redex into M and recursively solve E[?n[inst]] =? E'[M] *)
811812
let switch f a b = if l2r then f a b else f b a in
812-
let delta i =
813-
switch (evar_eqappr_x flags env i pbty keys None) apprF
814-
(whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vskM)
813+
let delta i =
814+
let vskM = Option.get (eval_flexible_term flags.open_ts env evd (fst vskM) (snd vskM)) in
815+
let apprM' = whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vskM in
816+
(* We cheat here. Unfolding here means that we should not go back to the heads
817+
when rediscovering the problem ?e=t, so we put the unfolded term in place of the
818+
head. *)
819+
let hds = (apprM', apprM') in
820+
switch (evar_eqappr_x flags env i pbty keys None hds) apprF apprM'
815821
in
816822
let default i = ise_try i [miller l2r ev apprF apprM;
817823
consume l2r apprF apprM;
@@ -832,8 +838,12 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
832838
let apprM' =
833839
whd_betaiota_deltazeta_for_iota_state flags.open_ts env evd (termM',skM)
834840
in
841+
(* We cheat here. Unfolding here means that we should not go back to the heads
842+
when rediscovering the problem ?e=t, so we put the unfolded term in place of the
843+
head. *)
844+
let hds = if l2r then (fst hds, apprM') else (apprM', snd hds) in
835845
let delta' i =
836-
switch (evar_eqappr_x flags env i pbty keys None) apprF apprM'
846+
switch (evar_eqappr_x flags env i pbty keys None hds) apprF apprM'
837847
in
838848
fun i -> ise_try i [miller l2r ev apprF apprM';
839849
consume l2r apprF apprM'; delta']
@@ -888,7 +898,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
888898
UnifFailure (evd,OccurCheck (fst ev,tR)))])
889899
ev lF tR evd
890900
in
891-
let first_order env i t1 t2 sk1 sk2 =
901+
let first_order env i t1 t2 sk1 sk2 hds =
892902
(* Try first-order unification *)
893903
match ise_stack2 false env i (evar_conv_x flags) sk1 sk2 with
894904
| None, Success i' ->
@@ -900,7 +910,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
900910
(position_problem true pbty,destEvar i' ev1',term2)
901911
else
902912
(* HH: Why not to drop sk1 and sk2 since they unified *)
903-
evar_eqappr_x flags env evd pbty keys None
913+
evar_eqappr_x flags env evd pbty keys None hds
904914
(ev1', sk1) (term2, sk2)
905915
| Some (r,[]), Success i' ->
906916
(* We have sk1'[] = sk2[] for some sk1' s.t. sk1[]=sk1'[r[]] *)
@@ -910,7 +920,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
910920
solve_simple_eqn (conv_fun evar_conv_x) flags env i'
911921
(position_problem false pbty,destEvar i' ev2',Stack.zip i' (term1,r))
912922
else
913-
evar_eqappr_x flags env evd pbty keys None
923+
evar_eqappr_x flags env evd pbty keys None hds
914924
(ev2', sk1) (term2, sk2)
915925
| Some ([],r), Success i' ->
916926
(* Symmetrically *)
@@ -922,7 +932,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
922932
(position_problem true pbty,destEvar i' ev1',Stack.zip i' (term2,r))
923933
else
924934
(* HH: Why not to drop sk1 and sk2 since they unified *)
925-
evar_eqappr_x flags env evd pbty keys None
935+
evar_eqappr_x flags env evd pbty keys None hds
926936
(ev1', sk1) (term2, sk2)
927937
| None, (UnifFailure _ as x) ->
928938
(* sk1 and sk2 have no common outer part *)
@@ -996,6 +1006,12 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
9961006
match (flex_kind_of_term flags env evd term1 sk1,
9971007
flex_kind_of_term flags env evd term2 sk2) with
9981008
| Flexible (sp1,al1), Flexible (sp2,al2) ->
1009+
begin match ((if lastUnfolded = Some true then let (t, sk) = fst hds in flex_kind_of_term flags env evd t sk else Flexible (sp1, al1)),
1010+
if lastUnfolded = Some false then let (t, sk) = snd hds in flex_kind_of_term flags env evd t sk else Flexible (sp2, al2)) with
1011+
| Flexible ev1, MaybeFlexible v2 -> flex_maybeflex true ev1 appr1 (snd hds) (snd hds)
1012+
| MaybeFlexible v1, Flexible ev2 -> flex_maybeflex false ev2 appr2 (fst hds) (fst hds)
1013+
| _, Rigid | Rigid, _ -> anomaly (Pp.str "flexible terms cannot fold to rigid ones")
1014+
| _ ->
9991015
(* Notations:
10001016
- "sk" is a stack (or, more abstractly, an evaluation context, written E)
10011017
- "ev" is an evar "?ev", more precisely an evar ?n with an instance inst
@@ -1007,7 +1023,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10071023
1b'. if E₁=E₁'[E₁''] and E₁'=E₂ unifiable, recursively solve E₁''[?n₁[inst₁]] = ?n₂[inst₂]
10081024
recursively solve E2[?n[inst]] = E'2[redex]
10091025
2. fails if neither E₁ nor E₂ is a prefix of the other *)
1010-
let f1 i = first_order env i term1 term2 sk1 sk2
1026+
let f1 i = first_order env i term1 term2 sk1 sk2 hds
10111027
and f2 i =
10121028
if Evar.equal sp1 sp2 then
10131029
match ise_stack2 false env i (evar_conv_x flags) sk1 sk2 with
@@ -1035,12 +1051,13 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10351051
| UnifFailure _ -> quick_fail i
10361052
in
10371053
ise_try evd [f1; f2; f3; f4; f5]
1054+
end
10381055

10391056
| Flexible ev1, MaybeFlexible v2 ->
1040-
flex_maybeflex true ev1 appr1 appr2 v2
1057+
flex_maybeflex true ev1 appr1 appr2 (snd hds)
10411058

10421059
| MaybeFlexible vsk1, Flexible ev2 ->
1043-
flex_maybeflex false ev2 appr2 appr1 vsk1
1060+
flex_maybeflex false ev2 appr2 appr1 (fst hds)
10441061

10451062
| MaybeFlexible (v1', sk1' as vsk1'), MaybeFlexible (v2', sk2' as vsk2') -> begin
10461063
match EConstr.kind evd term1, EConstr.kind evd term2 with
@@ -1060,7 +1077,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10601077
and f2 i =
10611078
let out1 = whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vsk1'
10621079
and out2 = whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vsk2'
1063-
in evar_eqappr_x flags env i pbty keys None out1 out2
1080+
in evar_eqappr_x flags env i pbty keys None hds out1 out2
10641081
in
10651082
ise_try evd [f1; f2]
10661083

@@ -1072,7 +1089,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10721089
and f2 i =
10731090
let out1 = whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vsk1'
10741091
and out2 = whd_betaiota_deltazeta_for_iota_state flags.open_ts env i vsk2'
1075-
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
10761093
in
10771094
ise_try evd [f1; f2]
10781095

@@ -1084,7 +1101,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10841101
in
10851102
(match res with
10861103
| Some (f1,args1) ->
1087-
evar_eqappr_x flags env evd pbty keys None (f1,Stack.append_app args1 sk1)
1104+
evar_eqappr_x flags env evd pbty keys None hds (f1,Stack.append_app args1 sk1)
10881105
appr2
10891106
| None -> UnifFailure (evd,NotSameHead))
10901107

@@ -1095,7 +1112,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
10951112
in
10961113
(match res with
10971114
| Some (f2,args2) ->
1098-
evar_eqappr_x flags env evd pbty keys None appr1 (f2,Stack.append_app args2 sk2)
1115+
evar_eqappr_x flags env evd pbty keys None hds appr1 (f2,Stack.append_app args2 sk2)
10991116
| None -> UnifFailure (evd,NotSameHead))
11001117

11011118
| _, _ ->
@@ -1160,14 +1177,14 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
11601177
ise_try i [
11611178
(fun i ->
11621179
if b || !no_cs1 then
1163-
evar_eqappr_x flags env i pbty keys (Some false)
1180+
evar_eqappr_x flags env i pbty keys (Some false) hds
11641181
(whd_betaiota_deltazeta_for_iota_state
11651182
flags.open_ts env i vsk1')
11661183
appr2
11671184
else quick_fail i);
11681185
fun i ->
11691186
if b then quick_fail i else
1170-
evar_eqappr_x flags env i pbty keys (Some true) appr1
1187+
evar_eqappr_x flags env i pbty keys (Some true) hds appr1
11711188
(whd_betaiota_deltazeta_for_iota_state
11721189
flags.open_ts env i vsk2')]
11731190
in
@@ -1186,8 +1203,20 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
11861203
(* When in modulo_betaiota = false case, lambda's are not reduced *)
11871204
(fun i -> exact_ise_stack2 env i (evar_conv_x flags) sk1 sk2)]
11881205

1189-
| Flexible ev1, Rigid -> flex_rigid true ev1 appr1 appr2
1190-
| Rigid, Flexible ev2 -> flex_rigid false ev2 appr2 appr1
1206+
| Flexible ev1, Rigid ->
1207+
let (t2, sk2) as appr2 = snd hds in
1208+
begin match flex_kind_of_term flags env evd t2 sk2 with
1209+
| Flexible ev2 -> anomaly (Pp.str "rigid terms can not fold to flexible ones")
1210+
| MaybeFlexible v2 -> flex_maybeflex true ev1 appr1 appr2 appr2
1211+
| Rigid -> flex_rigid true ev1 appr1 appr2
1212+
end
1213+
| Rigid, Flexible ev2 ->
1214+
let (t1, sk1) as appr1 = fst hds in
1215+
begin match flex_kind_of_term flags env evd t1 sk1 with
1216+
| Flexible ev1 -> anomaly (Pp.str "rigid terms can not fold to flexible ones")
1217+
| MaybeFlexible v1 -> flex_maybeflex true ev2 appr2 appr1 appr1
1218+
| Rigid -> flex_rigid true ev2 appr2 appr1
1219+
end
11911220

11921221
| MaybeFlexible vsk1', Rigid ->
11931222
let f3 i =
@@ -1199,7 +1228,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
11991228
| Inr _ -> raise Not_found)
12001229
with Not_found -> UnifFailure (i,NoCanonicalStructure))
12011230
and f4 i =
1202-
evar_eqappr_x flags env i pbty keys (Some false)
1231+
evar_eqappr_x flags env i pbty keys (Some false) hds
12031232
(whd_betaiota_deltazeta_for_iota_state
12041233
flags.open_ts env i vsk1')
12051234
appr2
@@ -1216,7 +1245,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
12161245
| Inr _ -> raise Not_found)
12171246
with Not_found -> UnifFailure (i,NoCanonicalStructure))
12181247
and f4 i =
1219-
evar_eqappr_x flags env i pbty keys (Some true) appr1
1248+
evar_eqappr_x flags env i pbty keys (Some true) hds appr1
12201249
(whd_betaiota_deltazeta_for_iota_state
12211250
flags.open_ts env i vsk2')
12221251
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)