air_parser/sema/
errors.rs1use miden_diagnostics::{Diagnostic, Label, SourceSpan, Spanned, ToDiagnostic};
2
3use crate::ast::{Identifier, InvalidExprError, InvalidTypeError, ModuleId};
4
5#[derive(Clone, Debug, thiserror::Error)]
7pub enum SemanticAnalysisError {
8 #[error("root module is missing")]
9 MissingRoot,
10 #[error(
11 "root module must contain at both boundary_constraints and integrity_constraints sections"
12 )]
13 MissingConstraints,
14 #[error("root module must contain a public_inputs section")]
15 MissingPublicInputs,
16 #[error("reference to unknown module '{0}'")]
17 MissingModule(ModuleId),
18 #[error("invalid use of restricted section type in library module")]
19 RootSectionInLibrary(SourceSpan),
20 #[error("invalid import of root module")]
21 RootImport(SourceSpan),
22 #[error("name already in use")]
23 NameConflict(SourceSpan),
24 #[error("import refers to undefined item in '{0}'")]
25 ImportUndefined(ModuleId),
26 #[error("cannot import from self")]
27 ImportSelf(SourceSpan),
28 #[error("import conflict")]
29 ImportConflict { item: Identifier, prev: SourceSpan },
30 #[error("import failed")]
31 ImportFailed(SourceSpan),
32 #[error(transparent)]
33 InvalidExpr(#[from] InvalidExprError),
34 #[error(transparent)]
35 InvalidType(#[from] InvalidTypeError),
36 #[error("module is invalid, see diagnostics for details")]
37 Invalid,
38}
39impl Eq for SemanticAnalysisError {}
40impl PartialEq for SemanticAnalysisError {
41 fn eq(&self, other: &Self) -> bool {
42 match (self, other) {
43 (Self::MissingModule(lm), Self::MissingModule(rm)) => lm == rm,
44 (Self::ImportUndefined(lm), Self::ImportUndefined(rm)) => lm == rm,
45 (Self::ImportConflict { item: li, .. }, Self::ImportConflict { item: ri, .. }) => {
46 li == ri
47 }
48 (Self::InvalidExpr(l), Self::InvalidExpr(r)) => l == r,
49 _ => core::mem::discriminant(self) == core::mem::discriminant(other),
50 }
51 }
52}
53impl ToDiagnostic for SemanticAnalysisError {
54 fn to_diagnostic(self) -> Diagnostic {
55 match self {
56 Self::MissingRoot => Diagnostic::error().with_message("no root module found"),
57 Self::MissingConstraints => Diagnostic::error().with_message("root module must contain both boundary_constraints and integrity_constraints sections"),
58 Self::MissingPublicInputs => Diagnostic::error().with_message("root module must contain a public_inputs section"),
59 Self::MissingModule(id) => Diagnostic::error()
60 .with_message("found reference to module which does not exist")
61 .with_labels(vec![Label::primary(id.span().source_id(), id.span()).with_message("this module could not be found")]),
62 Self::RootSectionInLibrary(span) => Diagnostic::error()
63 .with_message("invalid use of restricted section type in library module")
64 .with_labels(vec![Label::primary(span.source_id(), span)
65 .with_message("invalid declaration occurs here")]),
66 Self::RootImport(span) => Diagnostic::error()
67 .with_message("invalid import of root module")
68 .with_labels(vec![Label::primary(span.source_id(), span)
69 .with_message("invalid declaration occurs here")])
70 .with_notes(vec!["The root module may not be imported. Try extracting the items you wish to import into a library module".to_string()]),
71 Self::NameConflict(span) => Diagnostic::error()
72 .with_message("name already in use")
73 .with_labels(vec![Label::primary(span.source_id(), span)
74 .with_message("conflicting definition occurs here")]),
75 Self::ImportUndefined(from) => Diagnostic::error()
76 .with_message("invalid import")
77 .with_labels(vec![Label::primary(from.span().source_id(), from.span())
78 .with_message(format!("no such item in '{from}'"))]),
79 Self::ImportSelf(span) => Diagnostic::error()
80 .with_message("invalid import")
81 .with_labels(vec![Label::primary(span.source_id(), span)
82 .with_message("cannot import a module from within itself")]),
83 Self::ImportConflict { item, prev } => Diagnostic::error()
84 .with_message("conflicting import")
85 .with_labels(vec![Label::primary(item.span().source_id(), item.span())
86 .with_message(format!("the item '{item}' is imported here")),
87 Label::secondary(prev.source_id(), prev)
88 .with_message("but it conflicts with an item of the same name here")]),
89 Self::ImportFailed(span) => Diagnostic::error()
90 .with_message("error occurred while resolving an import")
91 .with_labels(vec![Label::primary(span.source_id(), span)
92 .with_message("failed import occurred here")]),
93 Self::InvalidExpr(err) => err.to_diagnostic(),
94 Self::InvalidType(err) => err.to_diagnostic(),
95 Self::Invalid => Diagnostic::error().with_message("module is invalid, see diagnostics for details"),
96 }
97 }
98}