1#![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#[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("invalid module surface metadata for package '{package}': {reason}")]
48 #[diagnostic()]
49 InvalidPackageModuleSurface { package: String, reason: String },
50 #[error("ambiguous module path resolution for '{path}'")]
51 #[diagnostic(help("matching module prefixes: {}", matches.join(", ")))]
52 AmbiguousModulePath {
53 #[label]
54 span: SourceSpan,
55 #[source_code]
56 source_file: Option<Arc<SourceFile>>,
57 path: Arc<Path>,
58 matches: Box<[String]>,
59 },
60 #[error("undefined module '{path}'")]
61 #[diagnostic()]
62 UndefinedModule {
63 #[label]
64 span: SourceSpan,
65 #[source_code]
66 source_file: Option<Arc<SourceFile>>,
67 path: Arc<Path>,
68 },
69 #[error("private submodule '{module}'")]
70 #[diagnostic(help("only public submodules can be imported from another module"))]
71 PrivateSubmodule {
72 #[label("this submodule is private")]
73 span: SourceSpan,
74 #[source_code]
75 source_file: Option<Arc<SourceFile>>,
76 module: Arc<Path>,
77 #[related]
78 defined: Option<RelatedLabel>,
79 },
80 #[error(
81 "module '{path}' is not declared by its parent module '{parent}' as `mod {name}` or `pub mod {name}`"
82 )]
83 #[diagnostic(help(
84 "source modules must be declared by their parent module before they can be linked as descendants"
85 ))]
86 UndeclaredSubmodule {
87 path: Arc<Path>,
88 parent: Arc<Path>,
89 name: String,
90 },
91 #[error(
92 "name conflict in module '{module}': {kind} '{name}' conflicts with an existing item, import, or submodule"
93 )]
94 #[diagnostic()]
95 NamespaceNameConflict {
96 #[label("conflicting namespace member")]
97 span: SourceSpan,
98 #[source_code]
99 source_file: Option<Arc<SourceFile>>,
100 module: Arc<Path>,
101 name: String,
102 kind: &'static str,
103 },
104 #[error("modules cannot be re-exported with `pub use`: '{path}'")]
105 #[diagnostic(help(
106 "declare the module with `pub mod` in its parent module instead of re-exporting it"
107 ))]
108 ModuleReExport {
109 #[label("this `pub use` resolves to a module")]
110 span: SourceSpan,
111 #[source_code]
112 source_file: Option<Arc<SourceFile>>,
113 path: Arc<Path>,
114 },
115 #[error("module import target '{path}' resolved to an item")]
116 #[diagnostic(help(
117 "module-form imports must target modules; use `use {{item}} from module` for items"
118 ))]
119 InvalidModuleImportTarget {
120 #[label("this import expects a module target")]
121 span: SourceSpan,
122 #[source_code]
123 source_file: Option<Arc<SourceFile>>,
124 path: Arc<Path>,
125 },
126 #[error("item import target '{path}' resolved to a module")]
127 #[diagnostic(help("item-form imports may only import procedures, constants, or types"))]
128 InvalidItemImportTarget {
129 #[label("this import expects an item target")]
130 span: SourceSpan,
131 #[source_code]
132 source_file: Option<Arc<SourceFile>>,
133 path: Arc<Path>,
134 },
135 #[error("invalid re-export of kernel syscall '{path}'")]
136 #[diagnostic(help(
137 "re-export of kernel procedures is not permitted, except from the kernel root"
138 ))]
139 InvalidReExportOfKernelSyscall {
140 #[label("this import attempts to re-export a kernel syscall")]
141 span: SourceSpan,
142 #[source_code]
143 source_file: Option<Arc<SourceFile>>,
144 path: Arc<Path>,
145 },
146 #[error("import re-export cycle involving '{path}'")]
147 #[diagnostic(help("public item re-exports must not form cycles"))]
148 ImportReExportCycle {
149 #[label("this import participates in a re-export cycle")]
150 span: SourceSpan,
151 #[source_code]
152 source_file: Option<Arc<SourceFile>>,
153 path: Arc<Path>,
154 },
155 #[error("import target '{path}' cannot be resolved through import '{alias}'")]
156 #[diagnostic(help(
157 "imports are resolved independently; use the original global path instead of another import alias"
158 ))]
159 ImportTargetUsesImport {
160 #[label("this import target starts with another import alias")]
161 span: SourceSpan,
162 #[source_code]
163 source_file: Option<Arc<SourceFile>>,
164 path: Arc<Path>,
165 alias: String,
166 },
167 #[error("self-referential import of module '{path}'")]
168 #[diagnostic(help(
169 "a module cannot import itself; reference local items directly or use absolute paths in code"
170 ))]
171 SelfReferentialImport {
172 #[label("this import resolves to the module that contains it")]
173 span: SourceSpan,
174 #[source_code]
175 source_file: Option<Arc<SourceFile>>,
176 path: Arc<Path>,
177 },
178 #[error("cannot import submodule '{path}' declared in the same module")]
179 #[diagnostic(help(
180 "reference the submodule directly with a submodule-qualified path instead of importing it"
181 ))]
182 ImportTargetIsLocalSubmodule {
183 #[label("this import resolves to a submodule declared in the same scope")]
184 span: SourceSpan,
185 #[source_code]
186 source_file: Option<Arc<SourceFile>>,
187 path: Arc<Path>,
188 },
189 #[error("invalid relative item path '{path}'")]
190 #[diagnostic(help(
191 "item paths must be absolute, local, or qualified by an import or submodule in the current module"
192 ))]
193 InvalidRelativePath {
194 #[label("this path does not start with a local item, import, or submodule")]
195 span: SourceSpan,
196 #[source_code]
197 source_file: Option<Arc<SourceFile>>,
198 path: Arc<Path>,
199 },
200 #[error("undefined item '{path}'")]
201 #[diagnostic(help(
202 "you might be missing an import, or the containing library has not been linked"
203 ))]
204 UndefinedSymbol {
205 #[label]
206 span: SourceSpan,
207 #[source_code]
208 source_file: Option<Arc<SourceFile>>,
209 path: Arc<Path>,
210 },
211 #[error("invalid syscall: '{callee}' is not an exported kernel procedure")]
212 #[diagnostic()]
213 InvalidSysCallTarget {
214 #[label("call occurs here")]
215 span: SourceSpan,
216 #[source_code]
217 source_file: Option<Arc<SourceFile>>,
218 callee: Arc<Path>,
219 },
220 #[error("kernel procedure '{callee}' can only be invoked via syscall")]
221 #[diagnostic()]
222 KernelProcNotSyscall {
223 #[label("non-syscall reference to kernel procedure")]
224 span: SourceSpan,
225 #[source_code]
226 source_file: Option<Arc<SourceFile>>,
227 callee: Arc<Path>,
228 },
229 #[error("invalid procedure reference: path refers to a non-procedure item")]
230 #[diagnostic()]
231 InvalidInvokeTarget {
232 #[label("this path resolves to {path}, which is not a procedure")]
233 span: SourceSpan,
234 #[source_code]
235 source_file: Option<Arc<SourceFile>>,
236 path: Arc<Path>,
237 },
238 #[error("value for key {key} already present in the advice map")]
239 #[diagnostic(help(
240 "previous values at key were '{prev_values:?}'. Operation would have replaced them with '{new_values:?}'",
241 ))]
242 AdviceMapKeyAlreadyPresent {
243 key: Word,
244 prev_values: Vec<Felt>,
245 new_values: Vec<Felt>,
246 },
247 #[error("undefined type alias")]
248 #[diagnostic()]
249 UndefinedType {
250 #[label]
251 span: SourceSpan,
252 #[source_code]
253 source_file: Option<Arc<SourceFile>>,
254 },
255 #[error("invalid type reference")]
256 #[diagnostic(help("the item this path resolves to is not a type definition"))]
257 InvalidTypeRef {
258 #[label]
259 span: SourceSpan,
260 #[source_code]
261 source_file: Option<Arc<SourceFile>>,
262 },
263 #[error("invalid constant reference")]
264 #[diagnostic(help("the item this path resolves to is not a constant definition"))]
265 InvalidConstantRef {
266 #[label]
267 span: SourceSpan,
268 #[source_code]
269 source_file: Option<Arc<SourceFile>>,
270 },
271}
272
273impl From<SymbolResolutionError> for LinkerError {
274 #[inline]
275 fn from(value: SymbolResolutionError) -> Self {
276 Self::SymbolResolution(Box::new(value))
277 }
278}
279
280impl From<ConstEvalError> for LinkerError {
281 #[inline]
282 fn from(value: ConstEvalError) -> Self {
283 Self::ConstEval(Box::new(value))
284 }
285}