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::diagnostics::{Diagnostic, RelatedLabel, miette};
9
10/// Represents an error that occurs during symbol resolution
11#[derive(Debug, Clone, thiserror::Error, Diagnostic)]
12pub enum SymbolResolutionError {
13    #[error("undefined symbol reference")]
14    #[diagnostic(help("maybe you are missing an import?"))]
15    UndefinedSymbol {
16        #[label("this symbol path could not be resolved")]
17        span: SourceSpan,
18        #[source_code]
19        source_file: Option<Arc<SourceFile>>,
20    },
21    #[error("invalid symbol reference")]
22    #[diagnostic(help(
23        "references to a subpath of an imported symbol require the imported item to be a module"
24    ))]
25    InvalidAliasTarget {
26        #[label("this reference specifies a subpath relative to an import")]
27        span: SourceSpan,
28        #[source_code]
29        source_file: Option<Arc<SourceFile>>,
30        #[related]
31        relative_to: Option<RelatedLabel>,
32    },
33    #[error("invalid symbol path")]
34    #[diagnostic(help("all ancestors of a path must be modules"))]
35    InvalidSubPath {
36        #[label("this path specifies a subpath relative to another item")]
37        span: SourceSpan,
38        #[source_code]
39        source_file: Option<Arc<SourceFile>>,
40        #[related]
41        relative_to: Option<RelatedLabel>,
42    },
43    #[error("invalid symbol reference: wrong type")]
44    #[diagnostic()]
45    InvalidSymbolType {
46        expected: &'static str,
47        #[label("expected this symbol to reference a {expected} item")]
48        span: SourceSpan,
49        #[source_code]
50        source_file: Option<Arc<SourceFile>>,
51        #[related]
52        actual: Option<RelatedLabel>,
53    },
54}
55
56impl SymbolResolutionError {
57    pub fn undefined(span: SourceSpan, source_manager: &dyn SourceManager) -> Self {
58        Self::UndefinedSymbol {
59            span,
60            source_file: source_manager.get(span.source_id()).ok(),
61        }
62    }
63
64    pub fn invalid_alias_target(
65        span: SourceSpan,
66        referrer: SourceSpan,
67        source_manager: &dyn SourceManager,
68    ) -> Self {
69        let referer_source_file = source_manager.get(referrer.source_id()).ok();
70        let source_file = source_manager.get(span.source_id()).ok();
71        Self::InvalidAliasTarget {
72            span,
73            source_file,
74            relative_to: Some(
75                RelatedLabel::advice("this reference specifies a subpath relative to an import")
76                    .with_labeled_span(
77                        referrer,
78                        "this reference specifies a subpath relative to an import",
79                    )
80                    .with_source_file(referer_source_file),
81            ),
82        }
83    }
84
85    pub fn invalid_sub_path(
86        span: SourceSpan,
87        relative_to: SourceSpan,
88        source_manager: &dyn SourceManager,
89    ) -> Self {
90        let relative_to_source_file = source_manager.get(relative_to.source_id()).ok();
91        let source_file = source_manager.get(span.source_id()).ok();
92        Self::InvalidSubPath {
93            span,
94            source_file,
95            relative_to: Some(
96                RelatedLabel::advice("but this item is not a module")
97                    .with_labeled_span(relative_to, "but this item is not a module")
98                    .with_source_file(relative_to_source_file),
99            ),
100        }
101    }
102
103    pub fn invalid_symbol_type(
104        span: SourceSpan,
105        expected: &'static str,
106        actual: SourceSpan,
107        source_manager: &dyn SourceManager,
108    ) -> Self {
109        let actual_source_file = source_manager.get(actual.source_id()).ok();
110        let source_file = source_manager.get(span.source_id()).ok();
111        Self::InvalidSymbolType {
112            expected,
113            span,
114            source_file,
115            actual: Some(
116                RelatedLabel::advice("but the symbol resolved to this item")
117                    .with_labeled_span(actual, "but the symbol resolved to this item")
118                    .with_source_file(actual_source_file),
119            ),
120        }
121    }
122}