HepLean Documentation

Lean.Util.Trace

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:

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:

  1. 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.
  2. 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.
  3. 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.
  4. Be concise. Keep messages short. Avoid repetitive text. (This is also why the editor plugins abbreviate the common prefixes.)
  5. Emoji are concisest. Several helper functions in this module help with a consistent emoji language.
  6. 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.
structure Lean.TraceElem :
Instances For
    Equations
    Equations
    class Lean.MonadTrace (m : TypeType) :
    Instances
      Equations
      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
            @[inline]
            Equations
            • Lean.getTraces = do let sLean.getTraceState pure s.traces
            Instances For
              @[inline]
              Equations
              Instances For
                Equations
                Instances For
                  Equations
                  • One or more equations did not get rendered due to their size.
                  Instances For
                    @[inline]
                    Equations
                    Instances For
                      @[inline]
                      Equations
                      Instances For
                        @[inline]
                        Equations
                        • One or more equations did not get rendered due to their size.
                        Instances For
                          class Lean.MonadAlwaysExcept (ε : outParam (Type u)) (m : Type u → Type v) :
                          Type (max (u + 1) v)

                          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.

                          Instances
                            Equations
                            • Lean.instMonadAlwaysExceptEIO = { except := inferInstance }
                            instance Lean.instMonadAlwaysExceptStateT {m : TypeType} [Monad m] {ε σ : Type} [always : Lean.MonadAlwaysExcept ε m] :
                            Equations
                            • Lean.instMonadAlwaysExceptStateT = { except := let x := Lean.MonadAlwaysExcept.except; inferInstance }
                            instance Lean.instMonadAlwaysExceptStateRefT' {m : TypeType} {ε ω σ : Type} [always : Lean.MonadAlwaysExcept ε m] :
                            Equations
                            • Lean.instMonadAlwaysExceptStateRefT' = { except := let x := Lean.MonadAlwaysExcept.except; inferInstance }
                            Equations
                            • Lean.instMonadAlwaysExceptReaderT = { except := let x := Lean.MonadAlwaysExcept.except; inferInstance }
                            instance Lean.instMonadAlwaysExceptMonadCacheT {α : Type} {m : TypeType} {ε ω β : Type} [always : Lean.MonadAlwaysExcept ε m] [STWorld ω m] [BEq α] [Hashable α] :
                            Equations
                            • Lean.instMonadAlwaysExceptMonadCacheT = { except := let x := Lean.MonadAlwaysExcept.except; inferInstance }
                            def Lean.withTraceNode {α : Type} {m : TypeType} [Monad m] [Lean.MonadTrace m] [MonadLiftT IO m] [Lean.MonadRef m] [Lean.AddMessageContext m] [Lean.MonadOptions m] {ε : Type} [always : Lean.MonadAlwaysExcept ε m] [MonadLiftT BaseIO m] (cls : Lean.Name) (msg : Except ε αm Lean.MessageData) (k : m α) (collapsed : Bool := true) (tag : String := "") :
                            m α
                            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
                                def Lean.registerTraceClass (traceClassName : Lean.Name) (inherited : Bool := false) (ref : Lean.Name := by exact decl_name%) :

                                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
                                        Instances For
                                          def Lean.exceptEmoji {α : Type} {ε : Type u_1} :
                                          Except ε αString

                                          Visualize an Except using a checkmark or a cross.

                                          Equations
                                          Instances For
                                            class Lean.ExceptToEmoji (ε α : Type) :
                                            Instances
                                              Equations
                                              • Lean.instExceptToEmojiBool = { toEmoji := Lean.exceptBoolEmoji }
                                              Equations
                                              • Lean.instExceptToEmojiOption = { toEmoji := Lean.exceptOptionEmoji }
                                              def Lean.withTraceNodeBefore {α : Type} {m : TypeType} [Monad m] [Lean.MonadTrace m] [MonadLiftT IO m] {ε : Type} [Lean.MonadRef m] [Lean.AddMessageContext m] [Lean.MonadOptions m] [always : Lean.MonadAlwaysExcept ε m] [MonadLiftT BaseIO m] [Lean.ExceptToEmoji ε α] (cls : Lean.Name) (msg : m Lean.MessageData) (k : m α) (collapsed : Bool := true) (tag : String := "") :
                                              m α

                                              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.
                                              Instances For