miden_assembly/linker/
errors.rs

1// Allow unused assignments - required by miette::Diagnostic derive macro
2#![allow(unused_assignments)]
3
4use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
5
6use miden_assembly_syntax::{
7    Felt, Path,
8    ast::{SymbolResolutionError, constants::ConstEvalError},
9    debuginfo::{SourceFile, SourceSpan},
10    diagnostics::{Diagnostic, RelatedError, RelatedLabel, miette},
11};
12use miden_core::{FieldElement, utils::to_hex};
13
14// LINKER ERROR
15// ================================================================================================
16
17/// An error which can be generated while linking modules and resolving procedure references.
18#[derive(Debug, thiserror::Error, Diagnostic)]
19#[non_exhaustive]
20pub enum LinkerError {
21    #[error("there are no modules to analyze")]
22    #[diagnostic()]
23    Empty,
24    #[error(transparent)]
25    #[diagnostic(transparent)]
26    SymbolResolution(#[from] Box<SymbolResolutionError>),
27    #[error(transparent)]
28    #[diagnostic(transparent)]
29    ConstEval(#[from] Box<ConstEvalError>),
30    #[error("linking failed")]
31    #[diagnostic(help("see diagnostics for details"))]
32    Related {
33        #[related]
34        errors: Box<[RelatedError]>,
35    },
36    #[error("linking failed")]
37    #[diagnostic(help("see diagnostics for details"))]
38    Failed {
39        #[related]
40        labels: Box<[RelatedLabel]>,
41    },
42    #[error("found a cycle in the call graph, involving these procedures: {}", nodes.join(", "))]
43    #[diagnostic()]
44    Cycle { nodes: Box<[String]> },
45    #[error("duplicate definition found for module '{path}'")]
46    #[diagnostic()]
47    DuplicateModule { path: Arc<Path> },
48    #[error("undefined module '{path}'")]
49    #[diagnostic()]
50    UndefinedModule {
51        #[label]
52        span: SourceSpan,
53        #[source_code]
54        source_file: Option<Arc<SourceFile>>,
55        path: Arc<Path>,
56    },
57    #[error("undefined item '{path}'")]
58    #[diagnostic(help(
59        "you might be missing an import, or the containing library has not been linked"
60    ))]
61    UndefinedSymbol {
62        #[label]
63        span: SourceSpan,
64        #[source_code]
65        source_file: Option<Arc<SourceFile>>,
66        path: Arc<Path>,
67    },
68    #[error("invalid syscall: '{callee}' is not an exported kernel procedure")]
69    #[diagnostic()]
70    InvalidSysCallTarget {
71        #[label("call occurs here")]
72        span: SourceSpan,
73        #[source_code]
74        source_file: Option<Arc<SourceFile>>,
75        callee: Arc<Path>,
76    },
77    #[error("invalid procedure reference: path refers to a non-procedure item")]
78    #[diagnostic()]
79    InvalidInvokeTarget {
80        #[label("this path resolves to {path}, which is not a procedure")]
81        span: SourceSpan,
82        #[source_code]
83        source_file: Option<Arc<SourceFile>>,
84        path: Arc<Path>,
85    },
86    #[error("value for key {} already present in the advice map", to_hex(Felt::elements_as_bytes(.key)))]
87    #[diagnostic(help(
88        "previous values at key were '{prev_values:?}'. Operation would have replaced them with '{new_values:?}'",
89    ))]
90    AdviceMapKeyAlreadyPresent {
91        key: [Felt; 4],
92        prev_values: Vec<Felt>,
93        new_values: Vec<Felt>,
94    },
95    #[error("undefined type alias")]
96    #[diagnostic()]
97    UndefinedType {
98        #[label]
99        span: SourceSpan,
100        #[source_code]
101        source_file: Option<Arc<SourceFile>>,
102    },
103    #[error("invalid type reference")]
104    #[diagnostic(help("the item this path resolves to is not a type definition"))]
105    InvalidTypeRef {
106        #[label]
107        span: SourceSpan,
108        #[source_code]
109        source_file: Option<Arc<SourceFile>>,
110    },
111    #[error("invalid constant reference")]
112    #[diagnostic(help("the item this path resolves to is not a constant definition"))]
113    InvalidConstantRef {
114        #[label]
115        span: SourceSpan,
116        #[source_code]
117        source_file: Option<Arc<SourceFile>>,
118    },
119}
120
121impl From<SymbolResolutionError> for LinkerError {
122    #[inline]
123    fn from(value: SymbolResolutionError) -> Self {
124        Self::SymbolResolution(Box::new(value))
125    }
126}
127
128impl From<ConstEvalError> for LinkerError {
129    #[inline]
130    fn from(value: ConstEvalError) -> Self {
131        Self::ConstEval(Box::new(value))
132    }
133}