This PR adds the `binderNameHint` gadget. It can be used in rewrite and
simp rules to preserve a user-provided name where possible.
The expression `binderNameHint v binder e` defined to be `e`.
If it is used on the right-hand side of an equation that is applied by a
tactic like `rw` or `simp`,
and `v` is a local variable, and `binder` is an expression that (after
beta-reduction) is a binder
(so `fun w => …` or `∀ w, …`), then it will rename `v` to the name used
in the binder, and remove
the `binderNameHint`.
A typical use of this gadget would be as follows; the gadget ensures
that after rewriting, the local
variable is still `name`, and not `x`:
```
theorem all_eq_not_any_not (l : List α) (p : α → Bool) :
l.all p = !l.any fun x => binderNameHint x p (!p x) := sorry
example (names : List String) : names.all (fun name => "Waldo".isPrefixOf name) = true := by
rw [all_eq_not_any_not]
-- ⊢ (!names.any fun name => !"Waldo".isPrefixOf name) = true
```
This gadget is supported by `simp`, `dsimp` and `rw` in the
right-hand-side of an equation, but not
in hypotheses or by other tactics.
35 lines
816 B
Text
35 lines
816 B
Text
/-!
|
|
Checks that `simp` removes the `binderNameHint` in the pre-phase, and does not spend time looking
|
|
at its arguments.
|
|
|
|
The following traces should show no rewriting of `x` or `y`, only `z`.
|
|
-/
|
|
|
|
def x : Nat := 0
|
|
def y : Nat := 0
|
|
def z : Nat := 0
|
|
|
|
set_option trace.Meta.Tactic.simp.rewrite true
|
|
|
|
/--
|
|
info: [Meta.Tactic.simp.rewrite] ↓ binderNameHint.eq_1:1000:
|
|
binderNameHint x y z
|
|
==>
|
|
z
|
|
[Meta.Tactic.simp.rewrite] unfold z, z ==> 0
|
|
[Meta.Tactic.simp.rewrite] eq_self:1000: 0 = 0 ==> True
|
|
-/
|
|
#guard_msgs in
|
|
example : binderNameHint x y z = 0 := by
|
|
simp [x, y, z]
|
|
|
|
/--
|
|
info: [Meta.Tactic.simp.rewrite] ↓ binderNameHint.eq_1:1000:
|
|
binderNameHint x y z
|
|
==>
|
|
z
|
|
[Meta.Tactic.simp.rewrite] unfold z, z ==> 0
|
|
-/
|
|
#guard_msgs in
|
|
example : binderNameHint x y z = 0 := by
|
|
dsimp [x, y, z]
|