Skip to main content

vj_sim/netlist/
error.rs

1//! Elaboration error type (NL-008): every elaboration failure this crate
2//! surfaces is a typed `ElabError`, never a panic and never a silently
3//! swallowed construct — see the plan's "Global constraints" section on
4//! exhaustive `sv_lang`/`sv_lang_kinds` kind matches.
5
6/// An elaboration failure. `netlist::elaborate` never panics on malformed or
7/// unsupported-but-syntactically-valid input; it returns one of these
8/// instead.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum ElabError {
11    /// A construct this pass does not (yet) lower — e.g. a `checker`/
12    /// primitive instantiation, a generate block, or any other symbol kind
13    /// this DFS's member-kind match does not recognize as either "a child
14    /// instance" or "a known-benign non-instantiating member". `hier_path`
15    /// is `Symbol::hierarchical_path()` of the offending symbol; `detail`
16    /// names the construct (its `SymbolKind`, `Debug`-formatted). Never a
17    /// silent skip: a construct this pass cannot account for must never
18    /// cause elaboration to quietly under-report the design's hierarchy
19    /// (ARCHITECTURE §7 item 9).
20    UnsupportedConstruct { hier_path: String, detail: String },
21    /// A `sv_lang`/dataflow call itself returned an unexpected `None`/`Err`
22    /// where this pass's own invariants say it should not have (e.g. an
23    /// `Instance` symbol with no `instance_body()`).
24    Frontend(String),
25    /// Task 3 (NL-015): `confirm_and_assign_symbol_keys`'s defensive
26    /// member-for-member re-check disagreed with
27    /// `Symbol::instance_body_has_same_type`'s "same type" verdict for a
28    /// group `merge_groups_within_bucket` already decided to merge. Never a
29    /// panic and never a silently-corrupted merged `Template` — this is the
30    /// hard-fail NL-015 requires. `member_index` is the position (in
31    /// `members()` order) of the first disagreeing member.
32    MergeInvariantViolated {
33        canonical_hier_path: String,
34        other_hier_path: String,
35        member_index: usize,
36        detail: String,
37    },
38}
39
40impl std::fmt::Display for ElabError {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        match self {
43            ElabError::UnsupportedConstruct { hier_path, detail } => {
44                write!(
45                    f,
46                    "unsupported construct at `{hier_path}` ({detail}) — not lowered by this elaboration pass"
47                )
48            }
49            ElabError::Frontend(msg) => write!(f, "sv-lang frontend error: {msg}"),
50            ElabError::MergeInvariantViolated {
51                canonical_hier_path,
52                other_hier_path,
53                member_index,
54                detail,
55            } => write!(
56                f,
57                "merge invariant violated between `{canonical_hier_path}` and \
58                 `{other_hier_path}` at member {member_index}: {detail}"
59            ),
60        }
61    }
62}
63
64impl std::error::Error for ElabError {}