pub struct SexpWitness {
pub shape: SexpShape,
pub display: String,
}Expand description
Typed witness of an offending Sexp at a typed-entry rejection
boundary — the joint identity (shape + literal) the substrate’s
diagnostic surface owes the operator. Pairs the closed-set
SexpShape projection (the twelve reachable Sexp outermost shapes
the reader can produce) with the Sexp::Display projection (the
literal value the operator wrote: 5, :foo, (list 1 2),
notify-ref, etc.).
Mirror at the offending-value boundary of the prior-run
SexpShape (typed-shape closed set), ExpectedKwargShape
(expected-shape closed set), KwargPath (kwargs-path shapes),
MacroDefHead (macro-definition-head closed set), UnquoteForm
(template-marker syntactic forms), CompilerSpecIoStage
(disk-persistence surface), and TemplateInvariantKind
(bytecode-runtime surface) closed-set lifts: those enums key
rejection variants on a typed identity carried inside the
variant’s data shape; SexpWitness keys the OFFENDING-VALUE side
(the got: String Sexp::Display slots on NonSymbolUnquoteTarget,
SpliceOutsideList, NonSymbolParam, RestParamMissingName,
DefmacroNonSymbolName, DefmacroNonListParams,
MissingHeadSymbol, and any future variant taking a &Sexp at
the helper boundary) on a typed joint identity so authoring tools
(REPL, LSP, tatara-check) bind to BOTH witness.shape (the
structural identity — pattern-matchable on SexpShape::List etc.)
AND witness.display (the literal value — renderable verbatim)
without losing either side.
Before this struct landed, the six error-builder helpers in
macro_expand.rs (non_symbol_unquote_target, splice_outside_list,
non_symbol_param, rest_param_missing_name,
defmacro_non_symbol_name, defmacro_non_list_params) and one
in domain.rs (missing_head_err’s caller) each projected &Sexp → String via Sexp::to_string() at the boundary — the structural
SexpShape was lost. After this primitive lands, every offending-
value variant slot that takes a SexpWitness carries the typed
shape AND the literal jointly in ONE owned value the variant lives
independent of the call frame on.
The byte-for-byte rendering contract is preserved: Display for
SexpWitness writes only the display field, so a variant whose
#[error(...)] annotation projects through {got} renders
byte-identically to the legacy got: String shape — every
downstream substring-grep consumer (tatara-check, REPL) passes
unchanged. The gain is structural: tools that pattern-match on
witness.shape == SexpShape::List now bind to the typed identity
directly instead of substring-parsing the rendered literal.
Clone + Debug + PartialEq + Eq are retained (same posture as
every other owned-data LispError field); Copy is dropped
because the display: String is not Copy. When a future run
gives Sexp source spans, pos: Option<usize> lands here in ONE
place and every offending-value site picks up positional rendering
with no per-variant edit — the same future-proofing posture
KwargPath, SexpShape, and ExpectedKwargShape already carry.
Theory anchor: THEORY.md §V.1 — knowable platform; the offending-
value’s joint identity (structural shape + renderable literal)
becomes a TYPE rather than a String projection at the helper
boundary that discards the shape. After this primitive lands the
substrate’s understanding of “the offending Sexp at a typed-entry
rejection” lives in ONE typed struct the diagnostic promotions
hang off of. THEORY.md §VI.1 — generation over composition; seven
inline got.to_string() projections at error-builder boundaries
(six in macro_expand.rs, one in domain.rs::missing_head_err’s
caller) is past the three-times-rule trigger. THEORY.md §II.1
invariant 1 — typed entry; the offending Sexp’s identity is part
of the proof of WHAT the typed-entry gate rejected, and the typed
witness makes both halves of that identity (shape + literal)
load-bearing data on the variant rather than the literal-only
String projection the legacy shape carried.
Fields§
§shape: SexpShapeStructural identity — the typed-shape projection (SexpShape::Int,
SexpShape::List, etc.). Pattern-matchable; future pos: Option<usize>
promotions land alongside this field once Sexp carries spans.
display: StringRenderable identity — the Sexp::Display projection ("5",
"(list 1 2)", ":foo", etc.). Owned so the witness lives
independent of the call frame and crosses thread boundaries
cleanly. Feeds the #[error(...)] annotation’s {got} slot
via SexpWitness’s Display impl.
Implementations§
Source§impl SexpWitness
impl SexpWitness
Sourcepub fn new(shape: SexpShape, display: impl Into<String>) -> Self
pub fn new(shape: SexpShape, display: impl Into<String>) -> Self
Owned constructor — pairs a typed SexpShape with an owned
String projection of the offending Sexp::Display. Used by
the sexp_witness(&Sexp) projection helper in domain.rs;
hand-written TataraDomain impls that need to construct a
witness at their own call boundary route through this
constructor.
Trait Implementations§
Source§impl Clone for SexpWitness
impl Clone for SexpWitness
Source§fn clone(&self) -> SexpWitness
fn clone(&self) -> SexpWitness
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more