Skip to main content

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