-
Notifications
You must be signed in to change notification settings - Fork 259
/
Copy patherrors.rs
316 lines (299 loc) · 15.7 KB
/
errors.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
pub use noirc_errors::Span;
use noirc_errors::{CustomDiagnostic as Diagnostic, FileDiagnostic};
use thiserror::Error;
use crate::{parser::ParserError, Ident, Type};
use super::import::PathResolutionError;
#[derive(Error, Debug, Clone, PartialEq, Eq)]
pub enum PubPosition {
#[error("parameter")]
Parameter,
#[error("return type")]
ReturnType,
}
#[derive(Error, Debug, Clone, PartialEq, Eq)]
pub enum ResolverError {
#[error("Duplicate definition")]
DuplicateDefinition { name: String, first_span: Span, second_span: Span },
#[error("Unused variable")]
UnusedVariable { ident: Ident },
#[error("Could not find variable in this scope")]
VariableNotDeclared { name: String, span: Span },
#[error("path is not an identifier")]
PathIsNotIdent { span: Span },
#[error("could not resolve path")]
PathResolutionError(PathResolutionError),
#[error("Expected")]
Expected { span: Span, expected: String, got: String },
#[error("Duplicate field in constructor")]
DuplicateField { field: Ident },
#[error("No such field in struct")]
NoSuchField { field: Ident, struct_definition: Ident },
#[error("Missing fields from struct")]
MissingFields { span: Span, missing_fields: Vec<String>, struct_definition: Ident },
#[error("Unneeded 'mut', pattern is already marked as mutable")]
UnnecessaryMut { first_mut: Span, second_mut: Span },
#[error("Unneeded 'pub', function is not the main method")]
UnnecessaryPub { ident: Ident, position: PubPosition },
#[error("Required 'pub', main function must return public value")]
NecessaryPub { ident: Ident },
#[error("'distinct' keyword can only be used with main method")]
DistinctNotAllowed { ident: Ident },
#[error("Missing expression for declared constant")]
MissingRhsExpr { name: String, span: Span },
#[error("Expression invalid in an array length context")]
InvalidArrayLengthExpr { span: Span },
#[error("Integer too large to be evaluated in an array length context")]
IntegerTooLarge { span: Span },
#[error("No global or generic type parameter found with the given name")]
NoSuchNumericTypeVariable { path: crate::Path },
#[error("Closures cannot capture mutable variables")]
CapturedMutableVariable { span: Span },
#[error("Test functions are not allowed to have any parameters")]
TestFunctionHasParameters { span: Span },
#[error("Only struct types can be used in constructor expressions")]
NonStructUsedInConstructor { typ: Type, span: Span },
#[error("Only struct types can have generics")]
NonStructWithGenerics { span: Span },
#[error("Cannot apply generics on Self type")]
GenericsOnSelfType { span: Span },
#[error("Incorrect amount of arguments to {item_name}")]
IncorrectGenericCount { span: Span, item_name: String, actual: usize, expected: usize },
#[error("{0}")]
ParserError(Box<ParserError>),
#[error("Function is not defined in a contract yet sets its contract visibility")]
ContractFunctionTypeInNormalFunction { span: Span },
#[error("Cannot create a mutable reference to {variable}, it was declared to be immutable")]
MutableReferenceToImmutableVariable { variable: String, span: Span },
#[error("Mutable references to array indices are unsupported")]
MutableReferenceToArrayElement { span: Span },
#[error("Function is not defined in a contract yet sets is_internal")]
ContractFunctionInternalInNormalFunction { span: Span },
#[error("Numeric constants should be printed without formatting braces")]
NumericConstantInFormatString { name: String, span: Span },
#[error("Closure environment must be a tuple or unit type")]
InvalidClosureEnvironment { typ: Type, span: Span },
#[error("{name} is private and not visible from the current module")]
PrivateFunctionCalled { name: String, span: Span },
#[error("{name} is not visible from the current crate")]
NonCrateFunctionCalled { name: String, span: Span },
#[error("Only sized types may be used in the entry point to a program")]
InvalidTypeForEntryPoint { span: Span },
#[error("Nested slices are not supported")]
NestedSlices { span: Span },
}
impl ResolverError {
pub fn into_file_diagnostic(self, file: fm::FileId) -> FileDiagnostic {
Diagnostic::from(self).in_file(file)
}
}
impl From<ResolverError> for Diagnostic {
/// Only user errors can be transformed into a Diagnostic
/// ICEs will make the compiler panic, as they could affect the
/// soundness of the generated program
fn from(error: ResolverError) -> Diagnostic {
match error {
ResolverError::DuplicateDefinition { name, first_span, second_span } => {
let mut diag = Diagnostic::simple_error(
format!("duplicate definitions of {name} found"),
"first definition found here".to_string(),
first_span,
);
diag.add_secondary("second definition found here".to_string(), second_span);
diag
}
ResolverError::UnusedVariable { ident } => {
let name = &ident.0.contents;
Diagnostic::simple_warning(
format!("unused variable {name}"),
"unused variable ".to_string(),
ident.span(),
)
}
ResolverError::VariableNotDeclared { name, span } => Diagnostic::simple_error(
format!("cannot find `{name}` in this scope "),
"not found in this scope".to_string(),
span,
),
ResolverError::PathIsNotIdent { span } => Diagnostic::simple_error(
"cannot use path as an identifier".to_string(),
String::new(),
span,
),
ResolverError::PathResolutionError(error) => error.into(),
ResolverError::Expected { span, expected, got } => Diagnostic::simple_error(
format!("expected {expected} got {got}"),
String::new(),
span,
),
ResolverError::DuplicateField { field } => Diagnostic::simple_error(
format!("duplicate field {field}"),
String::new(),
field.span(),
),
ResolverError::NoSuchField { field, struct_definition } => {
let mut error = Diagnostic::simple_error(
format!("no such field {field} defined in struct {struct_definition}"),
String::new(),
field.span(),
);
error.add_secondary(
format!("{struct_definition} defined here with no {field} field"),
struct_definition.span(),
);
error
}
ResolverError::MissingFields { span, missing_fields, struct_definition } => {
let plural = if missing_fields.len() != 1 { "s" } else { "" };
let missing_fields = missing_fields.join(", ");
let mut error = Diagnostic::simple_error(
format!("missing field{plural}: {missing_fields}"),
String::new(),
span,
);
error.add_secondary(
format!("{struct_definition} defined here"),
struct_definition.span(),
);
error
}
ResolverError::UnnecessaryMut { first_mut, second_mut } => {
let mut error = Diagnostic::simple_error(
"'mut' here is not necessary".to_owned(),
"".to_owned(),
second_mut,
);
error.add_secondary(
"Pattern was already made mutable from this 'mut'".to_owned(),
first_mut,
);
error
}
ResolverError::UnnecessaryPub { ident, position } => {
let name = &ident.0.contents;
let mut diag = Diagnostic::simple_warning(
format!("unnecessary pub keyword on {position} for function {name}"),
format!("unnecessary pub {position}"),
ident.0.span(),
);
diag.add_note("The `pub` keyword only has effects on arguments to the entry-point function of a program. Thus, adding it to other function parameters can be deceiving and should be removed".to_owned());
diag
}
ResolverError::NecessaryPub { ident } => {
let name = &ident.0.contents;
let mut diag = Diagnostic::simple_error(
format!("missing pub keyword on return type of function {name}"),
"missing pub on return type".to_string(),
ident.0.span(),
);
diag.add_note("The `pub` keyword is mandatory for the entry-point function return type because the verifier cannot retrieve private witness and thus the function will not be able to return a 'priv' value".to_owned());
diag
}
ResolverError::DistinctNotAllowed { ident } => {
let name = &ident.0.contents;
let mut diag = Diagnostic::simple_error(
format!("Invalid `distinct` keyword on return type of function {name}"),
"Invalid distinct on return type".to_string(),
ident.0.span(),
);
diag.add_note("The `distinct` keyword is only valid when used on the main function of a program, as its only purpose is to ensure that all witness indices that occur in the abi are unique".to_owned());
diag
}
ResolverError::MissingRhsExpr { name, span } => Diagnostic::simple_error(
format!(
"no expression specifying the value stored by the constant variable {name}"
),
"expected expression to be stored for let statement".to_string(),
span,
),
ResolverError::InvalidArrayLengthExpr { span } => Diagnostic::simple_error(
"Expression invalid in an array-length context".into(),
"Array-length expressions can only have simple integer operations and any variables used must be global constants".into(),
span,
),
ResolverError::IntegerTooLarge { span } => Diagnostic::simple_error(
"Integer too large to be evaluated to an array-length".into(),
"Array-lengths may be a maximum size of usize::MAX, including intermediate calculations".into(),
span,
),
ResolverError::NoSuchNumericTypeVariable { path } => Diagnostic::simple_error(
format!("Cannot find a global or generic type parameter named `{path}`"),
"Only globals or generic type parameters are allowed to be used as an array type's length".to_string(),
path.span(),
),
ResolverError::CapturedMutableVariable { span } => Diagnostic::simple_error(
"Closures cannot capture mutable variables".into(),
"Mutable variable".into(),
span,
),
ResolverError::TestFunctionHasParameters { span } => Diagnostic::simple_error(
"Test functions cannot have any parameters".into(),
"Try removing the parameters or moving the test into a wrapper function".into(),
span,
),
ResolverError::NonStructUsedInConstructor { typ, span } => Diagnostic::simple_error(
"Only struct types can be used in constructor expressions".into(),
format!("{typ} has no fields to construct it with"),
span,
),
ResolverError::NonStructWithGenerics { span } => Diagnostic::simple_error(
"Only struct types can have generic arguments".into(),
"Try removing the generic arguments".into(),
span,
),
ResolverError::GenericsOnSelfType { span } => Diagnostic::simple_error(
"Cannot apply generics to Self type".into(),
"Use an explicit type name or apply the generics at the start of the impl instead".into(),
span,
),
ResolverError::IncorrectGenericCount { span, item_name, actual, expected } => {
let expected_plural = if expected == 1 { "" } else { "s" };
let actual_plural = if actual == 1 { "is" } else { "are" };
Diagnostic::simple_error(
format!("`{item_name}` has {expected} generic argument{expected_plural} but {actual} {actual_plural} given here"),
"Incorrect number of generic arguments".into(),
span,
)
}
ResolverError::ParserError(error) => (*error).into(),
ResolverError::ContractFunctionTypeInNormalFunction { span } => Diagnostic::simple_error(
"Only functions defined within contracts can set their contract function type".into(),
"Non-contract functions cannot be 'open'".into(),
span,
),
ResolverError::MutableReferenceToImmutableVariable { variable, span } => {
Diagnostic::simple_error(format!("Cannot mutably reference the immutable variable {variable}"), format!("{variable} is immutable"), span)
},
ResolverError::MutableReferenceToArrayElement { span } => {
Diagnostic::simple_error("Mutable references to array elements are currently unsupported".into(), "Try storing the element in a fresh variable first".into(), span)
},
ResolverError::ContractFunctionInternalInNormalFunction { span } => Diagnostic::simple_error(
"Only functions defined within contracts can set their functions to be internal".into(),
"Non-contract functions cannot be 'internal'".into(),
span,
),
ResolverError::NumericConstantInFormatString { name, span } => Diagnostic::simple_error(
format!("cannot find `{name}` in this scope "),
"Numeric constants should be printed without formatting braces".to_string(),
span,
),
ResolverError::InvalidClosureEnvironment { span, typ } => Diagnostic::simple_error(
format!("{typ} is not a valid closure environment type"),
"Closure environment must be a tuple or unit type".to_string(), span),
// This will be upgraded to an error in future versions
ResolverError::PrivateFunctionCalled { span, name } => Diagnostic::simple_warning(
format!("{name} is private and not visible from the current module"),
format!("{name} is private"), span),
ResolverError::NonCrateFunctionCalled { span, name } => Diagnostic::simple_warning(
format!("{name} is not visible from the current crate"),
format!("{name} is only visible within its crate"), span),
ResolverError::InvalidTypeForEntryPoint { span } => Diagnostic::simple_error(
"Only sized types may be used in the entry point to a program".to_string(),
"Slices, references, or any type containing them may not be used in main or a contract function".to_string(), span),
ResolverError::NestedSlices { span } => Diagnostic::simple_error(
"Nested slices are not supported".into(),
"Try to use a constant sized array instead".into(),
span,
),
}
}
}