feat: add trace.Meta.Tactic.simp.backwardDefEq (#13640)

This PR adds a trace event emitted whenever a `dsimp` (or rfl-only
`simp`) rewrite fires
because of a `[backward_defeq]`-tagged theorem (i.e., one that would not
have applied without `set_option backward.defeqAttrib.useBackward
true`).

Useful for finding where downstream code is silently relying on the
backwards escape hatch — a precursor to either re-tagging the lemma as
`[defeq]` or restructuring the proof so it works under the strict
defeq rules.
This commit is contained in:
Joachim Breitner 2026-05-05 15:02:27 +02:00 committed by GitHub
parent e4c0a5a511
commit bd20c51ae4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 44 additions and 0 deletions

View file

@ -27,6 +27,7 @@ builtin_initialize registerTraceClass `Meta.Tactic.simp
builtin_initialize registerTraceClass `Meta.Tactic.simp.congr (inherited := true)
builtin_initialize registerTraceClass `Meta.Tactic.simp.discharge (inherited := true)
builtin_initialize registerTraceClass `Meta.Tactic.simp.rewrite (inherited := true)
builtin_initialize registerTraceClass `Meta.Tactic.simp.backwardDefEq (inherited := true)
builtin_initialize registerTraceClass `Meta.Tactic.simp.unify (inherited := true)
builtin_initialize registerTraceClass `Meta.Tactic.simp.ground (inherited := true)
builtin_initialize registerTraceClass `Meta.Tactic.simp.loopProtection (inherited := true)

View file

@ -233,6 +233,9 @@ where
continue
if let some result ← tryTheoremWithExtraArgs? e thm numExtraArgs then
trace[Debug.Meta.Tactic.simp] "rewrite result {e} => {result.expr}"
if rflOnly && !thm.rfl && thm.backwardRfl then
trace[Meta.Tactic.simp.backwardDefEq]
"used `[backward_defeq]` theorem {← ppOrigin thm.origin} to rewrite{indentExpr e}"
return some result
return none
@ -261,6 +264,9 @@ where
tryTheoremCore lhs xs bis val type e thm (numArgs - lhsNumArgs)
if let some result := result? then
trace[Debug.Meta.Tactic.simp] "rewrite result {e} => {result.expr}"
if rflOnly && !thm.rfl && thm.backwardRfl then
trace[Meta.Tactic.simp.backwardDefEq]
"used `[backward_defeq]` theorem {← ppOrigin thm.origin} to rewrite{indentExpr e}"
diagnoseWhenNoIndex thm
return some result
return none

View file

@ -0,0 +1,37 @@
/-!
# `trace.Meta.Tactic.simp.backwardDefEq` reports `[backward_defeq]` rewrites
The trace class fires when `dsimp` (or the rfl-only mode of `simp`) uses a
`[backward_defeq]` lemma to rewrite — i.e. when the rewrite would not have
fired without `set_option backward.defeqAttrib.useBackward true`.
-/
def slow : Nat → Nat := fun n => n + 0
@[backward_defeq] theorem slow_eq (n : Nat) : slow n = n :=
Nat.add_zero n
-- With `useBackward`, `slow_eq` fires and the trace is emitted.
set_option backward.defeqAttrib.useBackward true in
set_option trace.Meta.Tactic.simp.backwardDefEq true in
/--
trace: [Meta.Tactic.simp.backwardDefEq] used `[backward_defeq]` theorem slow_eq to rewrite
slow 1
-/
#guard_msgs in
example : slow 1 = 1 := by dsimp only [slow_eq]
-- Without `useBackward`, `dsimp` cannot use `slow_eq` and there is no trace event.
set_option trace.Meta.Tactic.simp.backwardDefEq true in
/-- error: `dsimp` made no progress -/
#guard_msgs in
example : slow 1 = 1 := by dsimp only [slow_eq]
@[implicit_reducible] def fastApp (f : Nat → Nat) (n : Nat) : Nat := f n
@[defeq] theorem fastApp_eq (f : Nat → Nat) (n : Nat) : fastApp f n = f n := rfl
-- A `[defeq]` lemma fires unconditionally; the trace is *not* emitted (the
-- trace is specifically for `[backward_defeq]`-only lemmas).
set_option trace.Meta.Tactic.simp.backwardDefEq true in
example (n : Nat) : fastApp Nat.succ n = Nat.succ n := by dsimp only [fastApp_eq]