1use alloc::{boxed::Box, sync::Arc, vec::Vec};
2use core::error::Error;
3
4use miden_air::RowIndex;
5use miette::Diagnostic;
6use vm_core::{
7 debuginfo::{SourceFile, SourceManager, SourceSpan},
8 mast::{BasicBlockNode, DecoratorId, MastForest, MastNodeExt, MastNodeId},
9 stack::MIN_STACK_DEPTH,
10 utils::to_hex,
11};
12use winter_prover::{ProverError, math::FieldElement};
13
14use super::{
15 Digest, Felt, QuadFelt, Word,
16 crypto::MerkleError,
17 system::{FMP_MAX, FMP_MIN},
18};
19use crate::MemoryError;
20
21#[derive(Debug, thiserror::Error, Diagnostic)]
25pub enum ExecutionError {
26 #[error("value for key {} not present in the advice map", to_hex(Felt::elements_as_bytes(.key)))]
27 #[diagnostic()]
28 AdviceMapKeyNotFound {
29 #[label]
30 label: SourceSpan,
31 #[source_code]
32 source_file: Option<Arc<SourceFile>>,
33 key: Word,
34 },
35 #[error("value for key {} already present in the advice map when loading MAST forest", to_hex(Felt::elements_as_bytes(.key)))]
36 #[diagnostic(help(
37 "previous values at key were '{prev_values:?}'. Operation would have replaced them with '{new_values:?}'",
38 ))]
39 AdviceMapKeyAlreadyPresent {
40 key: Word,
41 prev_values: Vec<Felt>,
42 new_values: Vec<Felt>,
43 },
44 #[error("advice stack read failed at clock cycle {row}")]
45 #[diagnostic()]
46 AdviceStackReadFailed {
47 #[label]
48 label: SourceSpan,
49 #[source_code]
50 source_file: Option<Arc<SourceFile>>,
51 row: RowIndex,
52 },
53 #[error("illegal use of instruction {0} while inside a syscall")]
55 CallInSyscall(&'static str),
56 #[error("instruction `caller` used outside of kernel context")]
58 CallerNotInSyscall,
59 #[error("external node with mast root {0} resolved to an external node")]
60 CircularExternalNode(Digest),
61 #[error("exceeded the allowed number of max cycles {0}")]
62 CycleLimitExceeded(u32),
63 #[error("decorator id {decorator_id} does not exist in MAST forest")]
64 DecoratorNotFoundInForest { decorator_id: DecoratorId },
65 #[error("division by zero at clock cycle {clk}")]
66 #[diagnostic()]
67 DivideByZero {
68 #[label]
69 label: SourceSpan,
70 #[source_code]
71 source_file: Option<Arc<SourceFile>>,
72 clk: RowIndex,
73 },
74 #[error("failed to execute the dynamic code block provided by the stack with root 0x{hex}; the block could not be found",
75 hex = to_hex(.digest.as_bytes())
76 )]
77 #[diagnostic()]
78 DynamicNodeNotFound {
79 #[label]
80 label: SourceSpan,
81 #[source_code]
82 source_file: Option<Arc<SourceFile>>,
83 digest: Digest,
84 },
85 #[error("error during processing of event in on_event handler")]
86 #[diagnostic()]
87 EventError {
88 #[label]
89 label: SourceSpan,
90 #[source_code]
91 source_file: Option<Arc<SourceFile>>,
92 #[source]
93 error: Box<dyn Error + Send + Sync + 'static>,
94 },
95 #[error("failed to execute Ext2Intt operation: {0}")]
96 Ext2InttError(Ext2InttError),
97 #[error("assertion failed at clock cycle {clk} with error {}",
98 match err_msg {
99 Some(msg) => format!("message: {msg}"),
100 None => format!("code: {err_code}"),
101 }
102 )]
103 #[diagnostic()]
104 FailedAssertion {
105 #[label]
106 label: SourceSpan,
107 #[source_code]
108 source_file: Option<Arc<SourceFile>>,
109 clk: RowIndex,
110 err_code: Felt,
111 err_msg: Option<Arc<str>>,
112 },
113 #[error("failed to execute the program for internal reason: {0}")]
114 FailedToExecuteProgram(&'static str),
115 #[error(
116 "Updating FMP register from {0} to {1} failed because {1} is outside of {FMP_MIN}..{FMP_MAX}"
117 )]
118 InvalidFmpValue(Felt, Felt),
119 #[error("FRI domain segment value cannot exceed 3, but was {0}")]
120 InvalidFriDomainSegment(u64),
121 #[error("degree-respecting projection is inconsistent: expected {0} but was {1}")]
122 InvalidFriLayerFolding(QuadFelt, QuadFelt),
123 #[error(
124 "when returning from a call or dyncall, stack depth must be {MIN_STACK_DEPTH}, but was {depth}"
125 )]
126 #[diagnostic()]
127 InvalidStackDepthOnReturn {
128 #[label("when returning from this call site")]
129 label: SourceSpan,
130 #[source_code]
131 source_file: Option<Arc<SourceFile>>,
132 depth: usize,
133 },
134 #[error(
135 "provided merkle tree {depth} is out of bounds and cannot be represented as an unsigned 8-bit integer"
136 )]
137 #[diagnostic()]
138 InvalidMerkleTreeDepth {
139 #[label]
140 label: SourceSpan,
141 #[source_code]
142 source_file: Option<Arc<SourceFile>>,
143 depth: Felt,
144 },
145 #[error("provided node index {index} is out of bounds for a merkle tree node at depth {depth}")]
146 #[diagnostic()]
147 InvalidMerkleTreeNodeIndex {
148 #[label]
149 label: SourceSpan,
150 #[source_code]
151 source_file: Option<Arc<SourceFile>>,
152 depth: Felt,
153 index: Felt,
154 },
155 #[error("attempted to calculate integer logarithm with zero argument at clock cycle {clk}")]
156 #[diagnostic()]
157 LogArgumentZero {
158 #[label]
159 label: SourceSpan,
160 #[source_code]
161 source_file: Option<Arc<SourceFile>>,
162 clk: RowIndex,
163 },
164 #[error("malformed signature key: {key_type}")]
165 #[diagnostic(help("the secret key associated with the provided public key is malformed"))]
166 MalformedSignatureKey {
167 #[label]
168 label: SourceSpan,
169 #[source_code]
170 source_file: Option<Arc<SourceFile>>,
171 key_type: &'static str,
172 },
173 #[error(
174 "MAST forest in host indexed by procedure root {root_digest} doesn't contain that root"
175 )]
176 MalformedMastForestInHost {
177 #[label]
178 label: SourceSpan,
179 #[source_code]
180 source_file: Option<Arc<SourceFile>>,
181 root_digest: Digest,
182 },
183 #[error("node id {node_id} does not exist in MAST forest")]
184 MastNodeNotFoundInForest { node_id: MastNodeId },
185 #[error(transparent)]
186 #[diagnostic(transparent)]
187 MemoryError(MemoryError),
188 #[error("no MAST forest contains the procedure with root digest {root_digest}")]
189 NoMastForestWithProcedure {
190 #[label]
191 label: SourceSpan,
192 #[source_code]
193 source_file: Option<Arc<SourceFile>>,
194 root_digest: Digest,
195 },
196 #[error("merkle path verification failed for value {value} at index {index} in the Merkle tree with root {root} (error {err})",
197 value = to_hex(Felt::elements_as_bytes(value)),
198 root = to_hex(root.as_bytes()),
199 err = match err_msg {
200 Some(msg) => format!("message: {msg}"),
201 None => format!("code: {err_code}"),
202 }
203 )]
204 MerklePathVerificationFailed {
205 #[label]
206 label: SourceSpan,
207 #[source_code]
208 source_file: Option<Arc<SourceFile>>,
209 value: Word,
210 index: Felt,
211 root: Digest,
212 err_code: Felt,
213 err_msg: Option<Arc<str>>,
214 },
215 #[error("failed to lookup value in Merkle store")]
216 MerkleStoreLookupFailed {
217 #[label]
218 label: SourceSpan,
219 #[source_code]
220 source_file: Option<Arc<SourceFile>>,
221 #[source]
222 err: MerkleError,
223 },
224 #[error("advice provider Merkle store backend merge failed")]
225 MerkleStoreMergeFailed {
226 #[label]
227 label: SourceSpan,
228 #[source_code]
229 source_file: Option<Arc<SourceFile>>,
230 #[source]
231 err: MerkleError,
232 },
233 #[error("advice provider Merkle store backend update failed")]
234 MerkleStoreUpdateFailed {
235 #[label]
236 label: SourceSpan,
237 #[source_code]
238 source_file: Option<Arc<SourceFile>>,
239 #[source]
240 err: MerkleError,
241 },
242 #[error("if statement expected a binary value on top of the stack, but got {value}")]
243 #[diagnostic()]
244 NotBinaryValueIf {
245 #[label]
246 label: SourceSpan,
247 #[source_code]
248 source_file: Option<Arc<SourceFile>>,
249 value: Felt,
250 },
251 #[error("operation expected a binary value, but got {value}")]
252 #[diagnostic()]
253 NotBinaryValueOp {
254 #[label]
255 label: SourceSpan,
256 #[source_code]
257 source_file: Option<Arc<SourceFile>>,
258 value: Felt,
259 },
260 #[error("loop condition must be a binary value, but got {value}")]
261 #[diagnostic(help(
262 "this could happen either when first entering the loop, or any subsequent iteration"
263 ))]
264 NotBinaryValueLoop {
265 #[label]
266 label: SourceSpan,
267 #[source_code]
268 source_file: Option<Arc<SourceFile>>,
269 value: Felt,
270 },
271 #[error("operation expected a u32 value, but got {value} (error code: {err_code})")]
272 NotU32Value {
273 #[label]
274 label: SourceSpan,
275 #[source_code]
276 source_file: Option<Arc<SourceFile>>,
277 value: Felt,
278 err_code: Felt,
279 },
280 #[error(
281 "Operand stack input is {input} but it is expected to fit in a u32 at clock cycle {clk}"
282 )]
283 #[diagnostic()]
284 NotU32StackValue {
285 #[label]
286 label: SourceSpan,
287 #[source_code]
288 source_file: Option<Arc<SourceFile>>,
289 clk: RowIndex,
290 input: u64,
291 },
292 #[error("stack should have at most {MIN_STACK_DEPTH} elements at the end of program execution, but had {} elements", MIN_STACK_DEPTH + .0)]
293 OutputStackOverflow(usize),
294 #[error("a program has already been executed in this process")]
295 ProgramAlreadyExecuted,
296 #[error("proof generation failed")]
297 ProverError(#[source] ProverError),
298 #[error("smt node {node_hex} not found", node_hex = to_hex(Felt::elements_as_bytes(node)))]
299 SmtNodeNotFound {
300 #[label]
301 label: SourceSpan,
302 #[source_code]
303 source_file: Option<Arc<SourceFile>>,
304 node: Word,
305 },
306 #[error("expected pre-image length of node {node_hex} to be a multiple of 8 but was {preimage_len}",
307 node_hex = to_hex(Felt::elements_as_bytes(node)),
308 )]
309 SmtNodePreImageNotValid {
310 #[label]
311 label: SourceSpan,
312 #[source_code]
313 source_file: Option<Arc<SourceFile>>,
314 node: Word,
315 preimage_len: usize,
316 },
317 #[error("syscall failed: procedure with root {hex} was not found in the kernel",
318 hex = to_hex(proc_root.as_bytes())
319 )]
320 SyscallTargetNotInKernel {
321 #[label]
322 label: SourceSpan,
323 #[source_code]
324 source_file: Option<Arc<SourceFile>>,
325 proc_root: Digest,
326 },
327 #[error("failed to execute arithmetic circuit evaluation operation: {error}")]
328 #[diagnostic()]
329 AceChipError {
330 #[label("this call failed")]
331 label: SourceSpan,
332 #[source_code]
333 source_file: Option<Arc<SourceFile>>,
334 error: AceError,
335 },
336}
337
338impl From<Ext2InttError> for ExecutionError {
339 fn from(value: Ext2InttError) -> Self {
340 Self::Ext2InttError(value)
341 }
342}
343
344impl ExecutionError {
345 pub fn advice_map_key_not_found(
346 key: Word,
347 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
348 ) -> Self {
349 let (label, source_file) = err_ctx.label_and_source_file();
350 Self::AdviceMapKeyNotFound { label, source_file, key }
351 }
352
353 pub fn advice_stack_read_failed(
354 row: RowIndex,
355 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
356 ) -> Self {
357 let (label, source_file) = err_ctx.label_and_source_file();
358 Self::AdviceStackReadFailed { label, source_file, row }
359 }
360
361 pub fn divide_by_zero(clk: RowIndex, err_ctx: &ErrorContext<'_, impl MastNodeExt>) -> Self {
362 let (label, source_file) = err_ctx.label_and_source_file();
363 Self::DivideByZero { clk, label, source_file }
364 }
365
366 pub fn input_not_u32(
367 clk: RowIndex,
368 input: u64,
369 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
370 ) -> Self {
371 let (label, source_file) = err_ctx.label_and_source_file();
372 Self::NotU32StackValue { clk, input, label, source_file }
373 }
374
375 pub fn dynamic_node_not_found(
376 digest: Digest,
377 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
378 ) -> Self {
379 let (label, source_file) = err_ctx.label_and_source_file();
380
381 Self::DynamicNodeNotFound { label, source_file, digest }
382 }
383
384 pub fn event_error(
385 error: Box<dyn Error + Send + Sync + 'static>,
386 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
387 ) -> Self {
388 let (label, source_file) = err_ctx.label_and_source_file();
389
390 Self::EventError { label, source_file, error }
391 }
392
393 pub fn failed_assertion(
394 clk: RowIndex,
395 err_code: Felt,
396 err_msg: Option<Arc<str>>,
397 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
398 ) -> Self {
399 let (label, source_file) = err_ctx.label_and_source_file();
400
401 Self::FailedAssertion {
402 label,
403 source_file,
404 clk,
405 err_code,
406 err_msg,
407 }
408 }
409
410 pub fn invalid_merkle_tree_depth(
411 depth: Felt,
412 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
413 ) -> Self {
414 let (label, source_file) = err_ctx.label_and_source_file();
415 Self::InvalidMerkleTreeDepth { label, source_file, depth }
416 }
417
418 pub fn invalid_merkle_tree_node_index(
419 depth: Felt,
420 index: Felt,
421 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
422 ) -> Self {
423 let (label, source_file) = err_ctx.label_and_source_file();
424 Self::InvalidMerkleTreeNodeIndex { label, source_file, depth, index }
425 }
426
427 pub fn invalid_stack_depth_on_return(
428 depth: usize,
429 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
430 ) -> Self {
431 let (label, source_file) = err_ctx.label_and_source_file();
432 Self::InvalidStackDepthOnReturn { label, source_file, depth }
433 }
434
435 pub fn log_argument_zero(clk: RowIndex, err_ctx: &ErrorContext<'_, impl MastNodeExt>) -> Self {
436 let (label, source_file) = err_ctx.label_and_source_file();
437 Self::LogArgumentZero { label, source_file, clk }
438 }
439
440 pub fn malfored_mast_forest_in_host(
441 root_digest: Digest,
442 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
443 ) -> Self {
444 let (label, source_file) = err_ctx.label_and_source_file();
445 Self::MalformedMastForestInHost { label, source_file, root_digest }
446 }
447
448 pub fn malformed_signature_key(
449 key_type: &'static str,
450 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
451 ) -> Self {
452 let (label, source_file) = err_ctx.label_and_source_file();
453 Self::MalformedSignatureKey { label, source_file, key_type }
454 }
455
456 pub fn merkle_path_verification_failed(
457 value: Word,
458 index: Felt,
459 root: Digest,
460 err_code: Felt,
461 err_msg: Option<Arc<str>>,
462 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
463 ) -> Self {
464 let (label, source_file) = err_ctx.label_and_source_file();
465
466 Self::MerklePathVerificationFailed {
467 label,
468 source_file,
469 value,
470 index,
471 root,
472 err_code,
473 err_msg,
474 }
475 }
476
477 pub fn merkle_store_lookup_failed(
478 err: MerkleError,
479 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
480 ) -> Self {
481 let (label, source_file) = err_ctx.label_and_source_file();
482 Self::MerkleStoreLookupFailed { label, source_file, err }
483 }
484
485 pub fn merkle_store_merge_failed(
487 err: MerkleError,
488 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
489 ) -> Self {
490 let (label, source_file) = err_ctx.label_and_source_file();
491 Self::MerkleStoreMergeFailed { label, source_file, err }
492 }
493
494 pub fn merkle_store_update_failed(
495 err: MerkleError,
496 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
497 ) -> Self {
498 let (label, source_file) = err_ctx.label_and_source_file();
499 Self::MerkleStoreUpdateFailed { label, source_file, err }
500 }
501
502 pub fn no_mast_forest_with_procedure(
503 root_digest: Digest,
504 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
505 ) -> Self {
506 let (label, source_file) = err_ctx.label_and_source_file();
507 Self::NoMastForestWithProcedure { label, source_file, root_digest }
508 }
509
510 pub fn not_binary_value_if(value: Felt, err_ctx: &ErrorContext<'_, impl MastNodeExt>) -> Self {
511 let (label, source_file) = err_ctx.label_and_source_file();
512 Self::NotBinaryValueIf { label, source_file, value }
513 }
514
515 pub fn not_binary_value_op(value: Felt, err_ctx: &ErrorContext<'_, impl MastNodeExt>) -> Self {
516 let (label, source_file) = err_ctx.label_and_source_file();
517 Self::NotBinaryValueOp { label, source_file, value }
518 }
519
520 pub fn not_binary_value_loop(
521 value: Felt,
522 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
523 ) -> Self {
524 let (label, source_file) = err_ctx.label_and_source_file();
525 Self::NotBinaryValueLoop { label, source_file, value }
526 }
527
528 pub fn not_u32_value(
529 value: Felt,
530 err_code: Felt,
531 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
532 ) -> Self {
533 let (label, source_file) = err_ctx.label_and_source_file();
534 Self::NotU32Value { label, source_file, value, err_code }
535 }
536
537 pub fn smt_node_not_found(node: Word, err_ctx: &ErrorContext<'_, impl MastNodeExt>) -> Self {
538 let (label, source_file) = err_ctx.label_and_source_file();
539 Self::SmtNodeNotFound { label, source_file, node }
540 }
541
542 pub fn smt_node_preimage_not_valid(
543 node: Word,
544 preimage_len: usize,
545 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
546 ) -> Self {
547 let (label, source_file) = err_ctx.label_and_source_file();
548 Self::SmtNodePreImageNotValid { label, source_file, node, preimage_len }
549 }
550
551 pub fn syscall_target_not_in_kernel(
552 proc_root: Digest,
553 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
554 ) -> Self {
555 let (label, source_file) = err_ctx.label_and_source_file();
556 Self::SyscallTargetNotInKernel { label, source_file, proc_root }
557 }
558
559 pub fn failed_arithmetic_evaluation(
560 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
561 error: AceError,
562 ) -> Self {
563 let (label, source_file) = err_ctx.label_and_source_file();
564 Self::AceChipError { label, source_file, error }
565 }
566}
567
568impl AsRef<dyn Diagnostic> for ExecutionError {
569 fn as_ref(&self) -> &(dyn Diagnostic + 'static) {
570 self
571 }
572}
573
574#[derive(Debug, thiserror::Error)]
578pub enum AceError {
579 #[error("num of variables should be word aligned and non-zero but was {0}")]
580 NumVarIsNotWordAlignedOrIsEmpty(u64),
581 #[error("num of evaluation gates should be word aligned and non-zero but was {0}")]
582 NumEvalIsNotWordAlignedOrIsEmpty(u64),
583 #[error("circuit does not evaluate to zero")]
584 CircuitNotEvaluateZero,
585 #[error("failed to read from memory")]
586 FailedMemoryRead,
587 #[error("failed to decode instruction")]
588 FailedDecodeInstruction,
589 #[error("failed to read from the wiring bus")]
590 FailedWireBusRead,
591 #[error("num of wires must be less than 2^30 but was {0}")]
592 TooManyWires(u64),
593}
594
595#[derive(Debug, thiserror::Error)]
599pub enum Ext2InttError {
600 #[error("input domain size must be a power of two, but was {0}")]
601 DomainSizeNotPowerOf2(u64),
602 #[error("input domain size ({0} elements) is too small")]
603 DomainSizeTooSmall(u64),
604 #[error("address of the last input must be smaller than 2^32, but was {0}")]
605 InputEndAddressTooBig(u64),
606 #[error("input size must be smaller than 2^32, but was {0}")]
607 InputSizeTooBig(u64),
608 #[error("address of the first input must be smaller than 2^32, but was {0}")]
609 InputStartAddressTooBig(u64),
610 #[error("address of the first input is not word aligned: {0}")]
611 InputStartNotWordAligned(u64),
612 #[error("output size ({0}) cannot be greater than the input size ({1})")]
613 OutputSizeTooBig(usize, usize),
614 #[error("output size must be greater than 0")]
615 OutputSizeIsZero,
616 #[error("uninitialized memory at address {0}")]
617 UninitializedMemoryAddress(u32),
618}
619
620#[derive(Debug)]
625pub struct ErrorContext<'a, N: MastNodeExt>(Option<ErrorContextImpl<'a, N>>);
626
627impl<'a, N: MastNodeExt> ErrorContext<'a, N> {
628 pub fn new(
632 mast_forest: &'a MastForest,
633 node: &'a N,
634 source_manager: Arc<dyn SourceManager>,
635 ) -> Self {
636 Self(Some(ErrorContextImpl::new(mast_forest, node, source_manager)))
637 }
638
639 pub fn new_with_op_idx(
643 mast_forest: &'a MastForest,
644 node: &'a N,
645 source_manager: Arc<dyn SourceManager>,
646 op_idx: usize,
647 ) -> Self {
648 Self(Some(ErrorContextImpl::new_with_op_idx(
649 mast_forest,
650 node,
651 source_manager,
652 op_idx,
653 )))
654 }
655
656 pub fn none() -> Self {
660 Self(None)
661 }
662
663 pub fn label_and_source_file(&self) -> (SourceSpan, Option<Arc<SourceFile>>) {
667 self.0
668 .as_ref()
669 .map_or((SourceSpan::UNKNOWN, None), |ctx| ctx.label_and_source_file())
670 }
671}
672
673impl Default for ErrorContext<'_, BasicBlockNode> {
674 fn default() -> Self {
675 Self::none()
676 }
677}
678
679#[derive(Debug)]
680struct ErrorContextImpl<'a, N: MastNodeExt> {
681 mast_forest: &'a MastForest,
682 node: &'a N,
683 source_manager: Arc<dyn SourceManager>,
684 op_idx: Option<usize>,
685}
686
687impl<'a, N: MastNodeExt> ErrorContextImpl<'a, N> {
688 pub fn new(
689 mast_forest: &'a MastForest,
690 node: &'a N,
691 source_manager: Arc<dyn SourceManager>,
692 ) -> Self {
693 Self {
694 mast_forest,
695 node,
696 source_manager,
697 op_idx: None,
698 }
699 }
700
701 pub fn new_with_op_idx(
702 mast_forest: &'a MastForest,
703 node: &'a N,
704 source_manager: Arc<dyn SourceManager>,
705 op_idx: usize,
706 ) -> Self {
707 Self {
708 mast_forest,
709 node,
710 source_manager,
711 op_idx: Some(op_idx),
712 }
713 }
714
715 pub fn label_and_source_file(&self) -> (SourceSpan, Option<Arc<SourceFile>>) {
716 self.node
717 .get_assembly_op(self.mast_forest, self.op_idx)
718 .and_then(|assembly_op| assembly_op.location())
719 .map_or_else(
720 || (SourceSpan::UNKNOWN, None),
721 |location| {
722 (
723 self.source_manager.location_to_span(location.clone()).unwrap_or_default(),
724 self.source_manager.get_by_path(&location.path),
725 )
726 },
727 )
728 }
729}
730
731#[cfg(test)]
735mod error_assertions {
736 use super::*;
737
738 fn _assert_error_is_send_sync_static<E: core::error::Error + Send + Sync + 'static>(_: E) {}
740
741 fn _assert_execution_error_bounds(err: ExecutionError) {
742 _assert_error_is_send_sync_static(err);
743 }
744}