Skip to main content

sinter_core/
reference.rs

1use serde::{Deserialize, Serialize};
2
3use crate::edge::Relation;
4use crate::node::{NodeId, Span};
5
6/// A use of a name that extraction saw but has not bound to a definition.
7///
8/// Unresolved is a first-class outcome: references are stored and countable,
9/// never guessed into edges. Phase 3 resolution consumes these and promotes
10/// each to an evidence-backed edge — or leaves it here, counted.
11#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
12pub struct Reference {
13    /// Repo-relative file the reference appears in.
14    pub file: String,
15    /// Referenced name as written (call target, import path, ...).
16    pub name: String,
17    /// Full path text at the reference site when the name was qualified
18    /// (`fmt.Println`, `util::double`) — import-evidence input.
19    pub path: Option<String>,
20    /// Relation an eventual binding would carry.
21    pub relation: Relation,
22    pub span: Span,
23    /// Innermost definition containing the reference site, if any —
24    /// the `src` of the edge resolution would create.
25    pub enclosing: Option<NodeId>,
26    /// Local rebinding of the imported/referenced name: `as` clauses
27    /// (`use x as y`, `import a as b`), Go's dot import (`.`), and glob
28    /// imports (`*`). The `name` field always keeps the original path.
29    pub alias: Option<String>,
30}
31
32/// A local binding (parameter, let/const, loop variable, catch variable)
33/// that shadows outer names. Not a symbol — recorded so resolution never
34/// binds a shadowed reference to the outer definition it no longer means.
35#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
36pub struct LocalBinding {
37    pub file: String,
38    pub name: String,
39    /// Where the binding is introduced.
40    pub span: Span,
41    /// End of the innermost definition containing it — the binding shadows
42    /// references from `span.start` to here.
43    pub scope_end: u64,
44    /// Declared/constructed type when the language chose to expose it
45    /// (`c *Counter`, `c := Counter{}`): local type evidence for method
46    /// binding. None = shadow-only binding.
47    pub type_name: Option<String>,
48}
49
50/// A declared field and its written type. Resolution uses this fact for
51/// receiver chains such as `self.harness.check()` without pretending that
52/// the field access itself is a symbol definition.
53#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
54pub struct FieldBinding {
55    /// Type/class/struct that declares the field.
56    pub owner: NodeId,
57    pub name: String,
58    /// Type exactly as written (`Arc<dyn Harness>`, `&Dog`, ...).
59    pub type_name: String,
60}
61
62/// Why a reference remained outside the graph. These are deliberately
63/// outcome descriptions, not guesses at a compiler diagnostic.
64#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
65#[serde(rename_all = "snake_case")]
66pub enum UnresolvedReason {
67    /// Source evidence pointed into the corpus, but did not identify one
68    /// target (missing member, ambiguity, or incomplete type facts).
69    SyntaxAnchoredMiss,
70    /// Source extraction had no corpus anchor and no compiler index was
71    /// available to distinguish an external/builtin from a missed edge.
72    SyntaxOnly,
73    /// A compiler index was present but supplied no in-corpus target.
74    CompilerUnresolved,
75}
76
77impl UnresolvedReason {
78    pub const fn as_str(self) -> &'static str {
79        match self {
80            Self::SyntaxAnchoredMiss => "syntax_anchored_miss",
81            Self::SyntaxOnly => "syntax_only",
82            Self::CompilerUnresolved => "compiler_unresolved",
83        }
84    }
85}
86
87/// Persisted unresolved outcome: the reference plus the coverage context
88/// that produced the miss.
89#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
90pub struct UnresolvedReference {
91    pub reference: Reference,
92    pub reason: UnresolvedReason,
93}
94
95/// A type embedding another (Go embedded struct field): member lookup on
96/// the owner falls through to the embedded type. Lookup fact, not an edge.
97#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
98pub struct Embed {
99    pub owner: NodeId,
100    pub type_name: String,
101}
102
103/// An impl block naming the trait it implements (`impl Runner for Widget`).
104/// Pairing fact for dynamic-dispatch edges: methods defined inside `span`
105/// implement the same-named methods of the trait `trait_name` resolves to.
106#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
107pub struct TraitImpl {
108    pub file: String,
109    /// Trait name as written (leaf segment for qualified paths).
110    pub trait_name: String,
111    /// Span of the whole impl block.
112    pub span: Span,
113}