Skip to content

Commit eaea52b

Browse files
committed
Support generalized rewriting with leibniz equality in let bindings
1 parent 2212109 commit eaea52b

File tree

4 files changed

+106
-3
lines changed

4 files changed

+106
-3
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
- **Added:**
2+
Add support for rewriting in let bindings (using Leibniz equality)
3+
to generalized rewriting
4+
(`#20985 <https://github.com/rocq-prover/rocq/pull/20985>`_,
5+
by Matthieu Sozeau).

tactics/rewrite.ml

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,66 @@ let subterm all flags (s : 'a pure_strategy) : 'a pure_strategy =
12231223
| Fail | Identity -> b'
12241224
in state, res
12251225

1226+
| LetIn (n, v, t, b) ->
1227+
let eq = Rocqlib.build_rocq_eq_data () in
1228+
let evars', eqty = Evd.fresh_global env (fst evars) eq.Rocqlib.eq in
1229+
let eqty = EConstr.mkApp (eqty, [| t |]) in
1230+
let state, v' =
1231+
s.strategy { state ; term1 = v ; ty1 = t ; cstr = (prop,Some eqty); evars = (evars', snd evars); env; unfresh }
1232+
in
1233+
let res =
1234+
match v' with
1235+
| Success r ->
1236+
let env' = EConstr.push_rel (LocalDef (n, v, t)) env in
1237+
let bty = Retyping.get_type_of env' (goalevars evars) b in
1238+
if not @@ noccurn (goalevars evars) 1 bty then Fail
1239+
else
1240+
let bty = subst1 mkProp bty in
1241+
let r = match r.rew_prf with
1242+
| RewPrf (_rel, prf) ->
1243+
let sigma, eqt = Evd.fresh_global env (fst r.rew_evars) eq.Rocqlib.eq in
1244+
let sigma, congr = Evd.fresh_global env sigma eq.Rocqlib.congr in
1245+
let congr = mkApp (congr, [| t; bty; mkLambda (n, t, b); r.rew_from; r.rew_to; prf |]) in
1246+
{ r with rew_prf = RewPrf (mkApp (eqt, [| bty |]), congr); rew_evars = (sigma, snd r.rew_evars) }
1247+
| x -> r
1248+
in
1249+
Success { r with
1250+
rew_car = bty;
1251+
rew_from = mkLetIn(n, r.rew_from, t, b);
1252+
rew_to = mkLetIn (n, r.rew_to, t, b) }
1253+
| Fail | Identity -> v'
1254+
in
1255+
let res =
1256+
match res with
1257+
| Success res ->
1258+
(match res.rew_prf with
1259+
| RewPrf (rel, prf) ->
1260+
Success (apply_constraint env res.rew_car rel prf (prop,cstr) res)
1261+
| _ -> Success res)
1262+
| _ -> res
1263+
in
1264+
(match res with
1265+
| Success _ -> state, res
1266+
| Fail | Identity ->
1267+
let env' = EConstr.push_rel (LocalDef (n, v, t)) env in
1268+
let bty = Retyping.get_type_of env' (goalevars evars) b in
1269+
let state, b' = s.strategy { state ; term1 = b ; ty1 = bty ; cstr = (prop, Option.map (lift 1) cstr);
1270+
evars; env = env'; unfresh }
1271+
in
1272+
let res =
1273+
match b' with
1274+
| Success r ->
1275+
let mklet t' = mkLetIn (n, v, t, t') in
1276+
Success { r with rew_car = r.rew_car;
1277+
rew_prf =
1278+
(match r.rew_prf with
1279+
| RewPrf (rel, prf) -> RewPrf (mklet rel, mklet prf)
1280+
| RewCast k -> RewCast k);
1281+
rew_from = mklet r.rew_from;
1282+
rew_to = mklet r.rew_to; }
1283+
| _ -> res
1284+
in state, res)
1285+
12261286
| Case (ci, u, pms, p, iv, c, brs) ->
12271287
let (ci, (p,rp), iv, c, brs) = EConstr.expand_case env (goalevars evars) (ci, u, pms, p, iv, c, brs) in
12281288
let cty = Retyping.get_type_of env (goalevars evars) c in
@@ -1618,7 +1678,7 @@ let solve_constraints env (evars,cstrs) =
16181678
let evars' = TC.resolve_typeclasses env ~filter:TC.all_evars ~fail:true evars' in
16191679
Evd.set_typeclass_evars evars' oldtcs
16201680

1621-
let nf_zeta =
1681+
let _nf_zeta =
16221682
Reductionops.clos_norm_flags (RedFlags.mkflags [RedFlags.fZETA])
16231683

16241684
exception RewriteFailure of Environ.env * Evd.evar_map * pretype_error
@@ -1662,7 +1722,7 @@ let cl_rewrite_clause_aux ?(abs=None) strat env avoid sigma concl is_hyp : resul
16621722
let res = match res.rew_prf with
16631723
| RewCast c -> None
16641724
| RewPrf (rel, p) ->
1665-
let p = nf_zeta env evars p in
1725+
(* let p = nf_zeta env evars p in *)
16661726
let term =
16671727
match abs with
16681728
| None -> p

test-suite/success/rewrite_strat.v

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,33 @@ Module StratTactic.
189189
Qed.
190190

191191
End StratTactic.
192+
193+
Module RewriteLet.
194+
Import Nat.
195+
196+
(* In a "deep" context *)
197+
198+
Axiom f : nat -> nat.
199+
200+
Goal forall x : nat, f (let x0 := x + 1 in x0 + x0) = f (S (S (x + x))).
201+
Proof.
202+
intros x.
203+
rewrite_strat (topdown (choice (<- plus_n_Sm) (<- plus_n_O))).
204+
reflexivity.
205+
Qed.
206+
207+
(* In a toplevel context, requiring to mediate between [eq] and [impl] / [flip impl] *)
208+
Goal forall x : nat, let x0 := x + 1 in x0 = x0.
209+
Proof.
210+
intros x.
211+
now rewrite_strat (topdown (choice (<- plus_n_Sm) (<- plus_n_O))).
212+
Qed.
213+
214+
Goal forall x : nat, (let x0 := x + 1 in x0 = x0) -> S x = S x.
215+
Proof.
216+
intros x H.
217+
rewrite_strat (topdown (choice (<- plus_n_Sm) (<- plus_n_O))) in H.
218+
exact H.
219+
Qed.
220+
221+
End RewriteLet.

theories/Corelib/Classes/Morphisms.v

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,15 @@ Ltac proper_subrelation :=
313313
#[global]
314314
Hint Extern 5 (@Proper _ ?H _) => proper_subrelation : typeclass_instances.
315315

316-
(** Essential subrelation instances for [iff], [impl] and [pointwise_relation]. *)
316+
(** Essential subrelation instances for [eq], [iff], [impl] and [pointwise_relation]. *)
317+
318+
#[global]
319+
Instance eq_flip_impl_subrelation : subrelation eq (Basics.flip Basics.impl).
320+
Proof. now intros x y ->. Qed.
321+
322+
#[global]
323+
Instance eq_impl_subrelation : subrelation eq Basics.impl.
324+
Proof. now intros x y ->. Qed.
317325

318326
#[global]
319327
Instance iff_impl_subrelation : subrelation iff impl | 2.

0 commit comments

Comments
 (0)