Trace messages #
Trace messages explain to the user what problem Lean solved and what steps it took. Think of trace messages like a figure in a paper.
They are shown in the editor as a collapsible tree,
usually as [class.name] message ▸
.
Every trace node has a class name, a message, and an array of children.
This module provides the API to produce trace messages,
the key entry points are:
registerTraceClass `class.name
registers a trace class- ``withTraceNode
class.name (fun result => return msg) do body
produces a trace message containing the trace messages inbody
as children trace[class.name] msg
produces a trace message without children
Users can enable trace options for a class using
set_option trace.class.name true
.
This only enables trace messages for the class.name
trace class
as well as child classes that are explicitly marked as inherited
(see registerTraceClass
).
Internally, trace messages are stored as MessageData
:
.trace cls msg #[.trace .., .trace ..]
When writing trace messages, try to follow these guidelines:
- Expansion progressively increases detail. Each level of expansion (of the trace node in the editor) should reveal more details. For example, the unexpanded node should show the top-level goal. Expanding it should show a list of steps. Expanding one of the steps then shows what happens during that step.
- One trace message per step.
The
[trace.class]
marker functions as a visual bullet point, making it easy to identify the different steps at a glance. - Outcome first. The top-level trace message should already show whether the action failed or succeeded, as opposed to a "success" trace message that comes pages later.
- Be concise. Keep messages short. Avoid repetitive text. (This is also why the editor plugins abbreviate the common prefixes.)
- Emoji are concisest. Several helper functions in this module help with a consistent emoji language.
- Good defaults.
Setting
set_option trace.Meta.synthInstance true
(etc.) should produce great trace messages out-of-the-box, without needing extra options to tweak it.
Equations
- Lean.instInhabitedTraceElem = { default := { ref := default, msg := default } }
Equations
- Lean.instInhabitedTraceState = { default := { traces := default } }
- modifyTraceState : (Lean.TraceState → Lean.TraceState) → m Unit
- getTraceState : m Lean.TraceState
Instances
Equations
- Lean.instMonadTraceOfMonadLift m n = { modifyTraceState := fun (f : Lean.TraceState → Lean.TraceState) => liftM (Lean.modifyTraceState f), getTraceState := liftM Lean.getTraceState }
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Lean.isTracingEnabledFor cls = do let inherited ← liftM (ST.Ref.get Lean.inheritedTraceOptions) let __do_lift ← Lean.getOptions pure (Lean.checkTraceOption inherited __do_lift cls)
Instances For
Equations
- Lean.modifyTraces f = Lean.modifyTraceState fun (s : Lean.TraceState) => { traces := f s.traces }
Instances For
Equations
- Lean.setTraceState s = Lean.modifyTraceState fun (x : Lean.TraceState) => s
Instances For
Equations
- Lean.addRawTrace msg = do let ref ← Lean.getRef let msg ← Lean.addMessageContext msg Lean.modifyTraces fun (x : Lean.PersistentArray Lean.TraceElem) => x.push { ref := ref, msg := msg }
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Lean.trace cls msg = do let __do_lift ← Lean.isTracingEnabledFor cls if __do_lift = true then Lean.addTrace cls (msg ()) else pure PUnit.unit
Instances For
Equations
- Lean.traceM cls mkMsg = do let __do_lift ← Lean.isTracingEnabledFor cls if __do_lift = true then do let msg ← mkMsg Lean.addTrace cls msg else pure PUnit.unit
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
MonadExcept
variant that is expected to catch all exceptions of the given type in case the
standard instance doesn't.
In most circumstances, we want to let runtime exceptions during term elaboration bubble up to the
command elaborator (see Core.tryCatch
). However, in a few cases like building the trace tree, we
really need to handle (and then re-throw) every exception lest we end up with a broken tree.
- except : MonadExceptOf ε m
Instances
Equations
- Lean.instMonadAlwaysExceptEIO = { except := inferInstance }
Equations
- Lean.instMonadAlwaysExceptStateT = { except := let x := Lean.MonadAlwaysExcept.except; inferInstance }
Equations
- Lean.instMonadAlwaysExceptStateRefT' = { except := let x := Lean.MonadAlwaysExcept.except; inferInstance }
Equations
- Lean.instMonadAlwaysExceptReaderT = { except := let x := Lean.MonadAlwaysExcept.except; inferInstance }
Equations
- Lean.instMonadAlwaysExceptMonadCacheT = { except := let x := Lean.MonadAlwaysExcept.except; inferInstance }
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Registers a trace class.
By default, trace classes are not inherited;
that is, set_option trace.foo true
does not imply set_option trace.foo.bar true
.
Calling registerTraceClass `foo.bar (inherited := true)
enables this inheritance
on an opt-in basis.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
Instances For
Equations
Instances For
Equations
- Lean.instExceptToEmojiBool = { toEmoji := Lean.exceptBoolEmoji }
Equations
- Lean.instExceptToEmojiOption = { toEmoji := Lean.exceptOptionEmoji }
Similar to withTraceNode
, but msg is constructed before executing k
.
This is important when debugging methods such as isDefEq
, and we want to generate the message
before k
updates the metavariable assignment. The class ExceptToEmoji
is used to convert
the result produced by k
into an emoji (e.g., 💥️
, ✅️
, ❌️
).
TODO: find better name for this function.
Equations
- One or more equations did not get rendered due to their size.