1use crate::convert_parse_tree_error::{
2 get_attribute_type, get_expected_attributes_args_multiplicity_msg, AttributeType,
3 ConvertParseTreeError,
4};
5use crate::diagnostic::{Code, Diagnostic, Hint, Issue, Reason, ToDiagnostic};
6use crate::formatting::*;
7use crate::lex_error::LexError;
8use crate::parser_error::{ParseError, ParseErrorKind};
9use crate::type_error::TypeError;
10
11use core::fmt;
12use std::fmt::Formatter;
13use sway_types::style::to_snake_case;
14use sway_types::{BaseIdent, Ident, IdentUnique, SourceEngine, Span, Spanned};
15use thiserror::Error;
16
17use self::ShadowingSource::*;
18use self::StructFieldUsageContext::*;
19
20#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
21pub enum InterfaceName {
22 Abi(Ident),
23 Trait(Ident),
24}
25
26impl fmt::Display for InterfaceName {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 match self {
29 InterfaceName::Abi(name) => write!(f, "ABI \"{name}\""),
30 InterfaceName::Trait(name) => write!(f, "trait \"{name}\""),
31 }
32 }
33}
34
35#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
54pub enum CompileError {
55 #[error("\"const generics\" are not supported here.")]
56 ConstGenericNotSupportedHere { span: Span },
57 #[error("This expression is not supported as lengths.")]
58 LengthExpressionNotSupported { span: Span },
59 #[error(
60 "This needs \"{feature}\" to be enabled, but it is currently disabled. For more details go to {url}."
61 )]
62 FeatureIsDisabled {
63 feature: String,
64 url: String,
65 span: Span,
66 },
67 #[error(
68 "There was an error while evaluating the evaluation order for the module dependency graph."
69 )]
70 ModuleDepGraphEvaluationError {},
71 #[error("A cyclic reference was found between the modules: {}.",
72 modules.iter().map(|ident| ident.as_str().to_string())
73 .collect::<Vec<_>>()
74 .join(", "))]
75 ModuleDepGraphCyclicReference { modules: Vec<BaseIdent> },
76
77 #[error("Variable \"{var_name}\" does not exist in this scope.")]
78 UnknownVariable { var_name: Ident, span: Span },
79 #[error("Identifier \"{name}\" was used as a variable, but it is actually a {what_it_is}.")]
80 NotAVariable {
81 name: Ident,
82 what_it_is: &'static str,
83 span: Span,
84 },
85 #[error("{feature} is currently not implemented.")]
86 Unimplemented {
87 feature: String,
92 help: Vec<String>,
96 span: Span,
97 },
98 #[error("{0}")]
99 TypeError(TypeError),
100 #[error("Error parsing input: {err:?}")]
101 ParseError { span: Span, err: String },
102 #[error(
103 "Internal compiler error: {0}\nPlease file an issue on the repository and include the \
104 code that triggered this error."
105 )]
106 Internal(&'static str, Span),
107 #[error(
108 "Internal compiler error: {0}\nPlease file an issue on the repository and include the \
109 code that triggered this error."
110 )]
111 InternalOwned(String, Span),
112 #[error(
113 "Predicate declaration contains no main function. Predicates require a main function."
114 )]
115 NoPredicateMainFunction(Span),
116 #[error("A predicate's main function must return a boolean.")]
117 PredicateMainDoesNotReturnBool(Span),
118 #[error("Script declaration contains no main function. Scripts require a main function.")]
119 NoScriptMainFunction(Span),
120 #[error("Fallback function already defined in scope.")]
121 MultipleDefinitionsOfFallbackFunction { name: Ident, span: Span },
122 #[error("Function \"{name}\" was already defined in scope.")]
123 MultipleDefinitionsOfFunction { name: Ident, span: Span },
124 #[error("Name \"{name}\" is defined multiple times.")]
125 MultipleDefinitionsOfName { name: Ident, span: Span },
126 #[error("Constant \"{name}\" was already defined in scope.")]
127 MultipleDefinitionsOfConstant { name: Ident, span: Span },
128 #[error("Type \"{name}\" was already defined in scope.")]
129 MultipleDefinitionsOfType { name: Ident, span: Span },
130 #[error("Variable \"{}\" is already defined in match arm.", first_definition.as_str())]
131 MultipleDefinitionsOfMatchArmVariable {
132 match_value: Span,
133 match_type: String,
134 first_definition: Span,
135 first_definition_is_struct_field: bool,
136 duplicate: Span,
137 duplicate_is_struct_field: bool,
138 },
139 #[error(
140 "Assignment to an immutable variable. Variable \"{decl_name} is not declared as mutable."
141 )]
142 AssignmentToNonMutableVariable {
143 decl_name: Ident,
145 lhs_span: Span,
147 },
148 #[error(
149 "Assignment to a {}. {} cannot be assigned to.",
150 if *is_configurable {
151 "configurable"
152 } else {
153 "constant"
154 },
155 if *is_configurable {
156 "Configurables"
157 } else {
158 "Constants"
159 }
160 )]
161 AssignmentToConstantOrConfigurable {
162 decl_name: Ident,
164 is_configurable: bool,
165 lhs_span: Span,
167 },
168 #[error(
169 "This assignment target cannot be assigned to, because {} is {}{decl_friendly_type_name} and not a mutable variable.",
170 if let Some(decl_name) = decl_name {
171 format!("\"{decl_name}\"")
172 } else {
173 "this".to_string()
174 },
175 a_or_an(decl_friendly_type_name)
176 )]
177 DeclAssignmentTargetCannotBeAssignedTo {
178 decl_name: Option<Ident>,
180 decl_friendly_type_name: &'static str,
182 lhs_span: Span,
184 },
185 #[error("This reference is not a reference to a mutable value (`&mut`).")]
186 AssignmentViaNonMutableReference {
187 decl_reference_name: Option<Ident>,
192 decl_reference_rhs: Option<Span>,
195 decl_reference_type: String,
198 span: Span,
199 },
200 #[error(
201 "Cannot call method \"{method_name}\" on variable \"{variable_name}\" because \
202 \"{variable_name}\" is not declared as mutable."
203 )]
204 MethodRequiresMutableSelf {
205 method_name: Ident,
206 variable_name: Ident,
207 span: Span,
208 },
209 #[error(
210 "This parameter was declared as mutable, which is not supported yet, did you mean to use ref mut?"
211 )]
212 MutableParameterNotSupported { param_name: Ident, span: Span },
213 #[error("Cannot pass immutable argument to mutable parameter.")]
214 ImmutableArgumentToMutableParameter { span: Span },
215 #[error("ref mut or mut parameter is not allowed for contract ABI function.")]
216 RefMutableNotAllowedInContractAbi { param_name: Ident, span: Span },
217 #[error("Reference to a mutable value cannot reference a constant.")]
218 RefMutCannotReferenceConstant {
219 constant: String,
224 span: Span,
225 },
226 #[error("Reference to a mutable value cannot reference an immutable variable.")]
227 RefMutCannotReferenceImmutableVariable {
228 decl_name: Ident,
230 span: Span,
231 },
232 #[error(
233 "Cannot call associated function \"{fn_name}\" as a method. Use associated function \
234 syntax instead."
235 )]
236 AssociatedFunctionCalledAsMethod { fn_name: Ident, span: Span },
237 #[error(
238 "Generic type \"{name}\" is not in scope. Perhaps you meant to specify type parameters in \
239 the function signature? For example: \n`fn \
240 {fn_name}<{comma_separated_generic_params}>({args}) -> ... `"
241 )]
242 TypeParameterNotInTypeScope {
243 name: Ident,
244 span: Span,
245 comma_separated_generic_params: String,
246 fn_name: Ident,
247 args: String,
248 },
249 #[error(
250 "expected: {expected} \n\
251 found: {given} \n\
252 help: The definition of this {decl_type} must \
253 match the one in the {interface_name} declaration."
254 )]
255 MismatchedTypeInInterfaceSurface {
256 interface_name: InterfaceName,
257 span: Span,
258 decl_type: String,
259 given: String,
260 expected: String,
261 },
262 #[error("Trait \"{name}\" cannot be found in the current scope.")]
263 UnknownTrait { span: Span, name: Ident },
264 #[error("Function \"{name}\" is not a part of {interface_name}'s interface surface.")]
265 FunctionNotAPartOfInterfaceSurface {
266 name: Ident,
267 interface_name: InterfaceName,
268 span: Span,
269 },
270 #[error("Constant \"{name}\" is not a part of {interface_name}'s interface surface.")]
271 ConstantNotAPartOfInterfaceSurface {
272 name: Ident,
273 interface_name: InterfaceName,
274 span: Span,
275 },
276 #[error("Type \"{name}\" is not a part of {interface_name}'s interface surface.")]
277 TypeNotAPartOfInterfaceSurface {
278 name: Ident,
279 interface_name: InterfaceName,
280 span: Span,
281 },
282 #[error("Constants are missing from this trait implementation: {}",
283 missing_constants.iter().map(|ident| ident.as_str().to_string())
284 .collect::<Vec<_>>()
285 .join("\n"))]
286 MissingInterfaceSurfaceConstants {
287 missing_constants: Vec<BaseIdent>,
288 span: Span,
289 },
290 #[error("Associated types are missing from this trait implementation: {}",
291 missing_types.iter().map(|ident| ident.as_str().to_string())
292 .collect::<Vec<_>>()
293 .join("\n"))]
294 MissingInterfaceSurfaceTypes {
295 missing_types: Vec<BaseIdent>,
296 span: Span,
297 },
298 #[error("Functions are missing from this trait implementation: {}",
299 missing_functions.iter().map(|ident| ident.as_str().to_string())
300 .collect::<Vec<_>>()
301 .join("\n"))]
302 MissingInterfaceSurfaceMethods {
303 missing_functions: Vec<BaseIdent>,
304 span: Span,
305 },
306 #[error("Expected {} type {} for \"{name}\", but instead found {}.", expected, if *expected == 1usize { "argument" } else { "arguments" }, given)]
307 IncorrectNumberOfTypeArguments {
308 name: Ident,
309 given: usize,
310 expected: usize,
311 span: Span,
312 },
313 #[error("\"{name}\" does not take type arguments.")]
314 DoesNotTakeTypeArguments { name: Ident, span: Span },
315 #[error("\"{name}\" does not take type arguments as prefix.")]
316 DoesNotTakeTypeArgumentsAsPrefix { name: Ident, span: Span },
317 #[error("Type arguments are not allowed for this type.")]
318 TypeArgumentsNotAllowed { span: Span },
319 #[error("\"{name}\" needs type arguments.")]
320 NeedsTypeArguments { name: Ident, span: Span },
321 #[error(
322 "Enum with name \"{name}\" could not be found in this scope. Perhaps you need to import \
323 it?"
324 )]
325 EnumNotFound { name: Ident, span: Span },
326 #[error("Instantiation of the struct \"{struct_name}\" is missing field \"{field_name}\".")]
331 StructInstantiationMissingFieldForErrorRecovery {
332 field_name: Ident,
333 struct_name: Ident,
335 span: Span,
336 },
337 #[error("Instantiation of the struct \"{struct_name}\" is missing {} {}.",
338 if field_names.len() == 1 { "field" } else { "fields" },
339 field_names.iter().map(|name| format!("\"{name}\"")).collect::<Vec::<_>>().join(", "))]
340 StructInstantiationMissingFields {
341 field_names: Vec<Ident>,
342 struct_name: Ident,
344 span: Span,
345 struct_decl_span: Span,
346 total_number_of_fields: usize,
347 },
348 #[error("Struct \"{struct_name}\" cannot be instantiated here because it has private fields.")]
349 StructCannotBeInstantiated {
350 struct_name: Ident,
352 span: Span,
353 struct_decl_span: Span,
354 private_fields: Vec<Ident>,
355 constructors: Vec<String>,
359 all_fields_are_private: bool,
361 is_in_storage_declaration: bool,
362 struct_can_be_changed: bool,
363 },
364 #[error("Field \"{field_name}\" of the struct \"{struct_name}\" is private.")]
365 StructFieldIsPrivate {
366 field_name: IdentUnique,
367 struct_name: Ident,
369 field_decl_span: Span,
370 struct_can_be_changed: bool,
371 usage_context: StructFieldUsageContext,
372 },
373 #[error("Field \"{field_name}\" does not exist in struct \"{struct_name}\".")]
374 StructFieldDoesNotExist {
375 field_name: IdentUnique,
376 available_fields: Vec<Ident>,
378 is_public_struct_access: bool,
379 struct_name: Ident,
381 struct_decl_span: Span,
382 struct_is_empty: bool,
383 usage_context: StructFieldUsageContext,
384 },
385 #[error("Field \"{field_name}\" has multiple definitions.")]
386 StructFieldDuplicated { field_name: Ident, duplicate: Ident },
387 #[error("No method \"{method}\" found for type \"{type_name}\".{}",
388 if matching_method_strings.is_empty() {
389 "".to_string()
390 } else {
391 format!(" \nMatching method{}:\n{}", if matching_method_strings.len()> 1 {"s"} else {""},
392 matching_method_strings.iter().map(|m| format!(" {m}")).collect::<Vec<_>>().join("\n"))
393 }
394 )]
395 MethodNotFound {
396 method: String,
397 type_name: String,
398 matching_method_strings: Vec<String>,
399 span: Span,
400 },
401 #[error("Module \"{name}\" could not be found.")]
402 ModuleNotFound { span: Span, name: String },
403 #[error("This expression has type \"{actually}\", which is not a struct. Fields can only be accessed on structs.")]
404 FieldAccessOnNonStruct {
405 actually: String,
406 storage_variable: Option<String>,
409 field_name: IdentUnique,
411 span: Span,
412 },
413 #[error("This expression has type \"{actually}\", which is not a tuple. Elements can only be accessed on tuples.")]
414 TupleElementAccessOnNonTuple {
415 actually: String,
416 span: Span,
417 index: usize,
418 index_span: Span,
419 },
420 #[error("This expression has type \"{actually}\", which is not an indexable type.")]
421 NotIndexable { actually: String, span: Span },
422 #[error("\"{name}\" is a {actually}, not an enum.")]
423 NotAnEnum {
424 name: String,
425 span: Span,
426 actually: String,
427 },
428 #[error("This is a {actually}, not a struct.")]
429 NotAStruct { span: Span, actually: String },
430 #[error("This is a {actually}, not an enum.")]
431 DeclIsNotAnEnum { actually: String, span: Span },
432 #[error("This is a {actually}, not a struct.")]
433 DeclIsNotAStruct { actually: String, span: Span },
434 #[error("This is a {actually}, not a function.")]
435 DeclIsNotAFunction { actually: String, span: Span },
436 #[error("This is a {actually}, not a variable.")]
437 DeclIsNotAVariable { actually: String, span: Span },
438 #[error("This is a {actually}, not an ABI.")]
439 DeclIsNotAnAbi { actually: String, span: Span },
440 #[error("This is a {actually}, not a trait.")]
441 DeclIsNotATrait { actually: String, span: Span },
442 #[error("This is a {actually}, not an impl block.")]
443 DeclIsNotAnImplTrait { actually: String, span: Span },
444 #[error("This is a {actually}, not a trait function.")]
445 DeclIsNotATraitFn { actually: String, span: Span },
446 #[error("This is a {actually}, not storage.")]
447 DeclIsNotStorage { actually: String, span: Span },
448 #[error("This is a {actually}, not a constant")]
449 DeclIsNotAConstant { actually: String, span: Span },
450 #[error("This is a {actually}, not a type alias")]
451 DeclIsNotATypeAlias { actually: String, span: Span },
452 #[error("Could not find symbol \"{name}\" in this scope.")]
453 SymbolNotFound { name: Ident, span: Span },
454 #[error("Found multiple bindings for \"{name}\" in this scope.")]
455 SymbolWithMultipleBindings {
456 name: Ident,
457 paths: Vec<String>,
458 span: Span,
459 },
460 #[error("Symbol \"{name}\" is private.")]
461 ImportPrivateSymbol { name: Ident, span: Span },
462 #[error("Module \"{name}\" is private.")]
463 ImportPrivateModule { name: Ident, span: Span },
464 #[error(
465 "Because this if expression's value is used, an \"else\" branch is required and it must \
466 return type \"{r#type}\""
467 )]
468 NoElseBranch { span: Span, r#type: String },
469 #[error(
470 "Symbol \"{name}\" does not refer to a type, it refers to a {actually_is}. It cannot be \
471 used in this position."
472 )]
473 NotAType {
474 span: Span,
475 name: String,
476 actually_is: &'static str,
477 },
478 #[error(
479 "This enum variant requires an instantiation expression. Try initializing it with \
480 arguments in parentheses."
481 )]
482 MissingEnumInstantiator { span: Span },
483 #[error(
484 "This path must return a value of type \"{ty}\" from function \"{function_name}\", but it \
485 does not."
486 )]
487 PathDoesNotReturn {
488 span: Span,
489 ty: String,
490 function_name: Ident,
491 },
492 #[error(
493 "This register was not initialized in the initialization section of the ASM expression. \
494 Initialized registers are: {initialized_registers}"
495 )]
496 UnknownRegister {
497 span: Span,
498 initialized_registers: String,
499 },
500 #[error("This opcode takes an immediate value but none was provided.")]
501 MissingImmediate { span: Span },
502 #[error("This immediate value is invalid.")]
503 InvalidImmediateValue { span: Span },
504 #[error("Variant \"{variant_name}\" does not exist on enum \"{enum_name}\"")]
505 UnknownEnumVariant {
506 enum_name: Ident,
507 variant_name: Ident,
508 span: Span,
509 },
510 #[error("Unknown opcode: \"{op_name}\".")]
511 UnrecognizedOp { op_name: Ident, span: Span },
512 #[error("Cannot infer type for type parameter \"{ty}\". Insufficient type information provided. Try annotating its type.")]
513 UnableToInferGeneric { ty: String, span: Span },
514 #[error("The generic type parameter \"{ty}\" is unconstrained.")]
515 UnconstrainedGenericParameter { ty: String, span: Span },
516 #[error("Trait \"{trait_name}\" is not implemented for type \"{ty}\".")]
517 TraitConstraintNotSatisfied {
518 type_id: usize, ty: String,
520 trait_name: String,
521 span: Span,
522 },
523 #[error(
524 "Expects trait constraint \"{param}: {trait_name}\" which is missing from type parameter \"{param}\"."
525 )]
526 TraitConstraintMissing {
527 param: String,
528 trait_name: String,
529 span: Span,
530 },
531 #[error("The value \"{val}\" is too large to fit in this 6-bit immediate spot.")]
532 Immediate06TooLarge { val: u64, span: Span },
533 #[error("The value \"{val}\" is too large to fit in this 12-bit immediate spot.")]
534 Immediate12TooLarge { val: u64, span: Span },
535 #[error("The value \"{val}\" is too large to fit in this 18-bit immediate spot.")]
536 Immediate18TooLarge { val: u64, span: Span },
537 #[error("The value \"{val}\" is too large to fit in this 24-bit immediate spot.")]
538 Immediate24TooLarge { val: u64, span: Span },
539 #[error(
540 "This op expects {expected} register(s) as arguments, but you provided {received} register(s)."
541 )]
542 IncorrectNumberOfAsmRegisters {
543 span: Span,
544 expected: usize,
545 received: usize,
546 },
547 #[error("This op does not take an immediate value.")]
548 UnnecessaryImmediate { span: Span },
549 #[error("This reference is ambiguous, and could refer to a module, enum, or function of the same name. Try qualifying the name with a path.")]
550 AmbiguousPath { span: Span },
551 #[error("This is a module path, and not an expression.")]
552 ModulePathIsNotAnExpression { module_path: String, span: Span },
553 #[error("Unknown type name.")]
554 UnknownType { span: Span },
555 #[error("Unknown type name \"{name}\".")]
556 UnknownTypeName { name: String, span: Span },
557 #[error("The file {file_path} could not be read: {stringified_error}")]
558 FileCouldNotBeRead {
559 span: Span,
560 file_path: String,
561 stringified_error: String,
562 },
563 #[error("This imported file must be a library. It must start with \"library;\"")]
564 ImportMustBeLibrary { span: Span },
565 #[error("An enum instantiaton cannot contain more than one value. This should be a single value of type {ty}.")]
566 MoreThanOneEnumInstantiator { span: Span, ty: String },
567 #[error("This enum variant represents the unit type, so it should not be instantiated with any value.")]
568 UnnecessaryEnumInstantiator { span: Span },
569 #[error("The enum variant `{ty}` is of type `unit`, so its constructor does not take arguments or parentheses. Try removing the ().")]
570 UnitVariantWithParenthesesEnumInstantiator { span: Span, ty: String },
571 #[error("Cannot find trait \"{name}\" in this scope.")]
572 TraitNotFound { name: String, span: Span },
573 #[error("Trait \"{trait_name}\" is not imported when calling \"{function_name}\".\nThe import is needed because \"{function_name}\" uses \"{trait_name}\" in one of its trait constraints.")]
574 TraitNotImportedAtFunctionApplication {
575 trait_name: String,
576 function_name: String,
577 function_call_site_span: Span,
578 trait_constraint_span: Span,
579 trait_candidates: Vec<String>,
580 },
581 #[error("This expression is not valid on the left hand side of a reassignment.")]
582 InvalidExpressionOnLhs { span: Span },
583 #[error("This code cannot be evaluated to a constant")]
584 CannotBeEvaluatedToConst { span: Span },
585 #[error(
586 "This code cannot be evaluated to a configurable because its size is not always limited."
587 )]
588 CannotBeEvaluatedToConfigurableSizeUnknown { span: Span },
589 #[error("{} \"{method_name}\" expects {expected} {} but you provided {received}.",
590 if *dot_syntax_used { "Method" } else { "Function" },
591 if *expected == 1usize { "argument" } else {"arguments"},
592 )]
593 TooManyArgumentsForFunction {
594 span: Span,
595 method_name: Ident,
596 dot_syntax_used: bool,
597 expected: usize,
598 received: usize,
599 },
600 #[error("{} \"{method_name}\" expects {expected} {} but you provided {received}.",
601 if *dot_syntax_used { "Method" } else { "Function" },
602 if *expected == 1usize { "argument" } else {"arguments"},
603 )]
604 TooFewArgumentsForFunction {
605 span: Span,
606 method_name: Ident,
607 dot_syntax_used: bool,
608 expected: usize,
609 received: usize,
610 },
611 #[error("The function \"{method_name}\" was called without parentheses. Try adding ().")]
612 MissingParenthesesForFunction { span: Span, method_name: Ident },
613 #[error("This type is invalid in a function selector. A contract ABI function selector must be a known sized type, not generic.")]
614 InvalidAbiType { span: Span },
615 #[error("This is a {actually_is}, not an ABI. An ABI cast requires a valid ABI to cast the address to.")]
616 NotAnAbi {
617 span: Span,
618 actually_is: &'static str,
619 },
620 #[error("An ABI can only be implemented for the `Contract` type, so this implementation of an ABI for type \"{ty}\" is invalid.")]
621 ImplAbiForNonContract { span: Span, ty: String },
622 #[error("Conflicting implementations of trait \"{trait_name}\" for type \"{type_implementing_for}\".")]
623 ConflictingImplsForTraitAndType {
624 trait_name: String,
625 type_implementing_for: String,
626 type_implementing_for_unaliased: String,
627 existing_impl_span: Span,
628 second_impl_span: Span,
629 },
630 #[error(
631 "\"{marker_trait_full_name}\" is a marker trait and cannot be explicitly implemented."
632 )]
633 MarkerTraitExplicitlyImplemented {
634 marker_trait_full_name: String,
635 span: Span,
636 },
637 #[error("Duplicate definitions for the {decl_kind} \"{decl_name}\" for type \"{type_implementing_for}\".")]
638 DuplicateDeclDefinedForType {
639 decl_kind: String,
640 decl_name: String,
641 type_implementing_for: String,
642 type_implementing_for_unaliased: String,
643 existing_impl_span: Span,
644 second_impl_span: Span,
645 },
646 #[error("The function \"{fn_name}\" in {interface_name} is defined with {num_parameters} parameters, but the provided implementation has {provided_parameters} parameters.")]
647 IncorrectNumberOfInterfaceSurfaceFunctionParameters {
648 fn_name: Ident,
649 interface_name: InterfaceName,
650 num_parameters: usize,
651 provided_parameters: usize,
652 span: Span,
653 },
654 #[error("This parameter was declared as type {should_be}, but argument of type {provided} was provided.")]
655 ArgumentParameterTypeMismatch {
656 span: Span,
657 should_be: String,
658 provided: String,
659 },
660 #[error("Function {fn_name} is recursive, which is unsupported at this time.")]
661 RecursiveCall { fn_name: Ident, span: Span },
662 #[error(
663 "Function {fn_name} is recursive via {call_chain}, which is unsupported at this time."
664 )]
665 RecursiveCallChain {
666 fn_name: Ident,
667 call_chain: String, span: Span,
669 },
670 #[error("Type {name} is recursive, which is unsupported at this time.")]
671 RecursiveType { name: Ident, span: Span },
672 #[error("Type {name} is recursive via {type_chain}, which is unsupported at this time.")]
673 RecursiveTypeChain {
674 name: Ident,
675 type_chain: String, span: Span,
677 },
678 #[error("The GM (get-metadata) opcode, when called from an external context, will cause the VM to panic.")]
679 GMFromExternalContext { span: Span },
680 #[error("The MINT opcode cannot be used in an external context.")]
681 MintFromExternalContext { span: Span },
682 #[error("The BURN opcode cannot be used in an external context.")]
683 BurnFromExternalContext { span: Span },
684 #[error("Contract storage cannot be used in an external context.")]
685 ContractStorageFromExternalContext { span: Span },
686 #[error("The {opcode} opcode cannot be used in a predicate.")]
687 InvalidOpcodeFromPredicate { opcode: String, span: Span },
688 #[error("Index out of bounds; the length is {count} but the index is {index}.")]
689 ArrayOutOfBounds { index: u64, count: u64, span: Span },
690 #[error(
691 "Invalid range; the range end at index {end} is smaller than its start at index {start}"
692 )]
693 InvalidRangeEndGreaterThanStart { start: u64, end: u64, span: Span },
694 #[error("Tuple index {index} is out of bounds. The tuple has {count} element{}.", plural_s(*count))]
695 TupleIndexOutOfBounds {
696 index: usize,
697 count: usize,
698 tuple_type: String,
699 span: Span,
700 prefix_span: Span,
701 },
702 #[error("Constant requires expression.")]
703 ConstantRequiresExpression { span: Span },
704 #[error("Constants cannot be shadowed. {shadowing_source} \"{name}\" shadows constant of the same name.")]
705 ConstantsCannotBeShadowed {
706 shadowing_source: ShadowingSource,
714 name: IdentUnique,
715 constant_span: Span,
716 constant_decl_span: Span,
717 is_alias: bool,
718 },
719 #[error("Configurables cannot be shadowed. {shadowing_source} \"{name}\" shadows configurable of the same name.")]
720 ConfigurablesCannotBeShadowed {
721 shadowing_source: ShadowingSource,
731 name: IdentUnique,
732 configurable_span: Span,
733 },
734 #[error("Configurables cannot be matched against. Configurable \"{name}\" cannot be used in pattern matching.")]
735 ConfigurablesCannotBeMatchedAgainst {
736 name: IdentUnique,
737 configurable_span: Span,
738 },
739 #[error(
740 "Constants cannot shadow variables. Constant \"{name}\" shadows variable of the same name."
741 )]
742 ConstantShadowsVariable {
743 name: IdentUnique,
744 variable_span: Span,
745 },
746 #[error("{existing_constant_or_configurable} of the name \"{name}\" already exists.")]
747 ConstantDuplicatesConstantOrConfigurable {
748 existing_constant_or_configurable: &'static str,
750 new_constant_or_configurable: &'static str,
752 name: IdentUnique,
753 existing_span: Span,
754 },
755 #[error("Imported symbol \"{name}\" shadows another symbol of the same name.")]
756 ShadowsOtherSymbol { name: IdentUnique },
757 #[error("The name \"{name}\" is already used for a generic parameter in this scope.")]
758 GenericShadowsGeneric { name: IdentUnique },
759 #[error("Non-exhaustive match expression. Missing patterns {missing_patterns}")]
760 MatchExpressionNonExhaustive {
761 missing_patterns: String,
762 span: Span,
763 },
764 #[error("Struct pattern is missing the {}field{} {}.",
765 if *missing_fields_are_public { "public " } else { "" },
766 plural_s(missing_fields.len()),
767 sequence_to_str(missing_fields, Enclosing::DoubleQuote, 2)
768 )]
769 MatchStructPatternMissingFields {
770 missing_fields: Vec<Ident>,
771 missing_fields_are_public: bool,
772 struct_name: Ident,
774 struct_decl_span: Span,
775 total_number_of_fields: usize,
776 span: Span,
777 },
778 #[error("Struct pattern must ignore inaccessible private field{} {}.",
779 plural_s(private_fields.len()),
780 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2))]
781 MatchStructPatternMustIgnorePrivateFields {
782 private_fields: Vec<Ident>,
783 struct_name: Ident,
785 struct_decl_span: Span,
786 all_fields_are_private: bool,
787 span: Span,
788 },
789 #[error("Variable \"{variable}\" is not defined in all alternatives.")]
790 MatchArmVariableNotDefinedInAllAlternatives {
791 match_value: Span,
792 match_type: String,
793 variable: Ident,
794 missing_in_alternatives: Vec<Span>,
795 },
796 #[error(
797 "Variable \"{variable}\" is expected to be of type \"{expected}\", but is \"{received}\"."
798 )]
799 MatchArmVariableMismatchedType {
800 match_value: Span,
801 match_type: String,
802 variable: Ident,
803 first_definition: Span,
804 expected: String,
805 received: String,
806 },
807 #[error("This cannot be matched.")]
808 MatchedValueIsNotValid {
809 supported_types_message: Vec<&'static str>,
812 span: Span,
813 },
814 #[error(
815 "The function \"{fn_name}\" in {interface_name} is pure, but this \
816 implementation is not. The \"storage\" annotation must be \
817 removed, or the trait declaration must be changed to \
818 \"#[storage({attrs})]\"."
819 )]
820 TraitDeclPureImplImpure {
821 fn_name: Ident,
822 interface_name: InterfaceName,
823 attrs: String,
824 span: Span,
825 },
826 #[error(
827 "Storage attribute access mismatch. The function \"{fn_name}\" in \
828 {interface_name} requires the storage attribute(s) #[storage({attrs})]."
829 )]
830 TraitImplPurityMismatch {
831 fn_name: Ident,
832 interface_name: InterfaceName,
833 attrs: String,
834 span: Span,
835 },
836 #[error("Impure function inside of non-contract. Contract storage is only accessible from contracts.")]
837 ImpureInNonContract { span: Span },
838 #[error(
839 "This function performs storage access but does not have the required storage \
840 attribute(s). Try adding \"#[storage({suggested_attributes})]\" to the function \
841 declaration."
842 )]
843 StorageAccessMismatched {
844 is_pure: bool,
846 storage_access_violations: Vec<(Span, StorageAccess)>,
847 suggested_attributes: String,
848 span: Span,
851 },
852 #[error(
853 "Parameter reference type or mutability mismatch between the trait function declaration and its implementation."
854 )]
855 ParameterRefMutabilityMismatch { span: Span },
856 #[error("Literal value is too large for type {ty}.")]
857 IntegerTooLarge { span: Span, ty: String },
858 #[error("Literal value underflows type {ty}.")]
859 IntegerTooSmall { span: Span, ty: String },
860 #[error("Literal value contains digits which are not valid for type {ty}.")]
861 IntegerContainsInvalidDigit { span: Span, ty: String },
862 #[error("A trait cannot be a subtrait of an ABI.")]
863 AbiAsSupertrait { span: Span },
864 #[error(
865 "Implementation of trait \"{supertrait_name}\" is required by this bound in \"{trait_name}\""
866 )]
867 SupertraitImplRequired {
868 supertrait_name: String,
869 trait_name: Ident,
870 span: Span,
871 },
872 #[error(
873 "Contract ABI method parameter \"{param_name}\" is set multiple times for this contract ABI method call"
874 )]
875 ContractCallParamRepeated { param_name: String, span: Span },
876 #[error(
877 "Unrecognized contract ABI method parameter \"{param_name}\". The only available parameters are \"gas\", \"coins\", and \"asset_id\""
878 )]
879 UnrecognizedContractParam { param_name: String, span: Span },
880 #[error("Attempting to specify a contract method parameter for a non-contract function call")]
881 CallParamForNonContractCallMethod { span: Span },
882 #[error("Storage field \"{field_name}\" does not exist.")]
883 StorageFieldDoesNotExist {
884 field_name: IdentUnique,
885 available_fields: Vec<(Vec<Ident>, Ident)>,
886 storage_decl_span: Span,
887 },
888 #[error("No storage has been declared")]
889 NoDeclaredStorage { span: Span },
890 #[error("Multiple storage declarations were found")]
891 MultipleStorageDeclarations { span: Span },
892 #[error("Type {ty} can only be declared directly as a storage field")]
893 InvalidStorageOnlyTypeDecl { ty: String, span: Span },
894 #[error(
895 "Internal compiler error: Unexpected {decl_type} declaration found.\n\
896 Please file an issue on the repository and include the code that triggered this error."
897 )]
898 UnexpectedDeclaration { decl_type: &'static str, span: Span },
899 #[error("This contract caller has no known address. Try instantiating a contract caller with a known contract address instead.")]
900 ContractAddressMustBeKnown { span: Span },
901 #[error("{}", error)]
902 ConvertParseTree {
903 #[from]
904 error: ConvertParseTreeError,
905 },
906 #[error("{}", error)]
907 Lex { error: LexError },
908 #[error("{}", error)]
909 Parse { error: ParseError },
910 #[error("Could not evaluate initializer to a const declaration.")]
911 NonConstantDeclValue { span: Span },
912 #[error("Declaring storage in a {program_kind} is not allowed.")]
913 StorageDeclarationInNonContract { program_kind: String, span: Span },
914 #[error("Unsupported argument type to intrinsic \"{name}\".{}", if hint.is_empty() { "".to_string() } else { format!(" Hint: {hint}") })]
915 IntrinsicUnsupportedArgType {
916 name: String,
917 span: Span,
918 hint: String,
919 },
920 #[error("Call to \"{name}\" expects {expected} argument(s)")]
921 IntrinsicIncorrectNumArgs {
922 name: String,
923 expected: u64,
924 span: Span,
925 },
926 #[error("Call to \"{name}\" expects {expected} type arguments")]
927 IntrinsicIncorrectNumTArgs {
928 name: String,
929 expected: u64,
930 span: Span,
931 },
932 #[error("Expected string literal")]
933 ExpectedStringLiteral { span: Span },
934 #[error("\"break\" used outside of a loop")]
935 BreakOutsideLoop { span: Span },
936 #[error("\"continue\" used outside of a loop")]
937 ContinueOutsideLoop { span: Span },
938 #[error("Contract ID value is not a literal.")]
941 ContractIdValueNotALiteral { span: Span },
942
943 #[error("{reason}")]
944 TypeNotAllowed {
945 reason: TypeNotAllowedReason,
946 span: Span,
947 },
948 #[error("ref mut parameter not allowed for main()")]
949 RefMutableNotAllowedInMain { param_name: Ident, span: Span },
950 #[error(
951 "Register \"{name}\" is initialized and later reassigned which is not allowed. \
952 Consider assigning to a different register inside the ASM block."
953 )]
954 InitializedRegisterReassignment { name: String, span: Span },
955 #[error("Control flow VM instructions are not allowed in assembly blocks.")]
956 DisallowedControlFlowInstruction { name: String, span: Span },
957 #[error("Calling private library method {name} is not allowed.")]
958 CallingPrivateLibraryMethod { name: String, span: Span },
959 #[error("Using intrinsic \"{intrinsic}\" in a predicate is not allowed.")]
960 DisallowedIntrinsicInPredicate { intrinsic: String, span: Span },
961 #[error("Possibly non-zero amount of coins transferred to non-payable contract method \"{fn_name}\".")]
962 CoinsPassedToNonPayableMethod { fn_name: Ident, span: Span },
963 #[error(
964 "Payable attribute mismatch. The \"{fn_name}\" method implementation \
965 {} in its signature in {interface_name}.",
966 if *missing_impl_attribute {
967 "is missing #[payable] attribute specified"
968 } else {
969 "has extra #[payable] attribute not mentioned"
970 }
971 )]
972 TraitImplPayabilityMismatch {
973 fn_name: Ident,
974 interface_name: InterfaceName,
975 missing_impl_attribute: bool,
976 span: Span,
977 },
978 #[error("Configurable constants are not allowed in libraries.")]
979 ConfigurableInLibrary { span: Span },
980 #[error("Multiple applicable items in scope. {}", {
981 let mut candidates = "".to_string();
982 let mut as_traits = as_traits.clone();
983 as_traits.sort_by_key(|a| a.0.to_lowercase());
985 for (index, as_trait) in as_traits.iter().enumerate() {
986 candidates = format!("{candidates}\n Disambiguate the associated {item_kind} for candidate #{index}\n <{} as {}>::{item_name}", as_trait.1, as_trait.0);
987 }
988 candidates
989 })]
990 MultipleApplicableItemsInScope {
991 span: Span,
992 item_name: String,
993 item_kind: String,
994 as_traits: Vec<(String, String)>,
995 },
996 #[error("Provided generic type is not of type str.")]
997 NonStrGenericType { span: Span },
998 #[error("A contract method cannot call methods belonging to the same ABI")]
999 ContractCallsItsOwnMethod { span: Span },
1000 #[error("ABI cannot define a method of the same name as its super-ABI \"{superabi}\"")]
1001 AbiShadowsSuperAbiMethod { span: Span, superabi: Ident },
1002 #[error("ABI cannot inherit samely named method (\"{method_name}\") from several super-ABIs: \"{superabi1}\" and \"{superabi2}\"")]
1003 ConflictingSuperAbiMethods {
1004 span: Span,
1005 method_name: String,
1006 superabi1: String,
1007 superabi2: String,
1008 },
1009 #[error("Associated types not supported in ABI.")]
1010 AssociatedTypeNotSupportedInAbi { span: Span },
1011 #[error("Cannot call ABI supertrait's method as a contract method: \"{fn_name}\"")]
1012 AbiSupertraitMethodCallAsContractCall { fn_name: Ident, span: Span },
1013 #[error(
1014 "Methods {method_name} and {other_method_name} name have clashing function selectors."
1015 )]
1016 FunctionSelectorClash {
1017 method_name: Ident,
1018 span: Span,
1019 other_method_name: Ident,
1020 other_span: Span,
1021 },
1022 #[error("{invalid_type} is not a valid type in the self type of an impl block.")]
1023 TypeIsNotValidAsImplementingFor {
1024 invalid_type: InvalidImplementingForType,
1025 trait_name: Option<String>,
1027 span: Span,
1028 },
1029 #[error("Uninitialized register is being read before being written")]
1030 UninitRegisterInAsmBlockBeingRead { span: Span },
1031 #[error("Expression of type \"{expression_type}\" cannot be dereferenced.")]
1032 ExpressionCannotBeDereferenced { expression_type: String, span: Span },
1033 #[error("Fallback functions can only exist in contracts")]
1034 FallbackFnsAreContractOnly { span: Span },
1035 #[error("Fallback functions cannot have parameters")]
1036 FallbackFnsCannotHaveParameters { span: Span },
1037 #[error("Could not generate the entry method. See errors above for more details.")]
1038 CouldNotGenerateEntry { span: Span },
1039 #[error("Missing `std` in dependencies.")]
1040 CouldNotGenerateEntryMissingStd { span: Span },
1041 #[error("Type \"{ty}\" does not implement AbiEncode or AbiDecode.")]
1042 CouldNotGenerateEntryMissingImpl { ty: String, span: Span },
1043 #[error("Only bool, u8, u16, u32, u64, u256, b256, string arrays and string slices can be used here.")]
1044 EncodingUnsupportedType { span: Span },
1045 #[error("Configurables need a function named \"abi_decode_in_place\" to be in scope.")]
1046 ConfigurableMissingAbiDecodeInPlace { span: Span },
1047 #[error("Collision detected between two different types.\n Shared hash:{hash}\n First type:{first_type}\n Second type:{second_type}")]
1048 ABIHashCollision {
1049 span: Span,
1050 hash: String,
1051 first_type: String,
1052 second_type: String,
1053 },
1054 #[error("Type must be known at this point")]
1055 TypeMustBeKnownAtThisPoint { span: Span, internal: String },
1056 #[error("Multiple impls satisfying trait for type.")]
1057 MultipleImplsSatisfyingTraitForType {
1058 span: Span,
1059 type_annotation: String,
1060 trait_names: Vec<String>,
1061 trait_types_and_names: Vec<(String, String)>,
1062 },
1063 #[error("Multiple contracts methods with the same name.")]
1064 MultipleContractsMethodsWithTheSameName { spans: Vec<Span> },
1065 #[error("Error type enum \"{enum_name}\" has non-error variant{} {}. All variants must be marked as `#[error]`.",
1066 plural_s(non_error_variants.len()),
1067 sequence_to_str(non_error_variants, Enclosing::DoubleQuote, 2)
1068 )]
1069 ErrorTypeEnumHasNonErrorVariants {
1070 enum_name: IdentUnique,
1071 non_error_variants: Vec<IdentUnique>,
1072 },
1073 #[error("Enum variant \"{enum_variant_name}\" is marked as `#[error]`, but \"{enum_name}\" is not an `#[error_type]` enum.")]
1074 ErrorAttributeInNonErrorEnum {
1075 enum_name: IdentUnique,
1076 enum_variant_name: IdentUnique,
1077 },
1078 #[error("Incoherent impl was found due to breaking orphan rule check.")]
1079 IncoherentImplDueToOrphanRule { span: Span },
1080}
1081
1082impl std::convert::From<TypeError> for CompileError {
1083 fn from(other: TypeError) -> CompileError {
1084 CompileError::TypeError(other)
1085 }
1086}
1087
1088impl Spanned for CompileError {
1089 fn span(&self) -> Span {
1090 use CompileError::*;
1091 match self {
1092 ConstGenericNotSupportedHere { span } => span.clone(),
1093 LengthExpressionNotSupported { span } => span.clone(),
1094 FeatureIsDisabled { span, .. } => span.clone(),
1095 ModuleDepGraphEvaluationError { .. } => Span::dummy(),
1096 ModuleDepGraphCyclicReference { .. } => Span::dummy(),
1097 UnknownVariable { span, .. } => span.clone(),
1098 NotAVariable { span, .. } => span.clone(),
1099 Unimplemented { span, .. } => span.clone(),
1100 TypeError(err) => err.span(),
1101 ParseError { span, .. } => span.clone(),
1102 Internal(_, span) => span.clone(),
1103 InternalOwned(_, span) => span.clone(),
1104 NoPredicateMainFunction(span) => span.clone(),
1105 PredicateMainDoesNotReturnBool(span) => span.clone(),
1106 NoScriptMainFunction(span) => span.clone(),
1107 MultipleDefinitionsOfFunction { span, .. } => span.clone(),
1108 MultipleDefinitionsOfName { span, .. } => span.clone(),
1109 MultipleDefinitionsOfConstant { span, .. } => span.clone(),
1110 MultipleDefinitionsOfType { span, .. } => span.clone(),
1111 MultipleDefinitionsOfMatchArmVariable { duplicate, .. } => duplicate.clone(),
1112 MultipleDefinitionsOfFallbackFunction { span, .. } => span.clone(),
1113 AssignmentToNonMutableVariable { lhs_span, .. } => lhs_span.clone(),
1114 AssignmentToConstantOrConfigurable { lhs_span, .. } => lhs_span.clone(),
1115 DeclAssignmentTargetCannotBeAssignedTo { lhs_span, .. } => lhs_span.clone(),
1116 AssignmentViaNonMutableReference { span, .. } => span.clone(),
1117 MutableParameterNotSupported { span, .. } => span.clone(),
1118 ImmutableArgumentToMutableParameter { span } => span.clone(),
1119 RefMutableNotAllowedInContractAbi { span, .. } => span.clone(),
1120 RefMutCannotReferenceConstant { span, .. } => span.clone(),
1121 RefMutCannotReferenceImmutableVariable { span, .. } => span.clone(),
1122 MethodRequiresMutableSelf { span, .. } => span.clone(),
1123 AssociatedFunctionCalledAsMethod { span, .. } => span.clone(),
1124 TypeParameterNotInTypeScope { span, .. } => span.clone(),
1125 MismatchedTypeInInterfaceSurface { span, .. } => span.clone(),
1126 UnknownTrait { span, .. } => span.clone(),
1127 FunctionNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1128 ConstantNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1129 TypeNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1130 MissingInterfaceSurfaceConstants { span, .. } => span.clone(),
1131 MissingInterfaceSurfaceTypes { span, .. } => span.clone(),
1132 MissingInterfaceSurfaceMethods { span, .. } => span.clone(),
1133 IncorrectNumberOfTypeArguments { span, .. } => span.clone(),
1134 DoesNotTakeTypeArguments { span, .. } => span.clone(),
1135 DoesNotTakeTypeArgumentsAsPrefix { span, .. } => span.clone(),
1136 TypeArgumentsNotAllowed { span } => span.clone(),
1137 NeedsTypeArguments { span, .. } => span.clone(),
1138 StructInstantiationMissingFieldForErrorRecovery { span, .. } => span.clone(),
1139 StructInstantiationMissingFields { span, .. } => span.clone(),
1140 StructCannotBeInstantiated { span, .. } => span.clone(),
1141 StructFieldIsPrivate { field_name, .. } => field_name.span(),
1142 StructFieldDoesNotExist { field_name, .. } => field_name.span(),
1143 StructFieldDuplicated { field_name, .. } => field_name.span(),
1144 MethodNotFound { span, .. } => span.clone(),
1145 ModuleNotFound { span, .. } => span.clone(),
1146 TupleElementAccessOnNonTuple { span, .. } => span.clone(),
1147 NotAStruct { span, .. } => span.clone(),
1148 NotIndexable { span, .. } => span.clone(),
1149 FieldAccessOnNonStruct { span, .. } => span.clone(),
1150 SymbolNotFound { span, .. } => span.clone(),
1151 SymbolWithMultipleBindings { span, .. } => span.clone(),
1152 ImportPrivateSymbol { span, .. } => span.clone(),
1153 ImportPrivateModule { span, .. } => span.clone(),
1154 NoElseBranch { span, .. } => span.clone(),
1155 NotAType { span, .. } => span.clone(),
1156 MissingEnumInstantiator { span, .. } => span.clone(),
1157 PathDoesNotReturn { span, .. } => span.clone(),
1158 UnknownRegister { span, .. } => span.clone(),
1159 MissingImmediate { span, .. } => span.clone(),
1160 InvalidImmediateValue { span, .. } => span.clone(),
1161 UnknownEnumVariant { span, .. } => span.clone(),
1162 UnrecognizedOp { span, .. } => span.clone(),
1163 UnableToInferGeneric { span, .. } => span.clone(),
1164 UnconstrainedGenericParameter { span, .. } => span.clone(),
1165 TraitConstraintNotSatisfied { span, .. } => span.clone(),
1166 TraitConstraintMissing { span, .. } => span.clone(),
1167 Immediate06TooLarge { span, .. } => span.clone(),
1168 Immediate12TooLarge { span, .. } => span.clone(),
1169 Immediate18TooLarge { span, .. } => span.clone(),
1170 Immediate24TooLarge { span, .. } => span.clone(),
1171 IncorrectNumberOfAsmRegisters { span, .. } => span.clone(),
1172 UnnecessaryImmediate { span, .. } => span.clone(),
1173 AmbiguousPath { span } => span.clone(),
1174 ModulePathIsNotAnExpression { span, .. } => span.clone(),
1175 UnknownType { span, .. } => span.clone(),
1176 UnknownTypeName { span, .. } => span.clone(),
1177 FileCouldNotBeRead { span, .. } => span.clone(),
1178 ImportMustBeLibrary { span, .. } => span.clone(),
1179 MoreThanOneEnumInstantiator { span, .. } => span.clone(),
1180 UnnecessaryEnumInstantiator { span, .. } => span.clone(),
1181 UnitVariantWithParenthesesEnumInstantiator { span, .. } => span.clone(),
1182 TraitNotFound { span, .. } => span.clone(),
1183 TraitNotImportedAtFunctionApplication {
1184 function_call_site_span,
1185 ..
1186 } => function_call_site_span.clone(),
1187 InvalidExpressionOnLhs { span, .. } => span.clone(),
1188 TooManyArgumentsForFunction { span, .. } => span.clone(),
1189 TooFewArgumentsForFunction { span, .. } => span.clone(),
1190 MissingParenthesesForFunction { span, .. } => span.clone(),
1191 InvalidAbiType { span, .. } => span.clone(),
1192 NotAnAbi { span, .. } => span.clone(),
1193 ImplAbiForNonContract { span, .. } => span.clone(),
1194 ConflictingImplsForTraitAndType {
1195 second_impl_span, ..
1196 } => second_impl_span.clone(),
1197 MarkerTraitExplicitlyImplemented { span, .. } => span.clone(),
1198 DuplicateDeclDefinedForType {
1199 second_impl_span, ..
1200 } => second_impl_span.clone(),
1201 IncorrectNumberOfInterfaceSurfaceFunctionParameters { span, .. } => span.clone(),
1202 ArgumentParameterTypeMismatch { span, .. } => span.clone(),
1203 RecursiveCall { span, .. } => span.clone(),
1204 RecursiveCallChain { span, .. } => span.clone(),
1205 RecursiveType { span, .. } => span.clone(),
1206 RecursiveTypeChain { span, .. } => span.clone(),
1207 GMFromExternalContext { span, .. } => span.clone(),
1208 MintFromExternalContext { span, .. } => span.clone(),
1209 BurnFromExternalContext { span, .. } => span.clone(),
1210 ContractStorageFromExternalContext { span, .. } => span.clone(),
1211 InvalidOpcodeFromPredicate { span, .. } => span.clone(),
1212 ArrayOutOfBounds { span, .. } => span.clone(),
1213 ConstantRequiresExpression { span, .. } => span.clone(),
1214 ConstantsCannotBeShadowed { name, .. } => name.span(),
1215 ConfigurablesCannotBeShadowed { name, .. } => name.span(),
1216 ConfigurablesCannotBeMatchedAgainst { name, .. } => name.span(),
1217 ConstantShadowsVariable { name, .. } => name.span(),
1218 ConstantDuplicatesConstantOrConfigurable { name, .. } => name.span(),
1219 ShadowsOtherSymbol { name } => name.span(),
1220 GenericShadowsGeneric { name } => name.span(),
1221 MatchExpressionNonExhaustive { span, .. } => span.clone(),
1222 MatchStructPatternMissingFields { span, .. } => span.clone(),
1223 MatchStructPatternMustIgnorePrivateFields { span, .. } => span.clone(),
1224 MatchArmVariableNotDefinedInAllAlternatives { variable, .. } => variable.span(),
1225 MatchArmVariableMismatchedType { variable, .. } => variable.span(),
1226 MatchedValueIsNotValid { span, .. } => span.clone(),
1227 NotAnEnum { span, .. } => span.clone(),
1228 TraitDeclPureImplImpure { span, .. } => span.clone(),
1229 TraitImplPurityMismatch { span, .. } => span.clone(),
1230 DeclIsNotAnEnum { span, .. } => span.clone(),
1231 DeclIsNotAStruct { span, .. } => span.clone(),
1232 DeclIsNotAFunction { span, .. } => span.clone(),
1233 DeclIsNotAVariable { span, .. } => span.clone(),
1234 DeclIsNotAnAbi { span, .. } => span.clone(),
1235 DeclIsNotATrait { span, .. } => span.clone(),
1236 DeclIsNotAnImplTrait { span, .. } => span.clone(),
1237 DeclIsNotATraitFn { span, .. } => span.clone(),
1238 DeclIsNotStorage { span, .. } => span.clone(),
1239 DeclIsNotAConstant { span, .. } => span.clone(),
1240 DeclIsNotATypeAlias { span, .. } => span.clone(),
1241 ImpureInNonContract { span, .. } => span.clone(),
1242 StorageAccessMismatched { span, .. } => span.clone(),
1243 ParameterRefMutabilityMismatch { span, .. } => span.clone(),
1244 IntegerTooLarge { span, .. } => span.clone(),
1245 IntegerTooSmall { span, .. } => span.clone(),
1246 IntegerContainsInvalidDigit { span, .. } => span.clone(),
1247 AbiAsSupertrait { span, .. } => span.clone(),
1248 SupertraitImplRequired { span, .. } => span.clone(),
1249 ContractCallParamRepeated { span, .. } => span.clone(),
1250 UnrecognizedContractParam { span, .. } => span.clone(),
1251 CallParamForNonContractCallMethod { span, .. } => span.clone(),
1252 StorageFieldDoesNotExist { field_name, .. } => field_name.span(),
1253 InvalidStorageOnlyTypeDecl { span, .. } => span.clone(),
1254 NoDeclaredStorage { span, .. } => span.clone(),
1255 MultipleStorageDeclarations { span, .. } => span.clone(),
1256 UnexpectedDeclaration { span, .. } => span.clone(),
1257 ContractAddressMustBeKnown { span, .. } => span.clone(),
1258 ConvertParseTree { error } => error.span(),
1259 Lex { error } => error.span(),
1260 Parse { error } => error.span.clone(),
1261 EnumNotFound { span, .. } => span.clone(),
1262 TupleIndexOutOfBounds { span, .. } => span.clone(),
1263 NonConstantDeclValue { span, .. } => span.clone(),
1264 StorageDeclarationInNonContract { span, .. } => span.clone(),
1265 IntrinsicUnsupportedArgType { span, .. } => span.clone(),
1266 IntrinsicIncorrectNumArgs { span, .. } => span.clone(),
1267 IntrinsicIncorrectNumTArgs { span, .. } => span.clone(),
1268 BreakOutsideLoop { span } => span.clone(),
1269 ContinueOutsideLoop { span } => span.clone(),
1270 ContractIdValueNotALiteral { span } => span.clone(),
1271 RefMutableNotAllowedInMain { span, .. } => span.clone(),
1272 InitializedRegisterReassignment { span, .. } => span.clone(),
1273 DisallowedControlFlowInstruction { span, .. } => span.clone(),
1274 CallingPrivateLibraryMethod { span, .. } => span.clone(),
1275 DisallowedIntrinsicInPredicate { span, .. } => span.clone(),
1276 CoinsPassedToNonPayableMethod { span, .. } => span.clone(),
1277 TraitImplPayabilityMismatch { span, .. } => span.clone(),
1278 ConfigurableInLibrary { span } => span.clone(),
1279 MultipleApplicableItemsInScope { span, .. } => span.clone(),
1280 NonStrGenericType { span } => span.clone(),
1281 CannotBeEvaluatedToConst { span } => span.clone(),
1282 ContractCallsItsOwnMethod { span } => span.clone(),
1283 AbiShadowsSuperAbiMethod { span, .. } => span.clone(),
1284 ConflictingSuperAbiMethods { span, .. } => span.clone(),
1285 AssociatedTypeNotSupportedInAbi { span, .. } => span.clone(),
1286 AbiSupertraitMethodCallAsContractCall { span, .. } => span.clone(),
1287 FunctionSelectorClash { span, .. } => span.clone(),
1288 TypeNotAllowed { span, .. } => span.clone(),
1289 ExpectedStringLiteral { span } => span.clone(),
1290 TypeIsNotValidAsImplementingFor { span, .. } => span.clone(),
1291 UninitRegisterInAsmBlockBeingRead { span } => span.clone(),
1292 ExpressionCannotBeDereferenced { span, .. } => span.clone(),
1293 FallbackFnsAreContractOnly { span } => span.clone(),
1294 FallbackFnsCannotHaveParameters { span } => span.clone(),
1295 CouldNotGenerateEntry { span } => span.clone(),
1296 CouldNotGenerateEntryMissingStd { span } => span.clone(),
1297 CouldNotGenerateEntryMissingImpl { span, .. } => span.clone(),
1298 CannotBeEvaluatedToConfigurableSizeUnknown { span } => span.clone(),
1299 EncodingUnsupportedType { span } => span.clone(),
1300 ConfigurableMissingAbiDecodeInPlace { span } => span.clone(),
1301 ABIHashCollision { span, .. } => span.clone(),
1302 InvalidRangeEndGreaterThanStart { span, .. } => span.clone(),
1303 TypeMustBeKnownAtThisPoint { span, .. } => span.clone(),
1304 MultipleImplsSatisfyingTraitForType { span, .. } => span.clone(),
1305 MultipleContractsMethodsWithTheSameName { spans } => spans[0].clone(),
1306 ErrorTypeEnumHasNonErrorVariants { enum_name, .. } => enum_name.span(),
1307 ErrorAttributeInNonErrorEnum {
1308 enum_variant_name, ..
1309 } => enum_variant_name.span(),
1310 IncoherentImplDueToOrphanRule { span, .. } => span.clone(),
1311 }
1312 }
1313}
1314
1315impl ToDiagnostic for CompileError {
1327 fn to_diagnostic(&self, source_engine: &SourceEngine) -> Diagnostic {
1328 let code = Code::semantic_analysis;
1329 use CompileError::*;
1330 match self {
1331 ConstantsCannotBeShadowed { shadowing_source, name, constant_span, constant_decl_span, is_alias } => Diagnostic {
1332 reason: Some(Reason::new(code(1), "Constants cannot be shadowed".to_string())),
1333 issue: Issue::error(
1334 source_engine,
1335 name.span(),
1336 format!(
1337 "{shadowing_source} \"{name}\" shadows {}constant of the same name.",
1343 if constant_decl_span.clone() != Span::dummy() { "imported " } else { "" }
1344 )
1345 ),
1346 hints: vec![
1347 Hint::info(
1348 source_engine,
1349 constant_span.clone(),
1350 format!(
1351 "Shadowed constant \"{name}\" {} here{}.",
1357 if constant_decl_span.clone() != Span::dummy() { "gets imported" } else { "is declared" },
1358 if *is_alias { " as alias" } else { "" }
1359 )
1360 ),
1361 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1362 Hint::help(
1363 source_engine,
1364 name.span(),
1365 format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1366 )
1367 } else {
1368 Hint::none()
1369 },
1370 Hint::info( source_engine,
1372 constant_decl_span.clone(),
1373 format!("This is the original declaration of the imported constant \"{name}\".")
1374 ),
1375 ],
1376 help: vec![
1377 "Unlike variables, constants cannot be shadowed by other constants or variables.".to_string(),
1378 match (shadowing_source, *constant_decl_span != Span::dummy()) {
1379 (LetVar | PatternMatchingStructFieldVar, false) => format!("Consider renaming either the {} \"{name}\" or the constant \"{name}\".",
1380 format!("{shadowing_source}").to_lowercase(),
1381 ),
1382 (Const, false) => "Consider renaming one of the constants.".to_string(),
1383 (shadowing_source, true) => format!(
1384 "Consider renaming the {} \"{name}\" or using {} for the imported constant.",
1385 format!("{shadowing_source}").to_lowercase(),
1386 if *is_alias { "a different alias" } else { "an alias" }
1387 ),
1388 },
1389 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1390 format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1391 } else {
1392 Diagnostic::help_none()
1393 }
1394 ],
1395 },
1396 ConfigurablesCannotBeShadowed { shadowing_source, name, configurable_span } => Diagnostic {
1397 reason: Some(Reason::new(code(1), "Configurables cannot be shadowed".to_string())),
1398 issue: Issue::error(
1399 source_engine,
1400 name.span(),
1401 format!("{shadowing_source} \"{name}\" shadows configurable of the same name.")
1402 ),
1403 hints: vec![
1404 Hint::info(
1405 source_engine,
1406 configurable_span.clone(),
1407 format!("Shadowed configurable \"{name}\" is declared here.")
1408 ),
1409 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1410 Hint::help(
1411 source_engine,
1412 name.span(),
1413 format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1414 )
1415 } else {
1416 Hint::none()
1417 },
1418 ],
1419 help: vec![
1420 "Unlike variables, configurables cannot be shadowed by constants or variables.".to_string(),
1421 format!(
1422 "Consider renaming either the {} \"{name}\" or the configurable \"{name}\".",
1423 format!("{shadowing_source}").to_lowercase()
1424 ),
1425 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1426 format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1427 } else {
1428 Diagnostic::help_none()
1429 }
1430 ],
1431 },
1432 ConfigurablesCannotBeMatchedAgainst { name, configurable_span } => Diagnostic {
1433 reason: Some(Reason::new(code(1), "Configurables cannot be matched against".to_string())),
1434 issue: Issue::error(
1435 source_engine,
1436 name.span(),
1437 format!("\"{name}\" is a configurable and configurables cannot be matched against.")
1438 ),
1439 hints: {
1440 let mut hints = vec![
1441 Hint::info(
1442 source_engine,
1443 configurable_span.clone(),
1444 format!("Configurable \"{name}\" is declared here.")
1445 ),
1446 ];
1447
1448 hints.append(&mut Hint::multi_help(source_engine, &name.span(), vec![
1449 format!("Are you trying to define a pattern variable named \"{name}\"?"),
1450 format!("In that case, use some other name for the pattern variable,"),
1451 format!("or consider renaming the configurable \"{name}\"."),
1452 ]));
1453
1454 hints
1455 },
1456 help: vec![
1457 "Unlike constants, configurables cannot be matched against in pattern matching.".to_string(),
1458 "That's not possible, because patterns to match against must be compile-time constants.".to_string(),
1459 "Configurables are run-time constants. Their values are defined during the deployment.".to_string(),
1460 Diagnostic::help_empty_line(),
1461 "To test against a configurable, consider:".to_string(),
1462 format!("{}- replacing the `match` expression with `if-else`s altogether.", Indent::Single),
1463 format!("{}- matching against a variable and comparing that variable afterwards with the configurable.", Indent::Single),
1464 format!("{} E.g., instead of:", Indent::Single),
1465 Diagnostic::help_empty_line(),
1466 format!("{} SomeStruct {{ x: A_CONFIGURABLE, y: 42 }} => {{", Indent::Double),
1467 format!("{} do_something();", Indent::Double),
1468 format!("{} }}", Indent::Double),
1469 Diagnostic::help_empty_line(),
1470 format!("{} to have:", Indent::Single),
1471 Diagnostic::help_empty_line(),
1472 format!("{} SomeStruct {{ x, y: 42 }} => {{", Indent::Double),
1473 format!("{} if x == A_CONFIGURABLE {{", Indent::Double),
1474 format!("{} do_something();", Indent::Double),
1475 format!("{} }}", Indent::Double),
1476 format!("{} }}", Indent::Double),
1477 ],
1478 },
1479 ConstantShadowsVariable { name , variable_span } => Diagnostic {
1480 reason: Some(Reason::new(code(1), "Constants cannot shadow variables".to_string())),
1481 issue: Issue::error(
1482 source_engine,
1483 name.span(),
1484 format!("Constant \"{name}\" shadows variable of the same name.")
1485 ),
1486 hints: vec![
1487 Hint::info(
1488 source_engine,
1489 variable_span.clone(),
1490 format!("This is the shadowed variable \"{name}\".")
1491 ),
1492 ],
1493 help: vec![
1494 format!("Variables can shadow other variables, but constants cannot."),
1495 format!("Consider renaming either the variable or the constant."),
1496 ],
1497 },
1498 ConstantDuplicatesConstantOrConfigurable { existing_constant_or_configurable, new_constant_or_configurable, name, existing_span } => Diagnostic {
1499 reason: Some(Reason::new(code(1), match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1500 ("Constant", "Constant") => "Constant of the same name already exists".to_string(),
1501 ("Constant", "Configurable") => "Constant of the same name as configurable already exists".to_string(),
1502 ("Configurable", "Constant") => "Configurable of the same name as constant already exists".to_string(),
1503 _ => unreachable!("We can have only the listed combinations. Configurable duplicating configurable is not a valid combination.")
1504 })),
1505 issue: Issue::error(
1506 source_engine,
1507 name.span(),
1508 format!("{new_constant_or_configurable} \"{name}\" has the same name as an already declared {}.",
1509 existing_constant_or_configurable.to_lowercase()
1510 )
1511 ),
1512 hints: vec![
1513 Hint::info(
1514 source_engine,
1515 existing_span.clone(),
1516 format!("{existing_constant_or_configurable} \"{name}\" is {}declared here.",
1517 if existing_constant_or_configurable == new_constant_or_configurable {
1519 "already "
1520 } else {
1521 ""
1522 }
1523 )
1524 ),
1525 ],
1526 help: vec![
1527 match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1528 ("Constant", "Constant") => "Consider renaming one of the constants, or in case of imported constants, using an alias.".to_string(),
1529 _ => "Consider renaming either the configurable or the constant, or in case of an imported constant, using an alias.".to_string(),
1530 },
1531 ],
1532 },
1533 MultipleDefinitionsOfMatchArmVariable { match_value, match_type, first_definition, first_definition_is_struct_field, duplicate, duplicate_is_struct_field } => Diagnostic {
1534 reason: Some(Reason::new(code(1), "Match pattern variable is already defined".to_string())),
1535 issue: Issue::error(
1536 source_engine,
1537 duplicate.clone(),
1538 format!("Variable \"{}\" is already defined in this match arm.", first_definition.as_str())
1539 ),
1540 hints: vec![
1541 Hint::help(
1542 source_engine,
1543 if *duplicate_is_struct_field {
1544 duplicate.clone()
1545 }
1546 else {
1547 Span::dummy()
1548 },
1549 format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str())
1550 ),
1551 Hint::info(
1552 source_engine,
1553 first_definition.clone(),
1554 format!(
1555 "This {}is the first definition of the variable \"{}\".",
1556 if *first_definition_is_struct_field {
1557 format!("struct field \"{}\" ", first_definition.as_str())
1558 }
1559 else {
1560 "".to_string()
1561 },
1562 first_definition.as_str(),
1563 )
1564 ),
1565 Hint::help(
1566 source_engine,
1567 if *first_definition_is_struct_field && !*duplicate_is_struct_field {
1568 first_definition.clone()
1569 }
1570 else {
1571 Span::dummy()
1572 },
1573 format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str()),
1574 ),
1575 Hint::info(
1576 source_engine,
1577 match_value.clone(),
1578 format!("The expression to match on is of type \"{match_type}\".")
1579 ),
1580 ],
1581 help: vec![
1582 format!("Variables used in match arm patterns must be unique within a pattern, except in alternatives."),
1583 match (*first_definition_is_struct_field, *duplicate_is_struct_field) {
1584 (true, true) => format!("Consider declaring a variable with different name for either of the fields. E.g., `{0}: var_{0}`.", first_definition.as_str()),
1585 (true, false) | (false, true) => format!("Consider declaring a variable for the field \"{0}\" (e.g., `{0}: var_{0}`), or renaming the variable \"{0}\".", first_definition.as_str()),
1586 (false, false) => "Consider renaming either of the variables.".to_string(),
1587 },
1588 ],
1589 },
1590 MatchArmVariableMismatchedType { match_value, match_type, variable, first_definition, expected, received } => Diagnostic {
1591 reason: Some(Reason::new(code(1), "Match pattern variable has mismatched type".to_string())),
1592 issue: Issue::error(
1593 source_engine,
1594 variable.span(),
1595 format!("Variable \"{variable}\" is expected to be of type \"{expected}\", but is \"{received}\".")
1596 ),
1597 hints: vec![
1598 Hint::info(
1599 source_engine,
1600 first_definition.clone(),
1601 format!("\"{variable}\" is first defined here with type \"{expected}\".")
1602 ),
1603 Hint::info(
1604 source_engine,
1605 match_value.clone(),
1606 format!("The expression to match on is of type \"{match_type}\".")
1607 ),
1608 ],
1609 help: vec![
1610 format!("In the same match arm, a variable must have the same type in all alternatives."),
1611 ],
1612 },
1613 MatchArmVariableNotDefinedInAllAlternatives { match_value, match_type, variable, missing_in_alternatives} => Diagnostic {
1614 reason: Some(Reason::new(code(1), "Match pattern variable is not defined in all alternatives".to_string())),
1615 issue: Issue::error(
1616 source_engine,
1617 variable.span(),
1618 format!("Variable \"{variable}\" is not defined in all alternatives.")
1619 ),
1620 hints: {
1621 let mut hints = vec![
1622 Hint::info(
1623 source_engine,
1624 match_value.clone(),
1625 format!("The expression to match on is of type \"{match_type}\".")
1626 ),
1627 ];
1628
1629 for (i, alternative) in missing_in_alternatives.iter().enumerate() {
1630 hints.push(
1631 Hint::info(
1632 source_engine,
1633 alternative.clone(),
1634 format!("\"{variable}\" is {}missing in this alternative.", if i != 0 { "also " } else { "" }),
1635 )
1636 )
1637 }
1638
1639 hints
1640 },
1641 help: vec![
1642 format!("Consider removing the variable \"{variable}\" altogether, or adding it to all alternatives."),
1643 ],
1644 },
1645 MatchStructPatternMissingFields { missing_fields, missing_fields_are_public, struct_name, struct_decl_span, total_number_of_fields, span } => Diagnostic {
1646 reason: Some(Reason::new(code(1), "Struct pattern has missing fields".to_string())),
1647 issue: Issue::error(
1648 source_engine,
1649 span.clone(),
1650 format!("Struct pattern is missing the {}field{} {}.",
1651 if *missing_fields_are_public { "public " } else { "" },
1652 plural_s(missing_fields.len()),
1653 sequence_to_str(missing_fields, Enclosing::DoubleQuote, 2)
1654 )
1655 ),
1656 hints: vec![
1657 Hint::help(
1658 source_engine,
1659 span.clone(),
1660 "Struct pattern must either contain or ignore each struct field.".to_string()
1661 ),
1662 Hint::info(
1663 source_engine,
1664 struct_decl_span.clone(),
1665 format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1666 num_to_str(*total_number_of_fields),
1667 plural_s(*total_number_of_fields),
1668 )
1669 ),
1670 ],
1671 help: vec![
1672 format!("Consider ignoring {} field{} {}by using the `_` pattern{} `{}: _`.",
1676 singular_plural(missing_fields.len(), "the", "individual"),
1677 plural_s(missing_fields.len()),
1678 singular_plural(missing_fields.len(), &format!("\"{}\" ", missing_fields[0]), ""),
1679 singular_plural(missing_fields.len(), ":", ". E.g.,"),
1680 missing_fields[0]
1681 ),
1682 "Alternatively, consider ignoring all the missing fields by ending the struct pattern with `..`.".to_string(),
1683 ],
1684 },
1685 MatchStructPatternMustIgnorePrivateFields { private_fields, struct_name, struct_decl_span, all_fields_are_private, span } => Diagnostic {
1686 reason: Some(Reason::new(code(1), "Struct pattern must ignore inaccessible private fields".to_string())),
1687 issue: Issue::error(
1688 source_engine,
1689 span.clone(),
1690 format!("Struct pattern must ignore inaccessible private field{} {}.",
1691 plural_s(private_fields.len()),
1692 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1693 )
1694 ),
1695 hints: vec![
1696 Hint::help(
1697 source_engine,
1698 span.clone(),
1699 format!("To ignore the private field{}, end the struct pattern with `..`.",
1700 plural_s(private_fields.len()),
1701 )
1702 ),
1703 Hint::info(
1704 source_engine,
1705 struct_decl_span.clone(),
1706 format!("Struct \"{struct_name}\" is declared here, and has {}.",
1707 if *all_fields_are_private {
1708 "all private fields".to_string()
1709 } else {
1710 format!("private field{} {}",
1711 plural_s(private_fields.len()),
1712 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1713 )
1714 }
1715 )
1716 ),
1717 ],
1718 help: vec![],
1719 },
1720 TraitNotImportedAtFunctionApplication { trait_name, function_name, function_call_site_span, trait_constraint_span, trait_candidates } => {
1721 let mut trait_candidates = trait_candidates.clone();
1723 trait_candidates.sort();
1724 let trait_candidates = &trait_candidates; Diagnostic {
1727 reason: Some(Reason::new(code(1), "Trait is not imported".to_string())),
1728 issue: Issue::error(
1729 source_engine,
1730 function_call_site_span.clone(),
1731 format!(
1732 "Trait \"{trait_name}\" is not imported {}when calling \"{function_name}\".",
1733 get_file_name(source_engine, function_call_site_span.source_id())
1734 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1735 )
1736 ),
1737 hints: {
1738 let mut hints = vec![
1739 Hint::help(
1740 source_engine,
1741 function_call_site_span.clone(),
1742 format!("This import is needed because \"{function_name}\" requires \"{trait_name}\" in one of its trait constraints.")
1743 ),
1744 Hint::info(
1745 source_engine,
1746 trait_constraint_span.clone(),
1747 format!("In the definition of \"{function_name}\", \"{trait_name}\" is used in this trait constraint.")
1748 ),
1749 ];
1750
1751 match trait_candidates.len() {
1752 0 => (),
1757 1 => hints.push(Hint::help(
1759 source_engine,
1760 function_call_site_span.clone(),
1761 format!(
1762 "Import the \"{trait_name}\" trait {}by using: `use {};`.",
1763 get_file_name(source_engine, function_call_site_span.source_id())
1764 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" ")),
1765 trait_candidates[0]
1766 )
1767 )),
1768 _ => hints.push(Hint::help(
1770 source_engine,
1771 function_call_site_span.clone(),
1772 format!(
1773 "To import the proper \"{trait_name}\" {}follow the detailed instructions given below.",
1774 get_file_name(source_engine, function_call_site_span.source_id())
1775 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1776 )
1777 )),
1778 }
1779
1780 hints
1781 },
1782 help: {
1783 let mut help = vec![];
1784
1785 if trait_candidates.len() > 1 {
1786 help.push(format!("There are these {} traits with the name \"{trait_name}\" available in the modules:", num_to_str(trait_candidates.len())));
1787 for trait_candidate in trait_candidates.iter() {
1788 help.push(format!("{}- {trait_candidate}", Indent::Single));
1789 }
1790 help.push("To import the proper one follow these steps:".to_string());
1791 help.push(format!(
1792 "{}1. Look at the definition of the \"{function_name}\"{}.",
1793 Indent::Single,
1794 get_file_name(source_engine, trait_constraint_span.source_id())
1795 .map_or("".to_string(), |file_name| format!(" in the \"{file_name}\""))
1796 ));
1797 help.push(format!(
1798 "{}2. Detect which exact \"{trait_name}\" is used in the trait constraint in the \"{function_name}\".",
1799 Indent::Single
1800 ));
1801 help.push(format!(
1802 "{}3. Import that \"{trait_name}\"{}.",
1803 Indent::Single,
1804 get_file_name(source_engine, function_call_site_span.source_id())
1805 .map_or("".to_string(), |file_name| format!(" into \"{file_name}\""))
1806 ));
1807 help.push(format!("{} E.g., assuming it is the first one on the list, use: `use {};`", Indent::Double, trait_candidates[0]));
1808 }
1809
1810 help
1811 },
1812 }
1813 },
1814 ExpressionCannotBeDereferenced { expression_type, span } => Diagnostic {
1816 reason: Some(Reason::new(code(1), "Expression cannot be dereferenced".to_string())),
1817 issue: Issue::error(
1818 source_engine,
1819 span.clone(),
1820 format!("This expression cannot be dereferenced, because it is of type \"{expression_type}\", which is not a reference type.")
1821 ),
1822 hints: vec![
1823 Hint::help(
1824 source_engine,
1825 span.clone(),
1826 "In Sway, only references can be dereferenced.".to_string()
1827 ),
1828 Hint::help(
1829 source_engine,
1830 span.clone(),
1831 "Are you missing the reference operator `&` somewhere in the code?".to_string()
1832 ),
1833 ],
1834 help: vec![],
1835 },
1836 StructInstantiationMissingFields { field_names, struct_name, span, struct_decl_span, total_number_of_fields } => Diagnostic {
1837 reason: Some(Reason::new(code(1), "Struct instantiation has missing fields".to_string())),
1838 issue: Issue::error(
1839 source_engine,
1840 span.clone(),
1841 format!("Instantiation of the struct \"{struct_name}\" is missing the field{} {}.",
1842 plural_s(field_names.len()),
1843 sequence_to_str(field_names, Enclosing::DoubleQuote, 2)
1844 )
1845 ),
1846 hints: vec![
1847 Hint::help(
1848 source_engine,
1849 span.clone(),
1850 "Struct instantiation must initialize all the fields of the struct.".to_string()
1851 ),
1852 Hint::info(
1853 source_engine,
1854 struct_decl_span.clone(),
1855 format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1856 num_to_str(*total_number_of_fields),
1857 plural_s(*total_number_of_fields),
1858 )
1859 ),
1860 ],
1861 help: vec![],
1862 },
1863 StructCannotBeInstantiated { struct_name, span, struct_decl_span, private_fields, constructors, all_fields_are_private, is_in_storage_declaration, struct_can_be_changed } => Diagnostic {
1864 reason: Some(Reason::new(code(1), "Struct cannot be instantiated due to inaccessible private fields".to_string())),
1865 issue: Issue::error(
1866 source_engine,
1867 span.clone(),
1868 format!("\"{struct_name}\" cannot be {}instantiated in this {}, due to {}inaccessible private field{}.",
1869 if *is_in_storage_declaration { "" } else { "directly " },
1870 if *is_in_storage_declaration { "storage declaration" } else { "module" },
1871 singular_plural(private_fields.len(), "an ", ""),
1872 plural_s(private_fields.len())
1873 )
1874 ),
1875 hints: vec![
1876 Hint::help(
1877 source_engine,
1878 span.clone(),
1879 format!("Inaccessible field{} {} {}.",
1880 plural_s(private_fields.len()),
1881 is_are(private_fields.len()),
1882 sequence_to_str(private_fields, Enclosing::DoubleQuote, 5)
1883 )
1884 ),
1885 Hint::help(
1886 source_engine,
1887 span.clone(),
1888 if *is_in_storage_declaration {
1889 "Structs with private fields can be instantiated in storage declarations only if they are declared in the same module as the storage.".to_string()
1890 } else {
1891 "Structs with private fields can be instantiated only within the module in which they are declared.".to_string()
1892 }
1893 ),
1894 if *is_in_storage_declaration {
1895 Hint::help(
1896 source_engine,
1897 span.clone(),
1898 "They can still be initialized in storage declarations if they have public constructors that evaluate to a constant.".to_string()
1899 )
1900 } else {
1901 Hint::none()
1902 },
1903 if *is_in_storage_declaration {
1904 Hint::help(
1905 source_engine,
1906 span.clone(),
1907 "They can always be stored in storage by using the `read` and `write` functions provided in the `std::storage::storage_api`.".to_string()
1908 )
1909 } else {
1910 Hint::none()
1911 },
1912 if !*is_in_storage_declaration && !constructors.is_empty() {
1913 Hint::help(
1914 source_engine,
1915 span.clone(),
1916 format!("\"{struct_name}\" can be instantiated via public constructors suggested below.")
1917 )
1918 } else {
1919 Hint::none()
1920 },
1921 Hint::info(
1922 source_engine,
1923 struct_decl_span.clone(),
1924 format!("Struct \"{struct_name}\" is declared here, and has {}.",
1925 if *all_fields_are_private {
1926 "all private fields".to_string()
1927 } else {
1928 format!("private field{} {}",
1929 plural_s(private_fields.len()),
1930 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1931 )
1932 }
1933 )
1934 ),
1935 ],
1936 help: {
1937 let mut help = vec![];
1938
1939 if *is_in_storage_declaration {
1940 help.push(format!("Consider initializing \"{struct_name}\" by finding an available constructor that evaluates to a constant{}.",
1941 if *struct_can_be_changed {
1942 ", or implement a new one"
1943 } else {
1944 ""
1945 }
1946 ));
1947
1948 if !constructors.is_empty() {
1949 help.push("Check these already available constructors. They might evaluate to a constant:".to_string());
1950 for constructor in sequence_to_list(constructors, Indent::Single, usize::MAX) {
1952 help.push(constructor);
1953 }
1954 };
1955
1956 help.push(Diagnostic::help_empty_line());
1957
1958 help.push(format!("Or you can always store instances of \"{struct_name}\" in the contract storage, by using the `std::storage::storage_api`:"));
1959 help.push(format!("{}use std::storage::storage_api::{{read, write}};", Indent::Single));
1960 help.push(format!("{}write(STORAGE_KEY, 0, my_{});", Indent::Single, to_snake_case(struct_name.as_str())));
1961 help.push(format!("{}let my_{}_option = read::<{struct_name}>(STORAGE_KEY, 0);", Indent::Single, to_snake_case(struct_name.as_str())));
1962 }
1963 else if !constructors.is_empty() {
1964 help.push(format!("Consider instantiating \"{struct_name}\" by using one of the available constructors{}:",
1965 if *struct_can_be_changed {
1966 ", or implement a new one"
1967 } else {
1968 ""
1969 }
1970 ));
1971 for constructor in sequence_to_list(constructors, Indent::Single, 5) {
1972 help.push(constructor);
1973 }
1974 }
1975
1976 if *struct_can_be_changed {
1977 if *is_in_storage_declaration || !constructors.is_empty() {
1978 help.push(Diagnostic::help_empty_line());
1979 }
1980
1981 if !*is_in_storage_declaration && constructors.is_empty() {
1982 help.push(format!("Consider implementing a public constructor for \"{struct_name}\"."));
1983 };
1984
1985 help.push(
1986 format!("Alternatively, consider declaring {} as public in \"{struct_name}\": `pub {}: ...,`.",
1992 if *all_fields_are_private {
1993 "all fields".to_string()
1994 } else {
1995 format!("{} {}",
1996 singular_plural(private_fields.len(), "the field", "the fields"),
1997 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1998 )
1999 },
2000 if *all_fields_are_private {
2001 "<field>".to_string()
2002 } else {
2003 match &private_fields[..] {
2004 [field] => format!("{field}"),
2005 _ => "<field>".to_string(),
2006 }
2007 },
2008 )
2009 )
2010 };
2011
2012 help
2013 }
2014 },
2015 StructFieldIsPrivate { field_name, struct_name, field_decl_span, struct_can_be_changed, usage_context } => Diagnostic {
2016 reason: Some(Reason::new(code(1), "Private struct field is inaccessible".to_string())),
2017 issue: Issue::error(
2018 source_engine,
2019 field_name.span(),
2020 format!("Private field \"{field_name}\" {}is inaccessible in this module.",
2021 match usage_context {
2022 StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => "".to_string(),
2023 StorageAccess | StructFieldAccess => format!("of the struct \"{struct_name}\" "),
2024 }
2025 )
2026 ),
2027 hints: vec![
2028 Hint::help(
2029 source_engine,
2030 field_name.span(),
2031 format!("Private fields can only be {} within the module in which their struct is declared.",
2032 match usage_context {
2033 StructInstantiation { .. } | StorageDeclaration { .. } => "initialized",
2034 StorageAccess | StructFieldAccess => "accessed",
2035 PatternMatching { .. } => "matched",
2036 }
2037 )
2038 ),
2039 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2040 Hint::help(
2041 source_engine,
2042 field_name.span(),
2043 "Otherwise, they must be ignored by ending the struct pattern with `..`.".to_string()
2044 )
2045 } else {
2046 Hint::none()
2047 },
2048 Hint::info(
2049 source_engine,
2050 field_decl_span.clone(),
2051 format!("Field \"{field_name}\" {}is declared here as private.",
2052 match usage_context {
2053 StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => format!("of the struct \"{struct_name}\" "),
2054 StorageAccess | StructFieldAccess => "".to_string(),
2055 }
2056 )
2057 ),
2058 ],
2059 help: vec![
2060 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2061 format!("Consider removing the field \"{field_name}\" from the struct pattern, and ending the pattern with `..`.")
2062 } else {
2063 Diagnostic::help_none()
2064 },
2065 if *struct_can_be_changed {
2066 match usage_context {
2067 StorageAccess | StructFieldAccess | PatternMatching { .. } => {
2068 format!("{} declaring the field \"{field_name}\" as public in \"{struct_name}\": `pub {field_name}: ...,`.",
2069 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2070 "Alternatively, consider"
2071 } else {
2072 "Consider"
2073 }
2074 )
2075 },
2076 _ => Diagnostic::help_none(),
2078 }
2079 } else {
2080 Diagnostic::help_none()
2081 },
2082 ],
2083 },
2084 StructFieldDoesNotExist { field_name, available_fields, is_public_struct_access, struct_name, struct_decl_span, struct_is_empty, usage_context } => Diagnostic {
2085 reason: Some(Reason::new(code(1), "Struct field does not exist".to_string())),
2086 issue: Issue::error(
2087 source_engine,
2088 field_name.span(),
2089 format!("Field \"{field_name}\" does not exist in the struct \"{struct_name}\".")
2090 ),
2091 hints: {
2092 let public = if *is_public_struct_access { "public " } else { "" };
2093
2094 let (hint, show_struct_decl) = if *struct_is_empty {
2095 (Some(format!("\"{struct_name}\" is an empty struct. It doesn't have any fields.")), false)
2096 }
2097 else if (matches!(usage_context, StorageAccess) && *is_public_struct_access && available_fields.is_empty())
2102 ||
2103 (matches!(usage_context, StructInstantiation { struct_can_be_instantiated: false } | StorageDeclaration { struct_can_be_instantiated: false })) {
2104 (None, false)
2110 } else if !available_fields.is_empty() {
2111 const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2113 match &available_fields[..] {
2114 [field] => (Some(format!("Only available {public}field is \"{field}\".")), false),
2115 _ => (Some(format!("Available {public}fields are {}.", sequence_to_str(available_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY))),
2116 available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2117 ),
2118 }
2119 }
2120 else {
2121 (None, false)
2122 };
2123
2124 let mut hints = vec![];
2125
2126 if let Some(hint) = hint {
2127 hints.push(Hint::help(source_engine, field_name.span(), hint));
2128 };
2129
2130 if show_struct_decl {
2131 hints.push(Hint::info(
2132 source_engine,
2133 struct_decl_span.clone(),
2134 format!("Struct \"{struct_name}\" is declared here, and has {} {public}fields.",
2135 num_to_str(available_fields.len())
2136 )
2137 ));
2138 }
2139
2140 hints
2141 },
2142 help: vec![],
2143 },
2144 StructFieldDuplicated { field_name, duplicate } => Diagnostic {
2145 reason: Some(Reason::new(code(1), "Struct field has multiple definitions".to_string())),
2146 issue: Issue::error(
2147 source_engine,
2148 field_name.span(),
2149 format!("Field \"{field_name}\" has multiple definitions.")
2150 ),
2151 hints: {
2152 vec![
2153 Hint::info(
2154 source_engine,
2155 duplicate.span(),
2156 "Field definition duplicated here.".into(),
2157 )
2158 ]
2159 },
2160 help: vec![],
2161 },
2162 NotIndexable { actually, span } => Diagnostic {
2163 reason: Some(Reason::new(code(1), "Type is not indexable".to_string())),
2164 issue: Issue::error(
2165 source_engine,
2166 span.clone(),
2167 format!("This expression has type \"{actually}\", which is not an indexable type.")
2168 ),
2169 hints: vec![],
2170 help: vec![
2171 "Index operator `[]` can be used only on indexable types.".to_string(),
2172 "In Sway, indexable types are:".to_string(),
2173 format!("{}- arrays. E.g., `[u64;3]`.", Indent::Single),
2174 format!("{}- references, direct or indirect, to arrays. E.g., `&[u64;3]` or `&&&[u64;3]`.", Indent::Single),
2175 ],
2176 },
2177 FieldAccessOnNonStruct { actually, storage_variable, field_name, span } => Diagnostic {
2178 reason: Some(Reason::new(code(1), "Field access requires a struct".to_string())),
2179 issue: Issue::error(
2180 source_engine,
2181 span.clone(),
2182 format!("{} has type \"{actually}\", which is not a struct{}.",
2183 if let Some(storage_variable) = storage_variable {
2184 format!("Storage variable \"{storage_variable}\"")
2185 } else {
2186 "This expression".to_string()
2187 },
2188 if storage_variable.is_some() {
2189 ""
2190 } else {
2191 " or a reference to a struct"
2192 }
2193 )
2194 ),
2195 hints: vec![
2196 Hint::info(
2197 source_engine,
2198 field_name.span(),
2199 format!("Field access happens here, on \"{field_name}\".")
2200 )
2201 ],
2202 help: if storage_variable.is_some() {
2203 vec![
2204 "Fields can only be accessed on storage variables that are structs.".to_string(),
2205 ]
2206 } else {
2207 vec![
2208 "In Sway, fields can be accessed on:".to_string(),
2209 format!("{}- structs. E.g., `my_struct.field`.", Indent::Single),
2210 format!("{}- references, direct or indirect, to structs. E.g., `(&my_struct).field` or `(&&&my_struct).field`.", Indent::Single),
2211 ]
2212 }
2213 },
2214 SymbolWithMultipleBindings { name, paths, span } => Diagnostic {
2215 reason: Some(Reason::new(code(1), "Multiple bindings exist for symbol in the scope".to_string())),
2216 issue: Issue::error(
2217 source_engine,
2218 span.clone(),
2219 format!("The following paths are all valid bindings for symbol \"{}\": {}.", name, sequence_to_str(&paths.iter().map(|path| format!("{path}::{name}")).collect::<Vec<_>>(), Enclosing::DoubleQuote, 2)),
2220 ),
2221 hints: vec![],
2222 help: vec![format!("Consider using a fully qualified name, e.g., `{}::{}`.", paths[0], name)],
2223 },
2224 StorageFieldDoesNotExist { field_name, available_fields, storage_decl_span } => Diagnostic {
2225 reason: Some(Reason::new(code(1), "Storage field does not exist".to_string())),
2226 issue: Issue::error(
2227 source_engine,
2228 field_name.span(),
2229 format!("Storage field \"{field_name}\" does not exist in the storage.")
2230 ),
2231 hints: {
2232 let (hint, show_storage_decl) = if available_fields.is_empty() {
2233 ("The storage is empty. It doesn't have any fields.".to_string(), false)
2234 } else {
2235 const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2236 let display_fields = available_fields.iter().map(|(path, field_name)| {
2237 let path = path.iter().map(ToString::to_string).collect::<Vec<_>>().join("::");
2238 if path.is_empty() {
2239 format!("storage.{field_name}")
2240 } else {
2241 format!("storage::{path}.{field_name}")
2242 }
2243 }).collect::<Vec<_>>();
2244 match &display_fields[..] {
2245 [field] => (format!("Only available storage field is \"{field}\"."), false),
2246 _ => (format!("Available storage fields are {}.", sequence_to_str(&display_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY)),
2247 available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2248 ),
2249 }
2250 };
2251
2252 let mut hints = vec![];
2253
2254 hints.push(Hint::help(source_engine, field_name.span(), hint));
2255
2256 if show_storage_decl {
2257 hints.push(Hint::info(
2258 source_engine,
2259 storage_decl_span.clone(),
2260 format!("Storage is declared here, and has {} fields.",
2261 num_to_str(available_fields.len())
2262 )
2263 ));
2264 }
2265
2266 hints
2267 },
2268 help: vec![],
2269 },
2270 TupleIndexOutOfBounds { index, count, tuple_type, span, prefix_span } => Diagnostic {
2271 reason: Some(Reason::new(code(1), "Tuple index is out of bounds".to_string())),
2272 issue: Issue::error(
2273 source_engine,
2274 span.clone(),
2275 format!("Tuple index {index} is out of bounds. The tuple has only {count} element{}.", plural_s(*count))
2276 ),
2277 hints: vec![
2278 Hint::info(
2279 source_engine,
2280 prefix_span.clone(),
2281 format!("This expression has type \"{tuple_type}\".")
2282 ),
2283 ],
2284 help: vec![],
2285 },
2286 TupleElementAccessOnNonTuple { actually, span, index, index_span } => Diagnostic {
2287 reason: Some(Reason::new(code(1), "Tuple element access requires a tuple".to_string())),
2288 issue: Issue::error(
2289 source_engine,
2290 span.clone(),
2291 format!("This expression has type \"{actually}\", which is not a tuple or a reference to a tuple.")
2292 ),
2293 hints: vec![
2294 Hint::info(
2295 source_engine,
2296 index_span.clone(),
2297 format!("Tuple element access happens here, on the index {index}.")
2298 )
2299 ],
2300 help: vec![
2301 "In Sway, tuple elements can be accessed on:".to_string(),
2302 format!("{}- tuples. E.g., `my_tuple.1`.", Indent::Single),
2303 format!("{}- references, direct or indirect, to tuples. E.g., `(&my_tuple).1` or `(&&&my_tuple).1`.", Indent::Single),
2304 ],
2305 },
2306 RefMutCannotReferenceConstant { constant, span } => Diagnostic {
2307 reason: Some(Reason::new(code(1), "References to mutable values cannot reference constants".to_string())),
2308 issue: Issue::error(
2309 source_engine,
2310 span.clone(),
2311 format!("\"{constant}\" is a constant. `&mut` cannot reference constants.")
2312 ),
2313 hints: vec![],
2314 help: vec![
2315 "Consider:".to_string(),
2316 format!("{}- taking a reference without `mut`: `&{constant}`.", Indent::Single),
2317 format!("{}- referencing a mutable copy of the constant, by returning it from a block: `&mut {{ {constant} }}`.", Indent::Single)
2318 ],
2319 },
2320 RefMutCannotReferenceImmutableVariable { decl_name, span } => Diagnostic {
2321 reason: Some(Reason::new(code(1), "References to mutable values cannot reference immutable variables".to_string())),
2322 issue: Issue::error(
2323 source_engine,
2324 span.clone(),
2325 format!("\"{decl_name}\" is an immutable variable. `&mut` cannot reference immutable variables.")
2326 ),
2327 hints: vec![
2328 Hint::info(
2329 source_engine,
2330 decl_name.span(),
2331 format!("Variable \"{decl_name}\" is declared here as immutable.")
2332 ),
2333 ],
2334 help: vec![
2335 "Consider:".to_string(),
2336 format!("{}- declaring \"{decl_name}\" as mutable.", Indent::Single),
2338 format!("{}- taking a reference without `mut`: `&{decl_name}`.", Indent::Single),
2339 format!("{}- referencing a mutable copy of \"{decl_name}\", by returning it from a block: `&mut {{ {decl_name} }}`.", Indent::Single)
2340 ],
2341 },
2342 ConflictingImplsForTraitAndType { trait_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => Diagnostic {
2343 reason: Some(Reason::new(code(1), "Trait is already implemented for type".to_string())),
2344 issue: Issue::error(
2345 source_engine,
2346 second_impl_span.clone(),
2347 if type_implementing_for == type_implementing_for_unaliased {
2348 format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\".")
2349 } else {
2350 format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").")
2351 }
2352 ),
2353 hints: vec![
2354 Hint::info(
2355 source_engine,
2356 existing_impl_span.clone(),
2357 if type_implementing_for == type_implementing_for_unaliased {
2358 format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\".",
2359 call_path_suffix_with_args(trait_name)
2360 )
2361 } else {
2362 format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").",
2363 call_path_suffix_with_args(trait_name)
2364 )
2365 }
2366 ),
2367 ],
2368 help: vec![
2369 "In Sway, there can be at most one implementation of a trait for any given type.".to_string(),
2370 "This property is called \"trait coherence\".".to_string(),
2371 ],
2372 },
2373 DuplicateDeclDefinedForType { decl_kind, decl_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => {
2374 let decl_kind_snake_case = sway_types::style::to_upper_camel_case(decl_kind);
2375 Diagnostic {
2376 reason: Some(Reason::new(code(1), "Type contains duplicate declarations".to_string())),
2377 issue: Issue::error(
2378 source_engine,
2379 second_impl_span.clone(),
2380 if type_implementing_for == type_implementing_for_unaliased {
2381 format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\".")
2382 } else {
2383 format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").")
2384 }
2385 ),
2386 hints: vec![
2387 Hint::info(
2388 source_engine,
2389 existing_impl_span.clone(),
2390 format!("\"{decl_name}\" previously defined here.")
2391 )
2392 ],
2393 help: vec![
2394 "A type may not contain two or more declarations of the same name".to_string(),
2395 ],
2396 }
2397 },
2398 MarkerTraitExplicitlyImplemented { marker_trait_full_name, span} => Diagnostic {
2399 reason: Some(Reason::new(code(1), "Marker traits cannot be explicitly implemented".to_string())),
2400 issue: Issue::error(
2401 source_engine,
2402 span.clone(),
2403 format!("Trait \"{marker_trait_full_name}\" is a marker trait and cannot be explicitly implemented.")
2404 ),
2405 hints: vec![],
2406 help: match marker_trait_name(marker_trait_full_name) {
2407 "Error" => vec![
2408 "\"Error\" marker trait is automatically implemented by the compiler for string slices".to_string(),
2409 "and enums annotated with the `#[error_type]` attribute.".to_string(),
2410 ],
2411 "Enum" => vec![
2412 "\"Enum\" marker trait is automatically implemented by the compiler for all enum types.".to_string(),
2413 ],
2414 _ => vec![],
2415 }
2416 },
2417 AssignmentToNonMutableVariable { lhs_span, decl_name } => Diagnostic {
2418 reason: Some(Reason::new(code(1), "Immutable variables cannot be assigned to".to_string())),
2419 issue: Issue::error(
2420 source_engine,
2421 lhs_span.clone(),
2422 format!("{} cannot be assigned to, because {} is an immutable variable.",
2426 if decl_name.as_str() == lhs_span.as_str() { format!("\"{decl_name}\"")
2428 } else {
2429 "This expression".to_string()
2430 },
2431 if decl_name.as_str() == lhs_span.as_str() {
2432 "it".to_string()
2433 } else {
2434 format!("\"{decl_name}\"")
2435 }
2436 )
2437 ),
2438 hints: vec![
2439 Hint::info(
2440 source_engine,
2441 decl_name.span(),
2442 format!("Variable \"{decl_name}\" is declared here as immutable.")
2443 ),
2444 ],
2445 help: vec![
2446 format!("Consider declaring \"{decl_name}\" as mutable."),
2448 ],
2449 },
2450 AssignmentToConstantOrConfigurable { lhs_span, is_configurable, decl_name } => Diagnostic {
2451 reason: Some(Reason::new(code(1), format!("{} cannot be assigned to",
2452 if *is_configurable {
2453 "Configurables"
2454 } else {
2455 "Constants"
2456 }
2457 ))),
2458 issue: Issue::error(
2459 source_engine,
2460 lhs_span.clone(),
2461 format!("{} cannot be assigned to, because {} is a {}.",
2465 if decl_name.as_str() == lhs_span.as_str() { format!("\"{decl_name}\"")
2467 } else {
2468 "This expression".to_string()
2469 },
2470 if decl_name.as_str() == lhs_span.as_str() {
2471 "it".to_string()
2472 } else {
2473 format!("\"{decl_name}\"")
2474 },
2475 if *is_configurable {
2476 "configurable"
2477 } else {
2478 "constant"
2479 }
2480 )
2481 ),
2482 hints: vec![
2483 Hint::info(
2484 source_engine,
2485 decl_name.span(),
2486 format!("{} \"{decl_name}\" is declared here.",
2487 if *is_configurable {
2488 "Configurable"
2489 } else {
2490 "Constant"
2491 }
2492 )
2493 ),
2494 ],
2495 help: vec![],
2496 },
2497 DeclAssignmentTargetCannotBeAssignedTo { decl_name, decl_friendly_type_name, lhs_span } => Diagnostic {
2498 reason: Some(Reason::new(code(1), "Assignment target cannot be assigned to".to_string())),
2499 issue: Issue::error(
2500 source_engine,
2501 lhs_span.clone(),
2502 format!("{} cannot be assigned to, because {} is {}{decl_friendly_type_name} and not a mutable variable.",
2506 match decl_name {
2507 Some(decl_name) if decl_name.as_str() == lhs_span.as_str() => format!("\"{decl_name}\""),
2509 _ => "This".to_string(),
2510 },
2511 match decl_name {
2512 Some(decl_name) if decl_name.as_str() == lhs_span.as_str() =>
2513 "it".to_string(),
2514 Some(decl_name) => format!("\"{}\"", decl_name.as_str()),
2515 _ => "it".to_string(),
2516 },
2517 a_or_an(decl_friendly_type_name)
2518 )
2519 ),
2520 hints: vec![
2521 match decl_name {
2522 Some(decl_name) => Hint::info(
2523 source_engine,
2524 decl_name.span(),
2525 format!("{} \"{decl_name}\" is declared here.", ascii_sentence_case(&decl_friendly_type_name.to_string()))
2526 ),
2527 _ => Hint::none(),
2528 }
2529 ],
2530 help: vec![],
2531 },
2532 AssignmentViaNonMutableReference { decl_reference_name, decl_reference_rhs, decl_reference_type, span } => Diagnostic {
2533 reason: Some(Reason::new(code(1), "Reference is not a reference to a mutable value (`&mut`)".to_string())),
2534 issue: Issue::error(
2535 source_engine,
2536 span.clone(),
2537 format!("{} is not a reference to a mutable value (`&mut`).",
2541 match decl_reference_name {
2542 Some(decl_reference_name) => format!("Reference \"{decl_reference_name}\""),
2543 _ => "This reference expression".to_string(),
2544 }
2545 )
2546 ),
2547 hints: vec![
2548 match decl_reference_name {
2549 Some(decl_reference_name) => Hint::info(
2550 source_engine,
2551 decl_reference_name.span(),
2552 format!("Reference \"{decl_reference_name}\" is declared here as a reference to immutable value.")
2553 ),
2554 _ => Hint::none(),
2555 },
2556 match decl_reference_rhs {
2557 Some(decl_reference_rhs) => Hint::info(
2558 source_engine,
2559 decl_reference_rhs.clone(),
2560 format!("This expression has type \"{decl_reference_type}\" instead of \"&mut {}\".",
2561 &decl_reference_type[1..]
2562 )
2563 ),
2564 _ => Hint::info(
2565 source_engine,
2566 span.clone(),
2567 format!("It has type \"{decl_reference_type}\" instead of \"&mut {}\".",
2568 &decl_reference_type[1..]
2569 )
2570 ),
2571 },
2572 match decl_reference_rhs {
2573 Some(decl_reference_rhs) if decl_reference_rhs.as_str().starts_with('&') => Hint::help(
2574 source_engine,
2575 decl_reference_rhs.clone(),
2576 format!("Consider taking here a reference to a mutable value: `&mut {}`.",
2577 first_line(decl_reference_rhs.as_str()[1..].trim(), true)
2578 )
2579 ),
2580 _ => Hint::none(),
2581 },
2582 ],
2583 help: vec![
2584 format!("{} dereferenced in assignment targets must {} references to mutable values (`&mut`).",
2585 if decl_reference_name.is_some() {
2586 "References"
2587 } else {
2588 "Reference expressions"
2589 },
2590 if decl_reference_name.is_some() {
2591 "be"
2592 } else {
2593 "result in"
2594 }
2595 ),
2596 ],
2597 },
2598 Unimplemented { feature, help, span } => Diagnostic {
2599 reason: Some(Reason::new(code(1), "Used feature is currently not implemented".to_string())),
2600 issue: Issue::error(
2601 source_engine,
2602 span.clone(),
2603 format!("{feature} is currently not implemented.")
2604 ),
2605 hints: vec![],
2606 help: help.clone(),
2607 },
2608 MatchedValueIsNotValid { supported_types_message, span } => Diagnostic {
2609 reason: Some(Reason::new(code(1), "Matched value is not valid".to_string())),
2610 issue: Issue::error(
2611 source_engine,
2612 span.clone(),
2613 "This cannot be matched.".to_string()
2614 ),
2615 hints: vec![],
2616 help: {
2617 let mut help = vec![];
2618
2619 help.push("Matched value must be an expression whose result is of one of the types supported in pattern matching.".to_string());
2620 help.push(Diagnostic::help_empty_line());
2621 for msg in supported_types_message {
2622 help.push(msg.to_string());
2623 }
2624
2625 help
2626 }
2627 },
2628 TypeIsNotValidAsImplementingFor { invalid_type, trait_name, span } => Diagnostic {
2629 reason: Some(Reason::new(code(1), "Self type of an impl block is not valid".to_string())),
2630 issue: Issue::error(
2631 source_engine,
2632 span.clone(),
2633 format!("{invalid_type} is not a valid type in the self type of {} impl block.",
2634 match trait_name {
2635 Some(_) => "a trait",
2636 None => "an",
2637 }
2638 )
2639 ),
2640 hints: vec![
2641 if matches!(invalid_type, InvalidImplementingForType::SelfType) {
2642 Hint::help(
2643 source_engine,
2644 span.clone(),
2645 format!("Replace {invalid_type} with the actual type that you want to implement for.")
2646 )
2647 } else {
2648 Hint::none()
2649 }
2650 ],
2651 help: {
2652 if matches!(invalid_type, InvalidImplementingForType::Placeholder) {
2653 vec![
2654 format!("Are you trying to implement {} for any type?",
2655 match trait_name {
2656 Some(trait_name) => format!("trait \"{trait_name}\""),
2657 None => "functionality".to_string(),
2658 }
2659 ),
2660 Diagnostic::help_empty_line(),
2661 "If so, use generic type parameters instead.".to_string(),
2662 "E.g., instead of:".to_string(),
2663 format!("{}impl {}_",
2672 Indent::Single,
2673 match trait_name {
2674 Some(_) => "SomeTrait for ",
2675 None => "",
2676 }
2677 ),
2678 "use:".to_string(),
2679 format!("{}impl<T> {}T",
2680 Indent::Single,
2681 match trait_name {
2682 Some(_) => "SomeTrait for ",
2683 None => "",
2684 }
2685 ),
2686 ]
2687 } else {
2688 vec![]
2689 }
2690 }
2691 },
2692 ModulePathIsNotAnExpression { module_path, span } => Diagnostic {
2693 reason: Some(Reason::new(code(1), "Module path is not an expression".to_string())),
2694 issue: Issue::error(
2695 source_engine,
2696 span.clone(),
2697 "This is a module path, and not an expression.".to_string()
2698 ),
2699 hints: vec![
2700 Hint::help(
2701 source_engine,
2702 span.clone(),
2703 "An expression is expected at this location, but a module path is found.".to_string()
2704 ),
2705 ],
2706 help: vec![
2707 "In expressions, module paths can only be used to fully qualify names with a path.".to_string(),
2708 format!("E.g., `{module_path}::SOME_CONSTANT` or `{module_path}::some_function()`."),
2709 ]
2710 },
2711 Parse { error } => {
2712 match &error.kind {
2713 ParseErrorKind::UnassignableExpression { erroneous_expression_kind, erroneous_expression_span } => Diagnostic {
2714 reason: Some(Reason::new(code(1), "Expression cannot be assigned to".to_string())),
2715 issue: Issue::error(
2720 source_engine,
2721 error.span.clone(),
2722 format!("This expression cannot be assigned to, because it {} {}{}.",
2723 if &error.span == erroneous_expression_span { "is"
2725 } else {
2726 "contains"
2727 },
2728 if *erroneous_expression_kind == "parentheses" {
2729 ""
2730 } else {
2731 a_or_an(erroneous_expression_kind)
2732 },
2733 erroneous_expression_kind
2734 )
2735 ),
2736 hints: vec![
2737 if &error.span != erroneous_expression_span {
2738 Hint::info(
2739 source_engine,
2740 erroneous_expression_span.clone(),
2741 format!("{} the contained {erroneous_expression_kind}.",
2742 if *erroneous_expression_kind == "parentheses" {
2743 "These are"
2744 } else {
2745 "This is"
2746 }
2747 )
2748 )
2749 } else {
2750 Hint::none()
2751 },
2752 ],
2753 help: vec![
2754 format!("{} cannot be {}an assignment target.",
2755 ascii_sentence_case(&erroneous_expression_kind.to_string()),
2756 if &error.span == erroneous_expression_span {
2757 ""
2758 } else {
2759 "a part of "
2760 }
2761 ),
2762 Diagnostic::help_empty_line(),
2763 "In Sway, assignment targets must be one of the following:".to_string(),
2764 format!("{}- Expressions starting with a mutable variable, optionally having", Indent::Single),
2765 format!("{} array or tuple element accesses, struct field accesses,", Indent::Single),
2766 format!("{} or arbitrary combinations of those.", Indent::Single),
2767 format!("{} E.g., `mut_var` or `mut_struct.field` or `mut_array[x + y].field.1`.", Indent::Single),
2768 Diagnostic::help_empty_line(),
2769 format!("{}- Dereferencing of an arbitrary expression that results", Indent::Single),
2770 format!("{} in a reference to a mutable value.", Indent::Single),
2771 format!("{} E.g., `*ref_to_mutable_value` or `*max_mut(&mut x, &mut y)`.", Indent::Single),
2772 ]
2773 },
2774 ParseErrorKind::UnrecognizedOpCode { known_op_codes } => Diagnostic {
2775 reason: Some(Reason::new(code(1), "Assembly instruction is unknown".to_string())),
2776 issue: Issue::error(
2777 source_engine,
2778 error.span.clone(),
2779 format!("\"{}\" is not a known assembly instruction.",
2780 error.span.as_str()
2781 )
2782 ),
2783 hints: vec![did_you_mean_help(source_engine, error.span.clone(), known_op_codes.iter(), 2, Enclosing::DoubleQuote)],
2784 help: vec![]
2785 },
2786 _ => Diagnostic {
2787 issue: Issue::error(source_engine, self.span(), format!("{}", self)),
2791 ..Default::default()
2792 },
2793 }
2794 },
2795 ConvertParseTree { error } => {
2796 match error {
2797 ConvertParseTreeError::InvalidAttributeTarget { span, attribute, target_friendly_name, can_only_annotate_help } => Diagnostic {
2798 reason: Some(Reason::new(code(1), match get_attribute_type(attribute) {
2799 AttributeType::InnerDocComment => "Inner doc comment (`//!`) cannot document item",
2800 AttributeType::OuterDocComment => "Outer doc comment (`///`) cannot document item",
2801 AttributeType::Attribute => "Attribute cannot annotate item",
2802 }.to_string())),
2803 issue: Issue::error(
2804 source_engine,
2805 span.clone(),
2806 match get_attribute_type(attribute) {
2807 AttributeType::InnerDocComment => format!("Inner doc comment (`//!`) cannot document {}{target_friendly_name}.", a_or_an(&target_friendly_name)),
2808 AttributeType::OuterDocComment => format!("Outer doc comment (`///`) cannot document {}{target_friendly_name}.", a_or_an(&target_friendly_name)),
2809 AttributeType::Attribute => format!("\"{attribute}\" attribute cannot annotate {}{target_friendly_name}.", a_or_an(&target_friendly_name)),
2810 }.to_string()
2811 ),
2812 hints: vec![],
2813 help: can_only_annotate_help.iter().map(|help| help.to_string()).collect(),
2814 },
2815 ConvertParseTreeError::InvalidAttributeMultiplicity { last_occurrence, previous_occurrences } => Diagnostic {
2816 reason: Some(Reason::new(code(1), "Attribute can be applied only once".to_string())),
2817 issue: Issue::error(
2818 source_engine,
2819 last_occurrence.span(),
2820 format!("\"{last_occurrence}\" attribute can be applied only once, but is applied {} times.", num_to_str(previous_occurrences.len() + 1))
2821 ),
2822 hints: {
2823 let (first_occurrence, other_occurrences) = previous_occurrences.split_first().expect("there is at least one previous occurrence in `previous_occurrences`");
2824 let mut hints = vec![Hint::info(source_engine, first_occurrence.span(), "It is already applied here.".to_string())];
2825 other_occurrences.iter().for_each(|occurrence| hints.push(Hint::info(source_engine, occurrence.span(), "And here.".to_string())));
2826 hints
2827 },
2828 help: vec![],
2829 },
2830 ConvertParseTreeError::InvalidAttributeArgsMultiplicity { span, attribute, args_multiplicity, num_of_args } => Diagnostic {
2831 reason: Some(Reason::new(code(1), "Number of attribute arguments is invalid".to_string())),
2832 issue: Issue::error(
2833 source_engine,
2834 span.clone(),
2835 format!("\"{attribute}\" attribute must {}, but has {}.", get_expected_attributes_args_multiplicity_msg(args_multiplicity), num_to_str_or_none(*num_of_args))
2836 ),
2837 hints: vec![],
2838 help: vec![],
2839 },
2840 ConvertParseTreeError::InvalidAttributeArg { attribute, arg, expected_args } => Diagnostic {
2841 reason: Some(Reason::new(code(1), "Attribute argument is invalid".to_string())),
2842 issue: Issue::error(
2843 source_engine,
2844 arg.span(),
2845 format!("\"{arg}\" is an invalid argument for attribute \"{attribute}\".")
2846 ),
2847 hints: {
2848 let mut hints = vec![did_you_mean_help(source_engine, arg.span(), expected_args, 2, Enclosing::DoubleQuote)];
2849 if expected_args.len() == 1 {
2850 hints.push(Hint::help(source_engine, arg.span(), format!("The only valid argument is \"{}\".", expected_args[0])));
2851 } else if expected_args.len() <= 3 {
2852 hints.push(Hint::help(source_engine, arg.span(), format!("Valid arguments are {}.", sequence_to_str(expected_args, Enclosing::DoubleQuote, usize::MAX))));
2853 } else {
2854 hints.push(Hint::help(source_engine, arg.span(), "Valid arguments are:".to_string()));
2855 hints.append(&mut Hint::multi_help(source_engine, &arg.span(), sequence_to_list(expected_args, Indent::Single, usize::MAX)))
2856 }
2857 hints
2858 },
2859 help: vec![],
2860 },
2861 ConvertParseTreeError::InvalidAttributeArgExpectsValue { attribute, arg, value_span } => Diagnostic {
2862 reason: Some(Reason::new(code(1), format!("Attribute argument must {}have a value",
2863 match value_span {
2864 Some(_) => "not ",
2865 None => "",
2866 }
2867 ))),
2868 issue: Issue::error(
2869 source_engine,
2870 arg.span(),
2871 format!("\"{arg}\" argument of the attribute \"{attribute}\" must {}have a value.",
2872 match value_span {
2873 Some(_) => "not ",
2874 None => "",
2875 }
2876 )
2877 ),
2878 hints: vec![
2879 match &value_span {
2880 Some(value_span) => Hint::help(source_engine, value_span.clone(), format!("Remove the value: `= {}`.", value_span.as_str())),
2881 None => Hint::help(source_engine, arg.span(), format!("To set the value, use the `=` operator: `{arg} = <value>`.")),
2882 }
2883 ],
2884 help: vec![],
2885 },
2886 ConvertParseTreeError::InvalidAttributeArgValueType { span, arg, expected_type, received_type } => Diagnostic {
2887 reason: Some(Reason::new(code(1), "Attribute argument value has a wrong type".to_string())),
2888 issue: Issue::error(
2889 source_engine,
2890 span.clone(),
2891 format!("\"{arg}\" argument must have a value of type \"{expected_type}\".")
2892 ),
2893 hints: vec![
2894 Hint::help(
2895 source_engine,
2896 span.clone(),
2897 format!("This value has type \"{received_type}\"."),
2898 )
2899 ],
2900 help: vec![],
2901 },
2902 ConvertParseTreeError::InvalidAttributeArgValue { span, arg, expected_values } => Diagnostic {
2903 reason: Some(Reason::new(code(1), "Attribute argument value is invalid".to_string())),
2904 issue: Issue::error(
2905 source_engine,
2906 span.clone(),
2907 format!("\"{}\" is an invalid value for argument \"{arg}\".", span.as_str())
2908 ),
2909 hints: {
2910 let mut hints = vec![did_you_mean_help(source_engine, span.clone(), expected_values, 2, Enclosing::DoubleQuote)];
2911 if expected_values.len() == 1 {
2912 hints.push(Hint::help(source_engine, span.clone(), format!("The only valid argument value is \"{}\".", expected_values[0])));
2913 } else if expected_values.len() <= 3 {
2914 hints.push(Hint::help(source_engine, span.clone(), format!("Valid argument values are {}.", sequence_to_str(expected_values, Enclosing::DoubleQuote, usize::MAX))));
2915 } else {
2916 hints.push(Hint::help(source_engine, span.clone(), "Valid argument values are:".to_string()));
2917 hints.append(&mut Hint::multi_help(source_engine, span, sequence_to_list(expected_values, Indent::Single, usize::MAX)))
2918 }
2919 hints
2920 },
2921 help: vec![],
2922 },
2923 _ => Diagnostic {
2924 issue: Issue::error(source_engine, self.span(), format!("{}", self)),
2928 ..Default::default()
2929 },
2930 }
2931 }
2932 ConfigurableMissingAbiDecodeInPlace { span } => Diagnostic {
2933 reason: Some(Reason::new(code(1), "Configurables need a function named \"abi_decode_in_place\" to be in scope".to_string())),
2934 issue: Issue::error(
2935 source_engine,
2936 span.clone(),
2937 String::new()
2938 ),
2939 hints: vec![],
2940 help: vec![
2941 "The function \"abi_decode_in_place\" is usually defined in the standard library module \"std::codec\".".into(),
2942 "Verify that you are using a version of the \"std\" standard library that contains this function.".into(),
2943 ],
2944 },
2945 StorageAccessMismatched { span, is_pure, suggested_attributes, storage_access_violations } => Diagnostic {
2946 reason: Some(Reason::new(code(1), format!("{} function cannot {} storage",
2950 if *is_pure {
2951 "Pure"
2952 } else {
2953 "Storage read-only"
2954 },
2955 if *is_pure {
2956 "access"
2957 } else {
2958 "write to"
2959 }
2960 ))),
2961 issue: Issue::error(
2962 source_engine,
2963 span.clone(),
2964 format!("Function \"{}\" is {} and cannot {} storage.",
2965 span.as_str(),
2966 if *is_pure {
2967 "pure"
2968 } else {
2969 "declared as `#[storage(read)]`"
2970 },
2971 if *is_pure {
2972 "access"
2973 } else {
2974 "write to"
2975 },
2976 )
2977 ),
2978 hints: storage_access_violations
2979 .iter()
2980 .map(|(span, storage_access)| Hint::info(
2981 source_engine,
2982 span.clone(),
2983 format!("{storage_access}")
2984 ))
2985 .collect(),
2986 help: vec![
2987 format!("Consider declaring the function \"{}\" as `#[storage({suggested_attributes})]`,",
2988 span.as_str()
2989 ),
2990 format!("or removing the {} from the function body.",
2991 if *is_pure {
2992 "storage access code".to_string()
2993 } else {
2994 format!("storage write{}", plural_s(storage_access_violations.len()))
2995 }
2996 ),
2997 ],
2998 },
2999 MultipleImplsSatisfyingTraitForType { span, type_annotation , trait_names, trait_types_and_names: trait_types_and_spans } => Diagnostic {
3000 reason: Some(Reason::new(code(1), format!("Multiple impls satisfying {} for {}", trait_names.join("+"), type_annotation))),
3001 issue: Issue::error(
3002 source_engine,
3003 span.clone(),
3004 String::new()
3005 ),
3006 hints: vec![],
3007 help: vec![format!("Trait{} implemented for types:\n{}", if trait_names.len() > 1 {"s"} else {""}, trait_types_and_spans.iter().enumerate().map(|(e, (type_id, name))|
3008 format!("#{} {} for {}", e, name, type_id.clone())
3009 ).collect::<Vec<_>>().join("\n"))],
3010 },
3011 MultipleContractsMethodsWithTheSameName { spans } => Diagnostic {
3012 reason: Some(Reason::new(code(1), "Multiple contracts methods with the same name.".into())),
3013 issue: Issue::error(
3014 source_engine,
3015 spans[0].clone(),
3016 "This is the first method".into()
3017 ),
3018 hints: spans.iter().skip(1).map(|span| {
3019 Hint::error(source_engine, span.clone(), "This is the duplicated method.".into())
3020 }).collect(),
3021 help: vec!["Contract methods names must be unique, even when implementing multiple ABIs.".into()],
3022 },
3023 FunctionSelectorClash { method_name, span, other_method_name, other_span } => Diagnostic {
3024 reason: Some(Reason::new(code(1), format!("Methods {method_name} and {other_method_name} have clashing function selectors."))),
3025 issue: Issue::error(
3026 source_engine,
3027 span.clone(),
3028 String::new()
3029 ),
3030 hints: vec![Hint::error(source_engine, other_span.clone(), format!("The declaration of {other_method_name} is here"))],
3031 help: vec![format!("The methods of a contract must have distinct function selectors, which are computed from the method hash. \nRenaming one of the methods should solve the problem")]
3032 },
3033 ErrorTypeEnumHasNonErrorVariants { enum_name, non_error_variants } => Diagnostic {
3034 reason: Some(Reason::new(code(1), "Error type enum cannot have non-error variants".to_string())),
3035 issue: Issue::error(
3036 source_engine,
3037 enum_name.span(),
3038 format!("Error type enum \"{enum_name}\" has non-error variant{} {}.",
3039 plural_s(non_error_variants.len()),
3040 sequence_to_str(non_error_variants, Enclosing::DoubleQuote, 2)
3041 )
3042 ),
3043 hints: non_error_variants.iter().map(|variant| Hint::underscored_info(source_engine, variant.span())).collect(),
3044 help: vec![
3045 "All error type enum's variants must be marked as errors.".to_string(),
3046 "To mark error variants as errors, annotate them with the `#[error]` attribute.".to_string(),
3047 ]
3048 },
3049 ErrorAttributeInNonErrorEnum { enum_name, enum_variant_name } => Diagnostic {
3050 reason: Some(Reason::new(code(1), "Error enum variants must be in error type enums".to_string())),
3051 issue: Issue::error(
3052 source_engine,
3053 enum_variant_name.span(),
3054 format!("Enum variant \"{enum_variant_name}\" is marked as `#[error]`, but its enum is not an error type enum.")
3055 ),
3056 hints: vec![
3057 Hint::help(
3058 source_engine,
3059 enum_name.span(),
3060 format!("Consider annotating \"{enum_name}\" enum with the `#[error_type]` attribute."),
3061 )
3062 ],
3063 help: vec![
3064 "Enum variants can be marked as `#[error]` only if their parent enum is annotated with the `#[error_type]` attribute.".to_string(),
3065 ]
3066 },
3067 _ => Diagnostic {
3068 issue: Issue::error(source_engine, self.span(), format!("{}", self)),
3072 ..Default::default()
3073 }
3074 }
3075 }
3076}
3077
3078#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
3079pub enum TypeNotAllowedReason {
3080 #[error(
3081 "Returning a type containing `raw_slice` from `main()` is not allowed. \
3082 Consider converting it into a flat `raw_slice` first."
3083 )]
3084 NestedSliceReturnNotAllowedInMain,
3085
3086 #[error("The type \"{ty}\" is not allowed in storage.")]
3087 TypeNotAllowedInContractStorage { ty: String },
3088
3089 #[error("`str` or a type containing `str` on `main()` arguments is not allowed.")]
3090 StringSliceInMainParameters,
3091
3092 #[error("Returning `str` or a type containing `str` from `main()` is not allowed.")]
3093 StringSliceInMainReturn,
3094
3095 #[error("`str` or a type containing `str` on `configurables` is not allowed.")]
3096 StringSliceInConfigurables,
3097
3098 #[error("`str` or a type containing `str` on `const` is not allowed.")]
3099 StringSliceInConst,
3100
3101 #[error("slices or types containing slices on `const` are not allowed.")]
3102 SliceInConst,
3103
3104 #[error("references, pointers, slices, string slices or types containing any of these are not allowed.")]
3105 NotAllowedInTransmute,
3106}
3107
3108#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3109pub enum StructFieldUsageContext {
3110 StructInstantiation { struct_can_be_instantiated: bool },
3111 StorageDeclaration { struct_can_be_instantiated: bool },
3112 StorageAccess,
3113 PatternMatching { has_rest_pattern: bool },
3114 StructFieldAccess,
3115 }
3120
3121#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3122pub enum InvalidImplementingForType {
3123 SelfType,
3124 Placeholder,
3125 Other,
3126}
3127
3128impl fmt::Display for InvalidImplementingForType {
3129 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3130 match self {
3131 Self::SelfType => f.write_str("\"Self\""),
3132 Self::Placeholder => f.write_str("Placeholder `_`"),
3133 Self::Other => f.write_str("This"),
3134 }
3135 }
3136}
3137
3138#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3140pub enum ShadowingSource {
3141 Const,
3143 LetVar,
3145 PatternMatchingStructFieldVar,
3148}
3149
3150impl fmt::Display for ShadowingSource {
3151 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3152 match self {
3153 Self::Const => f.write_str("Constant"),
3154 Self::LetVar => f.write_str("Variable"),
3155 Self::PatternMatchingStructFieldVar => f.write_str("Pattern variable"),
3156 }
3157 }
3158}
3159
3160#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3164pub enum StorageAccess {
3165 Clear,
3166 ReadWord,
3167 ReadSlots,
3168 WriteWord,
3169 WriteSlots,
3170 ImpureFunctionCall(Span, bool, bool),
3174}
3175
3176impl StorageAccess {
3177 pub fn is_write(&self) -> bool {
3178 matches!(
3179 self,
3180 Self::Clear | Self::WriteWord | Self::WriteSlots | Self::ImpureFunctionCall(_, _, true)
3181 )
3182 }
3183}
3184
3185impl fmt::Display for StorageAccess {
3186 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3187 match self {
3188 Self::Clear => f.write_str("Clearing the storage happens here."),
3189 Self::ReadWord => f.write_str("Reading a word from the storage happens here."),
3190 Self::ReadSlots => f.write_str("Reading storage slots happens here."),
3191 Self::WriteWord => f.write_str("Writing a word to the storage happens here."),
3192 Self::WriteSlots => f.write_str("Writing to storage slots happens here."),
3193 Self::ImpureFunctionCall(call_path, reads, writes) => f.write_fmt(format_args!(
3194 "Function \"{}\" {} the storage.",
3195 call_path_suffix_with_args(&call_path.as_str().to_string()),
3196 match (reads, writes) {
3197 (true, true) => "reads from and writes to",
3198 (true, false) => "reads from",
3199 (false, true) => "writes to",
3200 (false, false) => unreachable!(
3201 "Function \"{}\" is impure, so it must read from or write to the storage.",
3202 call_path.as_str()
3203 ),
3204 }
3205 )),
3206 }
3207 }
3208}
3209
3210fn marker_trait_name(marker_trait_full_name: &str) -> &str {
3218 const MARKER_TRAITS_MODULE: &str = "std::marker::";
3219 assert!(
3220 marker_trait_full_name.starts_with(MARKER_TRAITS_MODULE),
3221 "`marker_trait_full_name` must start with \"std::marker::\", but it was \"{}\"",
3222 marker_trait_full_name
3223 );
3224
3225 let lower_boundary = MARKER_TRAITS_MODULE.len();
3226 let name_part = &marker_trait_full_name[lower_boundary..];
3227
3228 let upper_boundary = marker_trait_full_name.len() - lower_boundary;
3229 let only_name_len = std::cmp::min(
3230 name_part.find(':').unwrap_or(upper_boundary),
3231 name_part.find('<').unwrap_or(upper_boundary),
3232 );
3233 let upper_boundary = lower_boundary + only_name_len;
3234
3235 &marker_trait_full_name[lower_boundary..upper_boundary]
3236}