Skip to content

feat: add structured TraceResult to TraceData#12698

Open
kim-em wants to merge 4 commits intoleanprover:masterfrom
kim-em:kim/trace-result-field
Open

feat: add structured TraceResult to TraceData#12698
kim-em wants to merge 4 commits intoleanprover:masterfrom
kim-em:kim/trace-result-field

Conversation

@kim-em
Copy link
Collaborator

@kim-em kim-em commented Feb 26, 2026

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.

For withTraceNodeBefore (used by isDefEq), the mkResult parameter defaults to ExceptToTraceResult.toTraceResult, 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.

Motivated by mathlib's #defeq_abuse diagnostic tactic (leanprover-community/mathlib4#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

Adds a `result? : Option TraceResult` field to `TraceData`, so that
`withTraceNode` and `withTraceNodeBefore` record structured
success/failure information alongside the existing emoji in the
rendered header.

This allows metaprograms that walk trace trees to determine success or
failure by checking `td.result?` instead of string-matching on emoji
characters in the rendered `MessageData`.

For `withTraceNodeBefore`, `result?` is derived from the emoji
computed by `ExceptToEmoji`, correctly handling `Bool` (where
`.ok false` = failure) and `Option` (where `.ok none` = failure).

For `withTraceNode`, `result?` defaults to `.ok _ => success`,
`.error _ => failure`. Callers needing different semantics can pass
`result?` explicitly.

Trace nodes not created by `withTraceNode`/`withTraceNodeBefore`
(e.g. from `addTrace` or diagnostic formatting) get `result? := none`.

Motivated by mathlib's `#defeq_abuse` diagnostic tactic
(mathlib4#35750) which currently has to string-match on emoji
to determine trace node outcomes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
kim-em and others added 2 commits February 26, 2026 01:29
`withTraceNode` doesn't have access to `ExceptToEmoji`, so it can't
distinguish `Except.ok none` (failure) from `Except.ok (some _)`
(success). Defaulting to `none` is the honest choice; callers that
need structured results can pass `result?` explicitly.

`withTraceNodeBefore` is unaffected — it correctly derives from the
emoji string via `ExceptToEmoji`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…raceNodeBefore

Both `withTraceNode` and `withTraceNodeBefore` now take a
`mkResult? : Except ε α → Option TraceResult` callback instead of a
fixed `result? : Option TraceResult`. This lets callers compute the
structured result from the actual `Except` outcome.

- `withTraceNode`: defaults to `fun _ => none` (callers opt in)
- `withTraceNodeBefore`: defaults to inferring from `ExceptToEmoji`
  (success if emoji == checkEmoji, failure otherwise)

This addresses the semantic mismatch where `Except.ok none` or
`Except.ok false` would need to be reported as failure, not success.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The bomb emoji (💥) indicates an exception was thrown, which is
semantically different from a normal failure (❌). Lumping them
together as `.failure` loses this distinction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment on lines +396 to +398
if emoji == checkEmoji then some .success
else if emoji == bombEmoji then some .error
else some .failure) : m α := do
Copy link
Contributor

@eric-wieser eric-wieser Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather thand doing a unicode string comparison here, I think it would make more sense to define ExceptToTraceResult, superseding ExceptToEmoji, and TraceResult.toEmoji?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is much better. I was a bit afraid of making breaking changes here, but it seems to be okay.

@github-actions github-actions bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Feb 26, 2026
@mathlib-lean-pr-testing
Copy link

Mathlib CI status (docs):

  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase d4b560ec4ac4431e5439565f91e73eec1ce12c37 --onto c595413fccaa47ebdc399d9b817c17425687fc26. You can force Mathlib CI using the force-mathlib-ci label. (2026-02-26 03:07:24)

@leanprover-bot
Copy link
Collaborator

Reference manual CI status:

  • ❗ Reference manual CI will not be attempted unless your PR branches off the nightly-with-manual branch. Try git rebase d4b560ec4ac4431e5439565f91e73eec1ce12c37 --onto 8038a8b8904f89ad9542c8eda11379f8f006eab1. You can force reference manual CI using the force-manual-ci label. (2026-02-26 03:07:26)

mathlib-bors bot pushed a commit to leanprover-community/mathlib4 that referenced this pull request Mar 1, 2026
This PR adds `#defeq_abuse in`, a tactic/command combinator for diagnosing `backward.isDefEq.respectTransparency` failures. It runs the given tactic or command with the option both `true` and `false`, and when the strict setting fails, walks the trace tree to identify the specific `isDefEq` checks that are root causes.

Reusable trace-tree analysis utilities are extracted into `Mathlib.Lean.MessageData.Trace`:
- `TraceResult` / `traceResultOf` — structured access to the ✅/❌/💥 status encoding
- `foldTraceNodes` — generic fold over `MessageData` trace trees
- `stripTraceResultPrefix` / `dedupByString` — helpers for trace content comparison

Companion lean4 PRs that will simplify this further:
- leanprover/lean4#12698 — structured `TraceResult` field on `TraceData`
- leanprover/lean4#12699 — `Meta.synthInstance.apply` trace class

See https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/backward.2EisDefEq.2ErespectTransparency

🤖 Prepared with Claude Code

Co-authored-by: Thomas R. Murrills <68410468+thorimur@users.noreply.github.com>
@kim-em kim-em marked this pull request as ready for review March 2, 2026 02:08
@kim-em kim-em added the changelog-language Language features and metaprograms label Mar 2, 2026
@kim-em kim-em requested a review from eric-wieser March 2, 2026 03:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-language Language features and metaprograms toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants