This PR adds a `result? : Option TraceResult` field to `TraceData` and populates it in `withTraceNode` and `withTraceNodeBefore`, so that metaprograms walking trace trees can determine success/failure structurally instead of string-matching on emoji. `TraceResult` has three cases: `.success` (checkEmoji), `.failure` (crossEmoji), and `.error` (bombEmoji, exception thrown). An `ExceptToTraceResult` typeclass converts `Except` results to `TraceResult` directly, with instances for `Bool` and `Option`. `TraceResult.toEmoji` converts back to emoji for display. This replaces the previous `ExceptToEmoji` typeclass — `TraceResult` is now the primary representation rather than being derived from emoji strings. `withTraceNodeBefore` (used by `isDefEq`) uses `ExceptToTraceResult.toTraceResult` directly, correctly handling `Bool` (`.ok false` = failure) and `Option` (`.ok none` = failure), with `Except.error` mapping to `.error`. For `withTraceNode`, `result?` defaults to `none`. Callers can pass `mkResult?` to provide structured results; when set, the corresponding emoji is auto-prepended to the message. Motivated by mathlib's `#defeq_abuse` diagnostic tactic (https://github.com/leanprover-community/mathlib4/pull/35750) which currently string-matches on emoji to determine trace node outcomes. See https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/backward.2EisDefEq.2ErespectTransparency 🤖 Prepared with Claude Code --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
37 lines
1,007 B
Text
37 lines
1,007 B
Text
set_option linter.unusedSimpArgs false
|
||
|
||
variable (n v₁ v₂) (hv₁: v₁ < n + 1) (hv₂: v₂ < n + 1)
|
||
|
||
theorem foo (_: ¬ Fin.mk v₂ hv₂ = Fin.mk v₁ hv₁ ): True := trivial
|
||
|
||
/--
|
||
trace: [Meta.Tactic.simp.unify] eq_self:1000, failed to unify
|
||
?a = ?a
|
||
with
|
||
⟨v₂, hv₂⟩ = ⟨v₁, hv₁⟩
|
||
[Meta.Tactic.simp.rewrite] Fin.mk.injEq:1000:
|
||
⟨v₂, hv₂⟩ = ⟨v₁, hv₁⟩
|
||
==>
|
||
v₂ = v₁
|
||
[Meta.Tactic.simp.unify] eq_self:1000, failed to unify
|
||
?a = ?a
|
||
with
|
||
v₂ = v₁
|
||
[Meta.Tactic.simp.discharge] ✅️ Nat.ne_of_gt discharge ✅️
|
||
v₁ < v₂
|
||
[Meta.Tactic.simp.rewrite] hv:1000:
|
||
v₁ < v₂
|
||
==>
|
||
True
|
||
[Meta.Tactic.simp.rewrite] Nat.ne_of_gt:1000:
|
||
v₂ = v₁
|
||
==>
|
||
False
|
||
-/
|
||
#guard_msgs in
|
||
set_option trace.Meta.Tactic.simp true in
|
||
example (hv: v₁ < v₂) : True :=
|
||
foo n v₁ v₂ ‹_› ‹_›
|
||
(by simp +decide only [hv, Fin.mk.injEq, Nat.ne_of_gt, Nat.lt_succ_iff])
|
||
|
||
#check Fin.mk.injEq
|