Skip to main content

miden_assembly_syntax/ast/item/resolver/
error.rs

1// Allow unused assignments - required by miette::Diagnostic derive macro
2#![allow(unused_assignments)]
3
4use alloc::sync::Arc;
5
6use miden_debug_types::{SourceFile, SourceManager, SourceSpan};
7
8use crate::{
9    ast::ItemIndex,
10    diagnostics::{Diagnostic, RelatedLabel, miette},
11};
12
13/// Represents an error that occurs during symbol resolution
14#[derive(Debug, Clone, thiserror::Error, Diagnostic)]
15pub enum SymbolResolutionError {
16    #[error("undefined symbol reference")]
17    #[diagnostic(help("maybe you are missing an import?"))]
18    UndefinedSymbol {
19        #[label("this symbol path could not be resolved")]
20        span: SourceSpan,
21        #[source_code]
22        source_file: Option<Arc<SourceFile>>,
23    },
24    #[error("invalid symbol reference")]
25    #[diagnostic(help(
26        "references to a subpath of an imported symbol require the imported item to be a module"
27    ))]
28    InvalidAliasTarget {
29        #[label("this reference specifies a subpath relative to an import")]
30        span: SourceSpan,
31        #[source_code]
32        source_file: Option<Arc<SourceFile>>,
33        #[related]
34        relative_to: Option<RelatedLabel>,
35    },
36    #[error("invalid symbol path")]
37    #[diagnostic(help("all ancestors of a path must be modules"))]
38    InvalidSubPath {
39        #[label("this path specifies a subpath relative to another item")]
40        span: SourceSpan,
41        #[source_code]
42        source_file: Option<Arc<SourceFile>>,
43        #[related]
44        relative_to: Option<RelatedLabel>,
45    },
46    #[error("invalid symbol reference: wrong type")]
47    #[diagnostic()]
48    InvalidSymbolType {
49        expected: &'static str,
50        #[label("expected this symbol to reference a {expected} item")]
51        span: SourceSpan,
52        #[source_code]
53        source_file: Option<Arc<SourceFile>>,
54        #[related]
55        actual: Option<RelatedLabel>,
56    },
57    #[error("private symbol reference")]
58    #[diagnostic(help("only public items can be referenced from another module"))]
59    PrivateSymbol {
60        #[label("this symbol is private to another module")]
61        span: SourceSpan,
62        #[source_code]
63        source_file: Option<Arc<SourceFile>>,
64        #[related]
65        defined: Option<RelatedLabel>,
66    },
67    #[error("type expression nesting depth exceeded")]
68    #[diagnostic(help("type expression nesting exceeded the maximum depth of {max_depth}"))]
69    TypeExpressionDepthExceeded {
70        #[label("type expression nesting exceeded the configured depth limit")]
71        span: SourceSpan,
72        #[source_code]
73        source_file: Option<Arc<SourceFile>>,
74        max_depth: usize,
75    },
76    #[error("alias expansion cycle detected")]
77    #[diagnostic(help("alias expansion encountered a cycle"))]
78    AliasExpansionCycle {
79        #[label("this alias expansion is part of a cycle")]
80        span: SourceSpan,
81        #[source_code]
82        source_file: Option<Arc<SourceFile>>,
83    },
84    #[error("alias expansion depth exceeded")]
85    #[diagnostic(help("alias expansion exceeded the maximum depth of {max_depth}"))]
86    AliasExpansionDepthExceeded {
87        #[label("alias expansion exceeded the configured depth limit")]
88        span: SourceSpan,
89        #[source_code]
90        source_file: Option<Arc<SourceFile>>,
91        max_depth: usize,
92    },
93    #[error("too many items in module")]
94    #[diagnostic(help("break this module up into smaller modules"))]
95    TooManyItemsInModule {
96        #[label("module item count exceeds the supported limit of {max_items}")]
97        span: SourceSpan,
98        #[source_code]
99        source_file: Option<Arc<SourceFile>>,
100        max_items: usize,
101    },
102}
103
104impl SymbolResolutionError {
105    pub fn undefined(span: SourceSpan, source_manager: &dyn SourceManager) -> Self {
106        Self::UndefinedSymbol {
107            span,
108            source_file: source_manager.get(span.source_id()).ok(),
109        }
110    }
111
112    pub fn invalid_sub_path(
113        span: SourceSpan,
114        relative_to: SourceSpan,
115        source_manager: &dyn SourceManager,
116    ) -> Self {
117        let relative_to_source_file = source_manager.get(relative_to.source_id()).ok();
118        let source_file = source_manager.get(span.source_id()).ok();
119        Self::InvalidSubPath {
120            span,
121            source_file,
122            relative_to: Some(
123                RelatedLabel::advice("but this item is not a module")
124                    .with_labeled_span(relative_to, "but this item is not a module")
125                    .with_source_file(relative_to_source_file),
126            ),
127        }
128    }
129
130    pub fn invalid_symbol_type(
131        span: SourceSpan,
132        expected: &'static str,
133        actual: SourceSpan,
134        source_manager: &dyn SourceManager,
135    ) -> Self {
136        let actual_source_file = source_manager.get(actual.source_id()).ok();
137        let source_file = source_manager.get(span.source_id()).ok();
138        Self::InvalidSymbolType {
139            expected,
140            span,
141            source_file,
142            actual: Some(
143                RelatedLabel::advice("but the symbol resolved to this item")
144                    .with_labeled_span(actual, "but the symbol resolved to this item")
145                    .with_source_file(actual_source_file),
146            ),
147        }
148    }
149
150    pub fn private_symbol(
151        span: SourceSpan,
152        defined: SourceSpan,
153        source_manager: &dyn SourceManager,
154    ) -> Self {
155        let defined_source_file = source_manager.get(defined.source_id()).ok();
156        let source_file = source_manager.get(span.source_id()).ok();
157        Self::PrivateSymbol {
158            span,
159            source_file,
160            defined: Some(
161                RelatedLabel::advice("the referenced item is private")
162                    .with_labeled_span(defined, "the referenced item is private")
163                    .with_source_file(defined_source_file),
164            ),
165        }
166    }
167
168    pub fn type_expression_depth_exceeded(
169        span: SourceSpan,
170        max_depth: usize,
171        source_manager: &dyn SourceManager,
172    ) -> Self {
173        Self::TypeExpressionDepthExceeded {
174            span,
175            source_file: source_manager.get(span.source_id()).ok(),
176            max_depth,
177        }
178    }
179
180    pub fn alias_expansion_depth_exceeded(
181        span: SourceSpan,
182        max_depth: usize,
183        source_manager: &dyn SourceManager,
184    ) -> Self {
185        Self::AliasExpansionDepthExceeded {
186            span,
187            source_file: source_manager.get(span.source_id()).ok(),
188            max_depth,
189        }
190    }
191
192    pub fn too_many_items_in_module(span: SourceSpan, source_manager: &dyn SourceManager) -> Self {
193        Self::TooManyItemsInModule {
194            span,
195            source_file: source_manager.get(span.source_id()).ok(),
196            max_items: ItemIndex::MAX_ITEMS,
197        }
198    }
199}