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("This expression has type \"{argument_type}\", which does not implement \"std::marker::Error\". Panic expression arguments must implement \"Error\".")]
1079 PanicExpressionArgumentIsNotError { argument_type: String, span: Span },
1080 #[error("Incoherent impl was found due to breaking orphan rule check.")]
1081 IncoherentImplDueToOrphanRule { span: Span },
1082}
1083
1084impl std::convert::From<TypeError> for CompileError {
1085 fn from(other: TypeError) -> CompileError {
1086 CompileError::TypeError(other)
1087 }
1088}
1089
1090impl Spanned for CompileError {
1091 fn span(&self) -> Span {
1092 use CompileError::*;
1093 match self {
1094 ConstGenericNotSupportedHere { span } => span.clone(),
1095 LengthExpressionNotSupported { span } => span.clone(),
1096 FeatureIsDisabled { span, .. } => span.clone(),
1097 ModuleDepGraphEvaluationError { .. } => Span::dummy(),
1098 ModuleDepGraphCyclicReference { .. } => Span::dummy(),
1099 UnknownVariable { span, .. } => span.clone(),
1100 NotAVariable { span, .. } => span.clone(),
1101 Unimplemented { span, .. } => span.clone(),
1102 TypeError(err) => err.span(),
1103 ParseError { span, .. } => span.clone(),
1104 Internal(_, span) => span.clone(),
1105 InternalOwned(_, span) => span.clone(),
1106 NoPredicateMainFunction(span) => span.clone(),
1107 PredicateMainDoesNotReturnBool(span) => span.clone(),
1108 NoScriptMainFunction(span) => span.clone(),
1109 MultipleDefinitionsOfFunction { span, .. } => span.clone(),
1110 MultipleDefinitionsOfName { span, .. } => span.clone(),
1111 MultipleDefinitionsOfConstant { span, .. } => span.clone(),
1112 MultipleDefinitionsOfType { span, .. } => span.clone(),
1113 MultipleDefinitionsOfMatchArmVariable { duplicate, .. } => duplicate.clone(),
1114 MultipleDefinitionsOfFallbackFunction { span, .. } => span.clone(),
1115 AssignmentToNonMutableVariable { lhs_span, .. } => lhs_span.clone(),
1116 AssignmentToConstantOrConfigurable { lhs_span, .. } => lhs_span.clone(),
1117 DeclAssignmentTargetCannotBeAssignedTo { lhs_span, .. } => lhs_span.clone(),
1118 AssignmentViaNonMutableReference { span, .. } => span.clone(),
1119 MutableParameterNotSupported { span, .. } => span.clone(),
1120 ImmutableArgumentToMutableParameter { span } => span.clone(),
1121 RefMutableNotAllowedInContractAbi { span, .. } => span.clone(),
1122 RefMutCannotReferenceConstant { span, .. } => span.clone(),
1123 RefMutCannotReferenceImmutableVariable { span, .. } => span.clone(),
1124 MethodRequiresMutableSelf { span, .. } => span.clone(),
1125 AssociatedFunctionCalledAsMethod { span, .. } => span.clone(),
1126 TypeParameterNotInTypeScope { span, .. } => span.clone(),
1127 MismatchedTypeInInterfaceSurface { span, .. } => span.clone(),
1128 UnknownTrait { span, .. } => span.clone(),
1129 FunctionNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1130 ConstantNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1131 TypeNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1132 MissingInterfaceSurfaceConstants { span, .. } => span.clone(),
1133 MissingInterfaceSurfaceTypes { span, .. } => span.clone(),
1134 MissingInterfaceSurfaceMethods { span, .. } => span.clone(),
1135 IncorrectNumberOfTypeArguments { span, .. } => span.clone(),
1136 DoesNotTakeTypeArguments { span, .. } => span.clone(),
1137 DoesNotTakeTypeArgumentsAsPrefix { span, .. } => span.clone(),
1138 TypeArgumentsNotAllowed { span } => span.clone(),
1139 NeedsTypeArguments { span, .. } => span.clone(),
1140 StructInstantiationMissingFieldForErrorRecovery { span, .. } => span.clone(),
1141 StructInstantiationMissingFields { span, .. } => span.clone(),
1142 StructCannotBeInstantiated { span, .. } => span.clone(),
1143 StructFieldIsPrivate { field_name, .. } => field_name.span(),
1144 StructFieldDoesNotExist { field_name, .. } => field_name.span(),
1145 StructFieldDuplicated { field_name, .. } => field_name.span(),
1146 MethodNotFound { span, .. } => span.clone(),
1147 ModuleNotFound { span, .. } => span.clone(),
1148 TupleElementAccessOnNonTuple { span, .. } => span.clone(),
1149 NotAStruct { span, .. } => span.clone(),
1150 NotIndexable { span, .. } => span.clone(),
1151 FieldAccessOnNonStruct { span, .. } => span.clone(),
1152 SymbolNotFound { span, .. } => span.clone(),
1153 SymbolWithMultipleBindings { span, .. } => span.clone(),
1154 ImportPrivateSymbol { span, .. } => span.clone(),
1155 ImportPrivateModule { span, .. } => span.clone(),
1156 NoElseBranch { span, .. } => span.clone(),
1157 NotAType { span, .. } => span.clone(),
1158 MissingEnumInstantiator { span, .. } => span.clone(),
1159 PathDoesNotReturn { span, .. } => span.clone(),
1160 UnknownRegister { span, .. } => span.clone(),
1161 MissingImmediate { span, .. } => span.clone(),
1162 InvalidImmediateValue { span, .. } => span.clone(),
1163 UnknownEnumVariant { span, .. } => span.clone(),
1164 UnrecognizedOp { span, .. } => span.clone(),
1165 UnableToInferGeneric { span, .. } => span.clone(),
1166 UnconstrainedGenericParameter { span, .. } => span.clone(),
1167 TraitConstraintNotSatisfied { span, .. } => span.clone(),
1168 TraitConstraintMissing { span, .. } => span.clone(),
1169 Immediate06TooLarge { span, .. } => span.clone(),
1170 Immediate12TooLarge { span, .. } => span.clone(),
1171 Immediate18TooLarge { span, .. } => span.clone(),
1172 Immediate24TooLarge { span, .. } => span.clone(),
1173 IncorrectNumberOfAsmRegisters { span, .. } => span.clone(),
1174 UnnecessaryImmediate { span, .. } => span.clone(),
1175 AmbiguousPath { span } => span.clone(),
1176 ModulePathIsNotAnExpression { span, .. } => span.clone(),
1177 UnknownType { span, .. } => span.clone(),
1178 UnknownTypeName { span, .. } => span.clone(),
1179 FileCouldNotBeRead { span, .. } => span.clone(),
1180 ImportMustBeLibrary { span, .. } => span.clone(),
1181 MoreThanOneEnumInstantiator { span, .. } => span.clone(),
1182 UnnecessaryEnumInstantiator { span, .. } => span.clone(),
1183 UnitVariantWithParenthesesEnumInstantiator { span, .. } => span.clone(),
1184 TraitNotFound { span, .. } => span.clone(),
1185 TraitNotImportedAtFunctionApplication {
1186 function_call_site_span,
1187 ..
1188 } => function_call_site_span.clone(),
1189 InvalidExpressionOnLhs { span, .. } => span.clone(),
1190 TooManyArgumentsForFunction { span, .. } => span.clone(),
1191 TooFewArgumentsForFunction { span, .. } => span.clone(),
1192 MissingParenthesesForFunction { span, .. } => span.clone(),
1193 InvalidAbiType { span, .. } => span.clone(),
1194 NotAnAbi { span, .. } => span.clone(),
1195 ImplAbiForNonContract { span, .. } => span.clone(),
1196 ConflictingImplsForTraitAndType {
1197 second_impl_span, ..
1198 } => second_impl_span.clone(),
1199 MarkerTraitExplicitlyImplemented { span, .. } => span.clone(),
1200 DuplicateDeclDefinedForType {
1201 second_impl_span, ..
1202 } => second_impl_span.clone(),
1203 IncorrectNumberOfInterfaceSurfaceFunctionParameters { span, .. } => span.clone(),
1204 ArgumentParameterTypeMismatch { span, .. } => span.clone(),
1205 RecursiveCall { span, .. } => span.clone(),
1206 RecursiveCallChain { span, .. } => span.clone(),
1207 RecursiveType { span, .. } => span.clone(),
1208 RecursiveTypeChain { span, .. } => span.clone(),
1209 GMFromExternalContext { span, .. } => span.clone(),
1210 MintFromExternalContext { span, .. } => span.clone(),
1211 BurnFromExternalContext { span, .. } => span.clone(),
1212 ContractStorageFromExternalContext { span, .. } => span.clone(),
1213 InvalidOpcodeFromPredicate { span, .. } => span.clone(),
1214 ArrayOutOfBounds { span, .. } => span.clone(),
1215 ConstantRequiresExpression { span, .. } => span.clone(),
1216 ConstantsCannotBeShadowed { name, .. } => name.span(),
1217 ConfigurablesCannotBeShadowed { name, .. } => name.span(),
1218 ConfigurablesCannotBeMatchedAgainst { name, .. } => name.span(),
1219 ConstantShadowsVariable { name, .. } => name.span(),
1220 ConstantDuplicatesConstantOrConfigurable { name, .. } => name.span(),
1221 ShadowsOtherSymbol { name } => name.span(),
1222 GenericShadowsGeneric { name } => name.span(),
1223 MatchExpressionNonExhaustive { span, .. } => span.clone(),
1224 MatchStructPatternMissingFields { span, .. } => span.clone(),
1225 MatchStructPatternMustIgnorePrivateFields { span, .. } => span.clone(),
1226 MatchArmVariableNotDefinedInAllAlternatives { variable, .. } => variable.span(),
1227 MatchArmVariableMismatchedType { variable, .. } => variable.span(),
1228 MatchedValueIsNotValid { span, .. } => span.clone(),
1229 NotAnEnum { span, .. } => span.clone(),
1230 TraitDeclPureImplImpure { span, .. } => span.clone(),
1231 TraitImplPurityMismatch { span, .. } => span.clone(),
1232 DeclIsNotAnEnum { span, .. } => span.clone(),
1233 DeclIsNotAStruct { span, .. } => span.clone(),
1234 DeclIsNotAFunction { span, .. } => span.clone(),
1235 DeclIsNotAVariable { span, .. } => span.clone(),
1236 DeclIsNotAnAbi { span, .. } => span.clone(),
1237 DeclIsNotATrait { span, .. } => span.clone(),
1238 DeclIsNotAnImplTrait { span, .. } => span.clone(),
1239 DeclIsNotATraitFn { span, .. } => span.clone(),
1240 DeclIsNotStorage { span, .. } => span.clone(),
1241 DeclIsNotAConstant { span, .. } => span.clone(),
1242 DeclIsNotATypeAlias { span, .. } => span.clone(),
1243 ImpureInNonContract { span, .. } => span.clone(),
1244 StorageAccessMismatched { span, .. } => span.clone(),
1245 ParameterRefMutabilityMismatch { span, .. } => span.clone(),
1246 IntegerTooLarge { span, .. } => span.clone(),
1247 IntegerTooSmall { span, .. } => span.clone(),
1248 IntegerContainsInvalidDigit { span, .. } => span.clone(),
1249 AbiAsSupertrait { span, .. } => span.clone(),
1250 SupertraitImplRequired { span, .. } => span.clone(),
1251 ContractCallParamRepeated { span, .. } => span.clone(),
1252 UnrecognizedContractParam { span, .. } => span.clone(),
1253 CallParamForNonContractCallMethod { span, .. } => span.clone(),
1254 StorageFieldDoesNotExist { field_name, .. } => field_name.span(),
1255 InvalidStorageOnlyTypeDecl { span, .. } => span.clone(),
1256 NoDeclaredStorage { span, .. } => span.clone(),
1257 MultipleStorageDeclarations { span, .. } => span.clone(),
1258 UnexpectedDeclaration { span, .. } => span.clone(),
1259 ContractAddressMustBeKnown { span, .. } => span.clone(),
1260 ConvertParseTree { error } => error.span(),
1261 Lex { error } => error.span(),
1262 Parse { error } => error.span.clone(),
1263 EnumNotFound { span, .. } => span.clone(),
1264 TupleIndexOutOfBounds { span, .. } => span.clone(),
1265 NonConstantDeclValue { span, .. } => span.clone(),
1266 StorageDeclarationInNonContract { span, .. } => span.clone(),
1267 IntrinsicUnsupportedArgType { span, .. } => span.clone(),
1268 IntrinsicIncorrectNumArgs { span, .. } => span.clone(),
1269 IntrinsicIncorrectNumTArgs { span, .. } => span.clone(),
1270 BreakOutsideLoop { span } => span.clone(),
1271 ContinueOutsideLoop { span } => span.clone(),
1272 ContractIdValueNotALiteral { span } => span.clone(),
1273 RefMutableNotAllowedInMain { span, .. } => span.clone(),
1274 InitializedRegisterReassignment { span, .. } => span.clone(),
1275 DisallowedControlFlowInstruction { span, .. } => span.clone(),
1276 CallingPrivateLibraryMethod { span, .. } => span.clone(),
1277 DisallowedIntrinsicInPredicate { span, .. } => span.clone(),
1278 CoinsPassedToNonPayableMethod { span, .. } => span.clone(),
1279 TraitImplPayabilityMismatch { span, .. } => span.clone(),
1280 ConfigurableInLibrary { span } => span.clone(),
1281 MultipleApplicableItemsInScope { span, .. } => span.clone(),
1282 NonStrGenericType { span } => span.clone(),
1283 CannotBeEvaluatedToConst { span } => span.clone(),
1284 ContractCallsItsOwnMethod { span } => span.clone(),
1285 AbiShadowsSuperAbiMethod { span, .. } => span.clone(),
1286 ConflictingSuperAbiMethods { span, .. } => span.clone(),
1287 AssociatedTypeNotSupportedInAbi { span, .. } => span.clone(),
1288 AbiSupertraitMethodCallAsContractCall { span, .. } => span.clone(),
1289 FunctionSelectorClash { span, .. } => span.clone(),
1290 TypeNotAllowed { span, .. } => span.clone(),
1291 ExpectedStringLiteral { span } => span.clone(),
1292 TypeIsNotValidAsImplementingFor { span, .. } => span.clone(),
1293 UninitRegisterInAsmBlockBeingRead { span } => span.clone(),
1294 ExpressionCannotBeDereferenced { span, .. } => span.clone(),
1295 FallbackFnsAreContractOnly { span } => span.clone(),
1296 FallbackFnsCannotHaveParameters { span } => span.clone(),
1297 CouldNotGenerateEntry { span } => span.clone(),
1298 CouldNotGenerateEntryMissingStd { span } => span.clone(),
1299 CouldNotGenerateEntryMissingImpl { span, .. } => span.clone(),
1300 CannotBeEvaluatedToConfigurableSizeUnknown { span } => span.clone(),
1301 EncodingUnsupportedType { span } => span.clone(),
1302 ConfigurableMissingAbiDecodeInPlace { span } => span.clone(),
1303 ABIHashCollision { span, .. } => span.clone(),
1304 InvalidRangeEndGreaterThanStart { span, .. } => span.clone(),
1305 TypeMustBeKnownAtThisPoint { span, .. } => span.clone(),
1306 MultipleImplsSatisfyingTraitForType { span, .. } => span.clone(),
1307 MultipleContractsMethodsWithTheSameName { spans } => spans[0].clone(),
1308 ErrorTypeEnumHasNonErrorVariants { enum_name, .. } => enum_name.span(),
1309 ErrorAttributeInNonErrorEnum {
1310 enum_variant_name, ..
1311 } => enum_variant_name.span(),
1312 PanicExpressionArgumentIsNotError { span, .. } => span.clone(),
1313 IncoherentImplDueToOrphanRule { span, .. } => span.clone(),
1314 }
1315 }
1316}
1317
1318impl ToDiagnostic for CompileError {
1330 fn to_diagnostic(&self, source_engine: &SourceEngine) -> Diagnostic {
1331 let code = Code::semantic_analysis;
1332 use CompileError::*;
1333 match self {
1334 ConstantsCannotBeShadowed { shadowing_source, name, constant_span, constant_decl_span, is_alias } => Diagnostic {
1335 reason: Some(Reason::new(code(1), "Constants cannot be shadowed".to_string())),
1336 issue: Issue::error(
1337 source_engine,
1338 name.span(),
1339 format!(
1340 "{shadowing_source} \"{name}\" shadows {}constant of the same name.",
1346 if constant_decl_span.clone() != Span::dummy() { "imported " } else { "" }
1347 )
1348 ),
1349 hints: vec![
1350 Hint::info(
1351 source_engine,
1352 constant_span.clone(),
1353 format!(
1354 "Shadowed constant \"{name}\" {} here{}.",
1360 if constant_decl_span.clone() != Span::dummy() { "gets imported" } else { "is declared" },
1361 if *is_alias { " as alias" } else { "" }
1362 )
1363 ),
1364 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1365 Hint::help(
1366 source_engine,
1367 name.span(),
1368 format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1369 )
1370 } else {
1371 Hint::none()
1372 },
1373 Hint::info( source_engine,
1375 constant_decl_span.clone(),
1376 format!("This is the original declaration of the imported constant \"{name}\".")
1377 ),
1378 ],
1379 help: vec![
1380 "Unlike variables, constants cannot be shadowed by other constants or variables.".to_string(),
1381 match (shadowing_source, *constant_decl_span != Span::dummy()) {
1382 (LetVar | PatternMatchingStructFieldVar, false) => format!("Consider renaming either the {} \"{name}\" or the constant \"{name}\".",
1383 format!("{shadowing_source}").to_lowercase(),
1384 ),
1385 (Const, false) => "Consider renaming one of the constants.".to_string(),
1386 (shadowing_source, true) => format!(
1387 "Consider renaming the {} \"{name}\" or using {} for the imported constant.",
1388 format!("{shadowing_source}").to_lowercase(),
1389 if *is_alias { "a different alias" } else { "an alias" }
1390 ),
1391 },
1392 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1393 format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1394 } else {
1395 Diagnostic::help_none()
1396 }
1397 ],
1398 },
1399 ConfigurablesCannotBeShadowed { shadowing_source, name, configurable_span } => Diagnostic {
1400 reason: Some(Reason::new(code(1), "Configurables cannot be shadowed".to_string())),
1401 issue: Issue::error(
1402 source_engine,
1403 name.span(),
1404 format!("{shadowing_source} \"{name}\" shadows configurable of the same name.")
1405 ),
1406 hints: vec![
1407 Hint::info(
1408 source_engine,
1409 configurable_span.clone(),
1410 format!("Shadowed configurable \"{name}\" is declared here.")
1411 ),
1412 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1413 Hint::help(
1414 source_engine,
1415 name.span(),
1416 format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1417 )
1418 } else {
1419 Hint::none()
1420 },
1421 ],
1422 help: vec![
1423 "Unlike variables, configurables cannot be shadowed by constants or variables.".to_string(),
1424 format!(
1425 "Consider renaming either the {} \"{name}\" or the configurable \"{name}\".",
1426 format!("{shadowing_source}").to_lowercase()
1427 ),
1428 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1429 format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1430 } else {
1431 Diagnostic::help_none()
1432 }
1433 ],
1434 },
1435 ConfigurablesCannotBeMatchedAgainst { name, configurable_span } => Diagnostic {
1436 reason: Some(Reason::new(code(1), "Configurables cannot be matched against".to_string())),
1437 issue: Issue::error(
1438 source_engine,
1439 name.span(),
1440 format!("\"{name}\" is a configurable and configurables cannot be matched against.")
1441 ),
1442 hints: {
1443 let mut hints = vec![
1444 Hint::info(
1445 source_engine,
1446 configurable_span.clone(),
1447 format!("Configurable \"{name}\" is declared here.")
1448 ),
1449 ];
1450
1451 hints.append(&mut Hint::multi_help(source_engine, &name.span(), vec![
1452 format!("Are you trying to define a pattern variable named \"{name}\"?"),
1453 format!("In that case, use some other name for the pattern variable,"),
1454 format!("or consider renaming the configurable \"{name}\"."),
1455 ]));
1456
1457 hints
1458 },
1459 help: vec![
1460 "Unlike constants, configurables cannot be matched against in pattern matching.".to_string(),
1461 "That's not possible, because patterns to match against must be compile-time constants.".to_string(),
1462 "Configurables are run-time constants. Their values are defined during the deployment.".to_string(),
1463 Diagnostic::help_empty_line(),
1464 "To test against a configurable, consider:".to_string(),
1465 format!("{}- replacing the `match` expression with `if-else`s altogether.", Indent::Single),
1466 format!("{}- matching against a variable and comparing that variable afterwards with the configurable.", Indent::Single),
1467 format!("{} E.g., instead of:", Indent::Single),
1468 Diagnostic::help_empty_line(),
1469 format!("{} SomeStruct {{ x: A_CONFIGURABLE, y: 42 }} => {{", Indent::Double),
1470 format!("{} do_something();", Indent::Double),
1471 format!("{} }}", Indent::Double),
1472 Diagnostic::help_empty_line(),
1473 format!("{} to have:", Indent::Single),
1474 Diagnostic::help_empty_line(),
1475 format!("{} SomeStruct {{ x, y: 42 }} => {{", Indent::Double),
1476 format!("{} if x == A_CONFIGURABLE {{", Indent::Double),
1477 format!("{} do_something();", Indent::Double),
1478 format!("{} }}", Indent::Double),
1479 format!("{} }}", Indent::Double),
1480 ],
1481 },
1482 ConstantShadowsVariable { name , variable_span } => Diagnostic {
1483 reason: Some(Reason::new(code(1), "Constants cannot shadow variables".to_string())),
1484 issue: Issue::error(
1485 source_engine,
1486 name.span(),
1487 format!("Constant \"{name}\" shadows variable of the same name.")
1488 ),
1489 hints: vec![
1490 Hint::info(
1491 source_engine,
1492 variable_span.clone(),
1493 format!("This is the shadowed variable \"{name}\".")
1494 ),
1495 ],
1496 help: vec![
1497 format!("Variables can shadow other variables, but constants cannot."),
1498 format!("Consider renaming either the variable or the constant."),
1499 ],
1500 },
1501 ConstantDuplicatesConstantOrConfigurable { existing_constant_or_configurable, new_constant_or_configurable, name, existing_span } => Diagnostic {
1502 reason: Some(Reason::new(code(1), match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1503 ("Constant", "Constant") => "Constant of the same name already exists".to_string(),
1504 ("Constant", "Configurable") => "Constant of the same name as configurable already exists".to_string(),
1505 ("Configurable", "Constant") => "Configurable of the same name as constant already exists".to_string(),
1506 _ => unreachable!("We can have only the listed combinations. Configurable duplicating configurable is not a valid combination.")
1507 })),
1508 issue: Issue::error(
1509 source_engine,
1510 name.span(),
1511 format!("{new_constant_or_configurable} \"{name}\" has the same name as an already declared {}.",
1512 existing_constant_or_configurable.to_lowercase()
1513 )
1514 ),
1515 hints: vec![
1516 Hint::info(
1517 source_engine,
1518 existing_span.clone(),
1519 format!("{existing_constant_or_configurable} \"{name}\" is {}declared here.",
1520 if existing_constant_or_configurable == new_constant_or_configurable {
1522 "already "
1523 } else {
1524 ""
1525 }
1526 )
1527 ),
1528 ],
1529 help: vec![
1530 match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1531 ("Constant", "Constant") => "Consider renaming one of the constants, or in case of imported constants, using an alias.".to_string(),
1532 _ => "Consider renaming either the configurable or the constant, or in case of an imported constant, using an alias.".to_string(),
1533 },
1534 ],
1535 },
1536 MultipleDefinitionsOfMatchArmVariable { match_value, match_type, first_definition, first_definition_is_struct_field, duplicate, duplicate_is_struct_field } => Diagnostic {
1537 reason: Some(Reason::new(code(1), "Match pattern variable is already defined".to_string())),
1538 issue: Issue::error(
1539 source_engine,
1540 duplicate.clone(),
1541 format!("Variable \"{}\" is already defined in this match arm.", first_definition.as_str())
1542 ),
1543 hints: vec![
1544 Hint::help(
1545 source_engine,
1546 if *duplicate_is_struct_field {
1547 duplicate.clone()
1548 }
1549 else {
1550 Span::dummy()
1551 },
1552 format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str())
1553 ),
1554 Hint::info(
1555 source_engine,
1556 first_definition.clone(),
1557 format!(
1558 "This {}is the first definition of the variable \"{}\".",
1559 if *first_definition_is_struct_field {
1560 format!("struct field \"{}\" ", first_definition.as_str())
1561 }
1562 else {
1563 "".to_string()
1564 },
1565 first_definition.as_str(),
1566 )
1567 ),
1568 Hint::help(
1569 source_engine,
1570 if *first_definition_is_struct_field && !*duplicate_is_struct_field {
1571 first_definition.clone()
1572 }
1573 else {
1574 Span::dummy()
1575 },
1576 format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str()),
1577 ),
1578 Hint::info(
1579 source_engine,
1580 match_value.clone(),
1581 format!("The expression to match on is of type \"{match_type}\".")
1582 ),
1583 ],
1584 help: vec![
1585 format!("Variables used in match arm patterns must be unique within a pattern, except in alternatives."),
1586 match (*first_definition_is_struct_field, *duplicate_is_struct_field) {
1587 (true, true) => format!("Consider declaring a variable with different name for either of the fields. E.g., `{0}: var_{0}`.", first_definition.as_str()),
1588 (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()),
1589 (false, false) => "Consider renaming either of the variables.".to_string(),
1590 },
1591 ],
1592 },
1593 MatchArmVariableMismatchedType { match_value, match_type, variable, first_definition, expected, received } => Diagnostic {
1594 reason: Some(Reason::new(code(1), "Match pattern variable has mismatched type".to_string())),
1595 issue: Issue::error(
1596 source_engine,
1597 variable.span(),
1598 format!("Variable \"{variable}\" is expected to be of type \"{expected}\", but is \"{received}\".")
1599 ),
1600 hints: vec![
1601 Hint::info(
1602 source_engine,
1603 first_definition.clone(),
1604 format!("\"{variable}\" is first defined here with type \"{expected}\".")
1605 ),
1606 Hint::info(
1607 source_engine,
1608 match_value.clone(),
1609 format!("The expression to match on is of type \"{match_type}\".")
1610 ),
1611 ],
1612 help: vec![
1613 format!("In the same match arm, a variable must have the same type in all alternatives."),
1614 ],
1615 },
1616 MatchArmVariableNotDefinedInAllAlternatives { match_value, match_type, variable, missing_in_alternatives} => Diagnostic {
1617 reason: Some(Reason::new(code(1), "Match pattern variable is not defined in all alternatives".to_string())),
1618 issue: Issue::error(
1619 source_engine,
1620 variable.span(),
1621 format!("Variable \"{variable}\" is not defined in all alternatives.")
1622 ),
1623 hints: {
1624 let mut hints = vec![
1625 Hint::info(
1626 source_engine,
1627 match_value.clone(),
1628 format!("The expression to match on is of type \"{match_type}\".")
1629 ),
1630 ];
1631
1632 for (i, alternative) in missing_in_alternatives.iter().enumerate() {
1633 hints.push(
1634 Hint::info(
1635 source_engine,
1636 alternative.clone(),
1637 format!("\"{variable}\" is {}missing in this alternative.", if i != 0 { "also " } else { "" }),
1638 )
1639 )
1640 }
1641
1642 hints
1643 },
1644 help: vec![
1645 format!("Consider removing the variable \"{variable}\" altogether, or adding it to all alternatives."),
1646 ],
1647 },
1648 MatchStructPatternMissingFields { missing_fields, missing_fields_are_public, struct_name, struct_decl_span, total_number_of_fields, span } => Diagnostic {
1649 reason: Some(Reason::new(code(1), "Struct pattern has missing fields".to_string())),
1650 issue: Issue::error(
1651 source_engine,
1652 span.clone(),
1653 format!("Struct pattern is missing the {}field{} {}.",
1654 if *missing_fields_are_public { "public " } else { "" },
1655 plural_s(missing_fields.len()),
1656 sequence_to_str(missing_fields, Enclosing::DoubleQuote, 2)
1657 )
1658 ),
1659 hints: vec![
1660 Hint::help(
1661 source_engine,
1662 span.clone(),
1663 "Struct pattern must either contain or ignore each struct field.".to_string()
1664 ),
1665 Hint::info(
1666 source_engine,
1667 struct_decl_span.clone(),
1668 format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1669 num_to_str(*total_number_of_fields),
1670 plural_s(*total_number_of_fields),
1671 )
1672 ),
1673 ],
1674 help: vec![
1675 format!("Consider ignoring {} field{} {}by using the `_` pattern{} `{}: _`.",
1679 singular_plural(missing_fields.len(), "the", "individual"),
1680 plural_s(missing_fields.len()),
1681 singular_plural(missing_fields.len(), &format!("\"{}\" ", missing_fields[0]), ""),
1682 singular_plural(missing_fields.len(), ":", ". E.g.,"),
1683 missing_fields[0]
1684 ),
1685 "Alternatively, consider ignoring all the missing fields by ending the struct pattern with `..`.".to_string(),
1686 ],
1687 },
1688 MatchStructPatternMustIgnorePrivateFields { private_fields, struct_name, struct_decl_span, all_fields_are_private, span } => Diagnostic {
1689 reason: Some(Reason::new(code(1), "Struct pattern must ignore inaccessible private fields".to_string())),
1690 issue: Issue::error(
1691 source_engine,
1692 span.clone(),
1693 format!("Struct pattern must ignore inaccessible private field{} {}.",
1694 plural_s(private_fields.len()),
1695 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1696 )
1697 ),
1698 hints: vec![
1699 Hint::help(
1700 source_engine,
1701 span.clone(),
1702 format!("To ignore the private field{}, end the struct pattern with `..`.",
1703 plural_s(private_fields.len()),
1704 )
1705 ),
1706 Hint::info(
1707 source_engine,
1708 struct_decl_span.clone(),
1709 format!("Struct \"{struct_name}\" is declared here, and has {}.",
1710 if *all_fields_are_private {
1711 "all private fields".to_string()
1712 } else {
1713 format!("private field{} {}",
1714 plural_s(private_fields.len()),
1715 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1716 )
1717 }
1718 )
1719 ),
1720 ],
1721 help: vec![],
1722 },
1723 TraitNotImportedAtFunctionApplication { trait_name, function_name, function_call_site_span, trait_constraint_span, trait_candidates } => {
1724 let mut trait_candidates = trait_candidates.clone();
1726 trait_candidates.sort();
1727 let trait_candidates = &trait_candidates; Diagnostic {
1730 reason: Some(Reason::new(code(1), "Trait is not imported".to_string())),
1731 issue: Issue::error(
1732 source_engine,
1733 function_call_site_span.clone(),
1734 format!(
1735 "Trait \"{trait_name}\" is not imported {}when calling \"{function_name}\".",
1736 get_file_name(source_engine, function_call_site_span.source_id())
1737 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1738 )
1739 ),
1740 hints: {
1741 let mut hints = vec![
1742 Hint::help(
1743 source_engine,
1744 function_call_site_span.clone(),
1745 format!("This import is needed because \"{function_name}\" requires \"{trait_name}\" in one of its trait constraints.")
1746 ),
1747 Hint::info(
1748 source_engine,
1749 trait_constraint_span.clone(),
1750 format!("In the definition of \"{function_name}\", \"{trait_name}\" is used in this trait constraint.")
1751 ),
1752 ];
1753
1754 match trait_candidates.len() {
1755 0 => (),
1760 1 => hints.push(Hint::help(
1762 source_engine,
1763 function_call_site_span.clone(),
1764 format!(
1765 "Import the \"{trait_name}\" trait {}by using: `use {};`.",
1766 get_file_name(source_engine, function_call_site_span.source_id())
1767 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" ")),
1768 trait_candidates[0]
1769 )
1770 )),
1771 _ => hints.push(Hint::help(
1773 source_engine,
1774 function_call_site_span.clone(),
1775 format!(
1776 "To import the proper \"{trait_name}\" {}follow the detailed instructions given below.",
1777 get_file_name(source_engine, function_call_site_span.source_id())
1778 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1779 )
1780 )),
1781 }
1782
1783 hints
1784 },
1785 help: {
1786 let mut help = vec![];
1787
1788 if trait_candidates.len() > 1 {
1789 help.push(format!("There are these {} traits with the name \"{trait_name}\" available in the modules:", num_to_str(trait_candidates.len())));
1790 for trait_candidate in trait_candidates.iter() {
1791 help.push(format!("{}- {trait_candidate}", Indent::Single));
1792 }
1793 help.push("To import the proper one follow these steps:".to_string());
1794 help.push(format!(
1795 "{}1. Look at the definition of the \"{function_name}\"{}.",
1796 Indent::Single,
1797 get_file_name(source_engine, trait_constraint_span.source_id())
1798 .map_or("".to_string(), |file_name| format!(" in the \"{file_name}\""))
1799 ));
1800 help.push(format!(
1801 "{}2. Detect which exact \"{trait_name}\" is used in the trait constraint in the \"{function_name}\".",
1802 Indent::Single
1803 ));
1804 help.push(format!(
1805 "{}3. Import that \"{trait_name}\"{}.",
1806 Indent::Single,
1807 get_file_name(source_engine, function_call_site_span.source_id())
1808 .map_or("".to_string(), |file_name| format!(" into \"{file_name}\""))
1809 ));
1810 help.push(format!("{} E.g., assuming it is the first one on the list, use: `use {};`", Indent::Double, trait_candidates[0]));
1811 }
1812
1813 help
1814 },
1815 }
1816 },
1817 ExpressionCannotBeDereferenced { expression_type, span } => Diagnostic {
1819 reason: Some(Reason::new(code(1), "Expression cannot be dereferenced".to_string())),
1820 issue: Issue::error(
1821 source_engine,
1822 span.clone(),
1823 format!("This expression cannot be dereferenced, because it is of type \"{expression_type}\", which is not a reference type.")
1824 ),
1825 hints: vec![
1826 Hint::help(
1827 source_engine,
1828 span.clone(),
1829 "In Sway, only references can be dereferenced.".to_string()
1830 ),
1831 Hint::help(
1832 source_engine,
1833 span.clone(),
1834 "Are you missing the reference operator `&` somewhere in the code?".to_string()
1835 ),
1836 ],
1837 help: vec![],
1838 },
1839 StructInstantiationMissingFields { field_names, struct_name, span, struct_decl_span, total_number_of_fields } => Diagnostic {
1840 reason: Some(Reason::new(code(1), "Struct instantiation has missing fields".to_string())),
1841 issue: Issue::error(
1842 source_engine,
1843 span.clone(),
1844 format!("Instantiation of the struct \"{struct_name}\" is missing the field{} {}.",
1845 plural_s(field_names.len()),
1846 sequence_to_str(field_names, Enclosing::DoubleQuote, 2)
1847 )
1848 ),
1849 hints: vec![
1850 Hint::help(
1851 source_engine,
1852 span.clone(),
1853 "Struct instantiation must initialize all the fields of the struct.".to_string()
1854 ),
1855 Hint::info(
1856 source_engine,
1857 struct_decl_span.clone(),
1858 format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1859 num_to_str(*total_number_of_fields),
1860 plural_s(*total_number_of_fields),
1861 )
1862 ),
1863 ],
1864 help: vec![],
1865 },
1866 StructCannotBeInstantiated { struct_name, span, struct_decl_span, private_fields, constructors, all_fields_are_private, is_in_storage_declaration, struct_can_be_changed } => Diagnostic {
1867 reason: Some(Reason::new(code(1), "Struct cannot be instantiated due to inaccessible private fields".to_string())),
1868 issue: Issue::error(
1869 source_engine,
1870 span.clone(),
1871 format!("\"{struct_name}\" cannot be {}instantiated in this {}, due to {}inaccessible private field{}.",
1872 if *is_in_storage_declaration { "" } else { "directly " },
1873 if *is_in_storage_declaration { "storage declaration" } else { "module" },
1874 singular_plural(private_fields.len(), "an ", ""),
1875 plural_s(private_fields.len())
1876 )
1877 ),
1878 hints: vec![
1879 Hint::help(
1880 source_engine,
1881 span.clone(),
1882 format!("Inaccessible field{} {} {}.",
1883 plural_s(private_fields.len()),
1884 is_are(private_fields.len()),
1885 sequence_to_str(private_fields, Enclosing::DoubleQuote, 5)
1886 )
1887 ),
1888 Hint::help(
1889 source_engine,
1890 span.clone(),
1891 if *is_in_storage_declaration {
1892 "Structs with private fields can be instantiated in storage declarations only if they are declared in the same module as the storage.".to_string()
1893 } else {
1894 "Structs with private fields can be instantiated only within the module in which they are declared.".to_string()
1895 }
1896 ),
1897 if *is_in_storage_declaration {
1898 Hint::help(
1899 source_engine,
1900 span.clone(),
1901 "They can still be initialized in storage declarations if they have public constructors that evaluate to a constant.".to_string()
1902 )
1903 } else {
1904 Hint::none()
1905 },
1906 if *is_in_storage_declaration {
1907 Hint::help(
1908 source_engine,
1909 span.clone(),
1910 "They can always be stored in storage by using the `read` and `write` functions provided in the `std::storage::storage_api`.".to_string()
1911 )
1912 } else {
1913 Hint::none()
1914 },
1915 if !*is_in_storage_declaration && !constructors.is_empty() {
1916 Hint::help(
1917 source_engine,
1918 span.clone(),
1919 format!("\"{struct_name}\" can be instantiated via public constructors suggested below.")
1920 )
1921 } else {
1922 Hint::none()
1923 },
1924 Hint::info(
1925 source_engine,
1926 struct_decl_span.clone(),
1927 format!("Struct \"{struct_name}\" is declared here, and has {}.",
1928 if *all_fields_are_private {
1929 "all private fields".to_string()
1930 } else {
1931 format!("private field{} {}",
1932 plural_s(private_fields.len()),
1933 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1934 )
1935 }
1936 )
1937 ),
1938 ],
1939 help: {
1940 let mut help = vec![];
1941
1942 if *is_in_storage_declaration {
1943 help.push(format!("Consider initializing \"{struct_name}\" by finding an available constructor that evaluates to a constant{}.",
1944 if *struct_can_be_changed {
1945 ", or implement a new one"
1946 } else {
1947 ""
1948 }
1949 ));
1950
1951 if !constructors.is_empty() {
1952 help.push("Check these already available constructors. They might evaluate to a constant:".to_string());
1953 for constructor in sequence_to_list(constructors, Indent::Single, usize::MAX) {
1955 help.push(constructor);
1956 }
1957 };
1958
1959 help.push(Diagnostic::help_empty_line());
1960
1961 help.push(format!("Or you can always store instances of \"{struct_name}\" in the contract storage, by using the `std::storage::storage_api`:"));
1962 help.push(format!("{}use std::storage::storage_api::{{read, write}};", Indent::Single));
1963 help.push(format!("{}write(STORAGE_KEY, 0, my_{});", Indent::Single, to_snake_case(struct_name.as_str())));
1964 help.push(format!("{}let my_{}_option = read::<{struct_name}>(STORAGE_KEY, 0);", Indent::Single, to_snake_case(struct_name.as_str())));
1965 }
1966 else if !constructors.is_empty() {
1967 help.push(format!("Consider instantiating \"{struct_name}\" by using one of the available constructors{}:",
1968 if *struct_can_be_changed {
1969 ", or implement a new one"
1970 } else {
1971 ""
1972 }
1973 ));
1974 for constructor in sequence_to_list(constructors, Indent::Single, 5) {
1975 help.push(constructor);
1976 }
1977 }
1978
1979 if *struct_can_be_changed {
1980 if *is_in_storage_declaration || !constructors.is_empty() {
1981 help.push(Diagnostic::help_empty_line());
1982 }
1983
1984 if !*is_in_storage_declaration && constructors.is_empty() {
1985 help.push(format!("Consider implementing a public constructor for \"{struct_name}\"."));
1986 };
1987
1988 help.push(
1989 format!("Alternatively, consider declaring {} as public in \"{struct_name}\": `pub {}: ...,`.",
1995 if *all_fields_are_private {
1996 "all fields".to_string()
1997 } else {
1998 format!("{} {}",
1999 singular_plural(private_fields.len(), "the field", "the fields"),
2000 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
2001 )
2002 },
2003 if *all_fields_are_private {
2004 "<field>".to_string()
2005 } else {
2006 match &private_fields[..] {
2007 [field] => format!("{field}"),
2008 _ => "<field>".to_string(),
2009 }
2010 },
2011 )
2012 )
2013 };
2014
2015 help
2016 }
2017 },
2018 StructFieldIsPrivate { field_name, struct_name, field_decl_span, struct_can_be_changed, usage_context } => Diagnostic {
2019 reason: Some(Reason::new(code(1), "Private struct field is inaccessible".to_string())),
2020 issue: Issue::error(
2021 source_engine,
2022 field_name.span(),
2023 format!("Private field \"{field_name}\" {}is inaccessible in this module.",
2024 match usage_context {
2025 StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => "".to_string(),
2026 StorageAccess | StructFieldAccess => format!("of the struct \"{struct_name}\" "),
2027 }
2028 )
2029 ),
2030 hints: vec![
2031 Hint::help(
2032 source_engine,
2033 field_name.span(),
2034 format!("Private fields can only be {} within the module in which their struct is declared.",
2035 match usage_context {
2036 StructInstantiation { .. } | StorageDeclaration { .. } => "initialized",
2037 StorageAccess | StructFieldAccess => "accessed",
2038 PatternMatching { .. } => "matched",
2039 }
2040 )
2041 ),
2042 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2043 Hint::help(
2044 source_engine,
2045 field_name.span(),
2046 "Otherwise, they must be ignored by ending the struct pattern with `..`.".to_string()
2047 )
2048 } else {
2049 Hint::none()
2050 },
2051 Hint::info(
2052 source_engine,
2053 field_decl_span.clone(),
2054 format!("Field \"{field_name}\" {}is declared here as private.",
2055 match usage_context {
2056 StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => format!("of the struct \"{struct_name}\" "),
2057 StorageAccess | StructFieldAccess => "".to_string(),
2058 }
2059 )
2060 ),
2061 ],
2062 help: vec![
2063 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2064 format!("Consider removing the field \"{field_name}\" from the struct pattern, and ending the pattern with `..`.")
2065 } else {
2066 Diagnostic::help_none()
2067 },
2068 if *struct_can_be_changed {
2069 match usage_context {
2070 StorageAccess | StructFieldAccess | PatternMatching { .. } => {
2071 format!("{} declaring the field \"{field_name}\" as public in \"{struct_name}\": `pub {field_name}: ...,`.",
2072 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2073 "Alternatively, consider"
2074 } else {
2075 "Consider"
2076 }
2077 )
2078 },
2079 _ => Diagnostic::help_none(),
2081 }
2082 } else {
2083 Diagnostic::help_none()
2084 },
2085 ],
2086 },
2087 StructFieldDoesNotExist { field_name, available_fields, is_public_struct_access, struct_name, struct_decl_span, struct_is_empty, usage_context } => Diagnostic {
2088 reason: Some(Reason::new(code(1), "Struct field does not exist".to_string())),
2089 issue: Issue::error(
2090 source_engine,
2091 field_name.span(),
2092 format!("Field \"{field_name}\" does not exist in the struct \"{struct_name}\".")
2093 ),
2094 hints: {
2095 let public = if *is_public_struct_access { "public " } else { "" };
2096
2097 let (hint, show_struct_decl) = if *struct_is_empty {
2098 (Some(format!("\"{struct_name}\" is an empty struct. It doesn't have any fields.")), false)
2099 }
2100 else if (matches!(usage_context, StorageAccess) && *is_public_struct_access && available_fields.is_empty())
2105 ||
2106 (matches!(usage_context, StructInstantiation { struct_can_be_instantiated: false } | StorageDeclaration { struct_can_be_instantiated: false })) {
2107 (None, false)
2113 } else if !available_fields.is_empty() {
2114 const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2116 match &available_fields[..] {
2117 [field] => (Some(format!("Only available {public}field is \"{field}\".")), false),
2118 _ => (Some(format!("Available {public}fields are {}.", sequence_to_str(available_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY))),
2119 available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2120 ),
2121 }
2122 }
2123 else {
2124 (None, false)
2125 };
2126
2127 let mut hints = vec![];
2128
2129 if let Some(hint) = hint {
2130 hints.push(Hint::help(source_engine, field_name.span(), hint));
2131 };
2132
2133 if show_struct_decl {
2134 hints.push(Hint::info(
2135 source_engine,
2136 struct_decl_span.clone(),
2137 format!("Struct \"{struct_name}\" is declared here, and has {} {public}fields.",
2138 num_to_str(available_fields.len())
2139 )
2140 ));
2141 }
2142
2143 hints
2144 },
2145 help: vec![],
2146 },
2147 StructFieldDuplicated { field_name, duplicate } => Diagnostic {
2148 reason: Some(Reason::new(code(1), "Struct field has multiple definitions".to_string())),
2149 issue: Issue::error(
2150 source_engine,
2151 field_name.span(),
2152 format!("Field \"{field_name}\" has multiple definitions.")
2153 ),
2154 hints: {
2155 vec![
2156 Hint::info(
2157 source_engine,
2158 duplicate.span(),
2159 "Field definition duplicated here.".into(),
2160 )
2161 ]
2162 },
2163 help: vec![],
2164 },
2165 NotIndexable { actually, span } => Diagnostic {
2166 reason: Some(Reason::new(code(1), "Type is not indexable".to_string())),
2167 issue: Issue::error(
2168 source_engine,
2169 span.clone(),
2170 format!("This expression has type \"{actually}\", which is not an indexable type.")
2171 ),
2172 hints: vec![],
2173 help: vec![
2174 "Index operator `[]` can be used only on indexable types.".to_string(),
2175 "In Sway, indexable types are:".to_string(),
2176 format!("{}- arrays. E.g., `[u64;3]`.", Indent::Single),
2177 format!("{}- references, direct or indirect, to arrays. E.g., `&[u64;3]` or `&&&[u64;3]`.", Indent::Single),
2178 ],
2179 },
2180 FieldAccessOnNonStruct { actually, storage_variable, field_name, span } => Diagnostic {
2181 reason: Some(Reason::new(code(1), "Field access requires a struct".to_string())),
2182 issue: Issue::error(
2183 source_engine,
2184 span.clone(),
2185 format!("{} has type \"{actually}\", which is not a struct{}.",
2186 if let Some(storage_variable) = storage_variable {
2187 format!("Storage variable \"{storage_variable}\"")
2188 } else {
2189 "This expression".to_string()
2190 },
2191 if storage_variable.is_some() {
2192 ""
2193 } else {
2194 " or a reference to a struct"
2195 }
2196 )
2197 ),
2198 hints: vec![
2199 Hint::info(
2200 source_engine,
2201 field_name.span(),
2202 format!("Field access happens here, on \"{field_name}\".")
2203 )
2204 ],
2205 help: if storage_variable.is_some() {
2206 vec![
2207 "Fields can only be accessed on storage variables that are structs.".to_string(),
2208 ]
2209 } else {
2210 vec![
2211 "In Sway, fields can be accessed on:".to_string(),
2212 format!("{}- structs. E.g., `my_struct.field`.", Indent::Single),
2213 format!("{}- references, direct or indirect, to structs. E.g., `(&my_struct).field` or `(&&&my_struct).field`.", Indent::Single),
2214 ]
2215 }
2216 },
2217 SymbolWithMultipleBindings { name, paths, span } => Diagnostic {
2218 reason: Some(Reason::new(code(1), "Multiple bindings exist for symbol in the scope".to_string())),
2219 issue: Issue::error(
2220 source_engine,
2221 span.clone(),
2222 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)),
2223 ),
2224 hints: vec![],
2225 help: vec![format!("Consider using a fully qualified name, e.g., `{}::{}`.", paths[0], name)],
2226 },
2227 StorageFieldDoesNotExist { field_name, available_fields, storage_decl_span } => Diagnostic {
2228 reason: Some(Reason::new(code(1), "Storage field does not exist".to_string())),
2229 issue: Issue::error(
2230 source_engine,
2231 field_name.span(),
2232 format!("Storage field \"{field_name}\" does not exist in the storage.")
2233 ),
2234 hints: {
2235 let (hint, show_storage_decl) = if available_fields.is_empty() {
2236 ("The storage is empty. It doesn't have any fields.".to_string(), false)
2237 } else {
2238 const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2239 let display_fields = available_fields.iter().map(|(path, field_name)| {
2240 let path = path.iter().map(ToString::to_string).collect::<Vec<_>>().join("::");
2241 if path.is_empty() {
2242 format!("storage.{field_name}")
2243 } else {
2244 format!("storage::{path}.{field_name}")
2245 }
2246 }).collect::<Vec<_>>();
2247 match &display_fields[..] {
2248 [field] => (format!("Only available storage field is \"{field}\"."), false),
2249 _ => (format!("Available storage fields are {}.", sequence_to_str(&display_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY)),
2250 available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2251 ),
2252 }
2253 };
2254
2255 let mut hints = vec![];
2256
2257 hints.push(Hint::help(source_engine, field_name.span(), hint));
2258
2259 if show_storage_decl {
2260 hints.push(Hint::info(
2261 source_engine,
2262 storage_decl_span.clone(),
2263 format!("Storage is declared here, and has {} fields.",
2264 num_to_str(available_fields.len())
2265 )
2266 ));
2267 }
2268
2269 hints
2270 },
2271 help: vec![],
2272 },
2273 TupleIndexOutOfBounds { index, count, tuple_type, span, prefix_span } => Diagnostic {
2274 reason: Some(Reason::new(code(1), "Tuple index is out of bounds".to_string())),
2275 issue: Issue::error(
2276 source_engine,
2277 span.clone(),
2278 format!("Tuple index {index} is out of bounds. The tuple has only {count} element{}.", plural_s(*count))
2279 ),
2280 hints: vec![
2281 Hint::info(
2282 source_engine,
2283 prefix_span.clone(),
2284 format!("This expression has type \"{tuple_type}\".")
2285 ),
2286 ],
2287 help: vec![],
2288 },
2289 TupleElementAccessOnNonTuple { actually, span, index, index_span } => Diagnostic {
2290 reason: Some(Reason::new(code(1), "Tuple element access requires a tuple".to_string())),
2291 issue: Issue::error(
2292 source_engine,
2293 span.clone(),
2294 format!("This expression has type \"{actually}\", which is not a tuple or a reference to a tuple.")
2295 ),
2296 hints: vec![
2297 Hint::info(
2298 source_engine,
2299 index_span.clone(),
2300 format!("Tuple element access happens here, on the index {index}.")
2301 )
2302 ],
2303 help: vec![
2304 "In Sway, tuple elements can be accessed on:".to_string(),
2305 format!("{}- tuples. E.g., `my_tuple.1`.", Indent::Single),
2306 format!("{}- references, direct or indirect, to tuples. E.g., `(&my_tuple).1` or `(&&&my_tuple).1`.", Indent::Single),
2307 ],
2308 },
2309 RefMutCannotReferenceConstant { constant, span } => Diagnostic {
2310 reason: Some(Reason::new(code(1), "References to mutable values cannot reference constants".to_string())),
2311 issue: Issue::error(
2312 source_engine,
2313 span.clone(),
2314 format!("\"{constant}\" is a constant. `&mut` cannot reference constants.")
2315 ),
2316 hints: vec![],
2317 help: vec![
2318 "Consider:".to_string(),
2319 format!("{}- taking a reference without `mut`: `&{constant}`.", Indent::Single),
2320 format!("{}- referencing a mutable copy of the constant, by returning it from a block: `&mut {{ {constant} }}`.", Indent::Single)
2321 ],
2322 },
2323 RefMutCannotReferenceImmutableVariable { decl_name, span } => Diagnostic {
2324 reason: Some(Reason::new(code(1), "References to mutable values cannot reference immutable variables".to_string())),
2325 issue: Issue::error(
2326 source_engine,
2327 span.clone(),
2328 format!("\"{decl_name}\" is an immutable variable. `&mut` cannot reference immutable variables.")
2329 ),
2330 hints: vec![
2331 Hint::info(
2332 source_engine,
2333 decl_name.span(),
2334 format!("Variable \"{decl_name}\" is declared here as immutable.")
2335 ),
2336 ],
2337 help: vec![
2338 "Consider:".to_string(),
2339 format!("{}- declaring \"{decl_name}\" as mutable.", Indent::Single),
2341 format!("{}- taking a reference without `mut`: `&{decl_name}`.", Indent::Single),
2342 format!("{}- referencing a mutable copy of \"{decl_name}\", by returning it from a block: `&mut {{ {decl_name} }}`.", Indent::Single)
2343 ],
2344 },
2345 ConflictingImplsForTraitAndType { trait_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => Diagnostic {
2346 reason: Some(Reason::new(code(1), "Trait is already implemented for type".to_string())),
2347 issue: Issue::error(
2348 source_engine,
2349 second_impl_span.clone(),
2350 if type_implementing_for == type_implementing_for_unaliased {
2351 format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\".")
2352 } else {
2353 format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").")
2354 }
2355 ),
2356 hints: vec![
2357 Hint::info(
2358 source_engine,
2359 existing_impl_span.clone(),
2360 if type_implementing_for == type_implementing_for_unaliased {
2361 format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\".",
2362 call_path_suffix_with_args(trait_name)
2363 )
2364 } else {
2365 format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").",
2366 call_path_suffix_with_args(trait_name)
2367 )
2368 }
2369 ),
2370 ],
2371 help: vec![
2372 "In Sway, there can be at most one implementation of a trait for any given type.".to_string(),
2373 "This property is called \"trait coherence\".".to_string(),
2374 ],
2375 },
2376 DuplicateDeclDefinedForType { decl_kind, decl_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => {
2377 let decl_kind_snake_case = sway_types::style::to_upper_camel_case(decl_kind);
2378 Diagnostic {
2379 reason: Some(Reason::new(code(1), "Type contains duplicate declarations".to_string())),
2380 issue: Issue::error(
2381 source_engine,
2382 second_impl_span.clone(),
2383 if type_implementing_for == type_implementing_for_unaliased {
2384 format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\".")
2385 } else {
2386 format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").")
2387 }
2388 ),
2389 hints: vec![
2390 Hint::info(
2391 source_engine,
2392 existing_impl_span.clone(),
2393 format!("\"{decl_name}\" previously defined here.")
2394 )
2395 ],
2396 help: vec![
2397 "A type may not contain two or more declarations of the same name".to_string(),
2398 ],
2399 }
2400 },
2401 MarkerTraitExplicitlyImplemented { marker_trait_full_name, span} => Diagnostic {
2402 reason: Some(Reason::new(code(1), "Marker traits cannot be explicitly implemented".to_string())),
2403 issue: Issue::error(
2404 source_engine,
2405 span.clone(),
2406 format!("Trait \"{marker_trait_full_name}\" is a marker trait and cannot be explicitly implemented.")
2407 ),
2408 hints: vec![],
2409 help: match marker_trait_name(marker_trait_full_name) {
2410 "Error" => error_marker_trait_help_msg(),
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 PanicExpressionArgumentIsNotError { argument_type, span } => Diagnostic {
3068 reason: Some(Reason::new(code(1), "Panic expression arguments must implement \"Error\" marker trait".into())),
3069 issue: Issue::error(
3070 source_engine,
3071 span.clone(),
3072 format!("This expression has type \"{argument_type}\", which does not implement \"std::marker::Error\" trait."),
3073 ),
3074 hints: vec![],
3075 help: {
3076 let mut help = vec![
3077 "Panic expression accepts only arguments that implement \"std::marker::Error\" trait.".to_string(),
3078 Diagnostic::help_empty_line(),
3079 ];
3080 help.append(&mut error_marker_trait_help_msg());
3081 help
3082 },
3083 },
3084 _ => Diagnostic {
3085 issue: Issue::error(source_engine, self.span(), format!("{}", self)),
3089 ..Default::default()
3090 }
3091 }
3092 }
3093}
3094
3095#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
3096pub enum TypeNotAllowedReason {
3097 #[error(
3098 "Returning a type containing `raw_slice` from `main()` is not allowed. \
3099 Consider converting it into a flat `raw_slice` first."
3100 )]
3101 NestedSliceReturnNotAllowedInMain,
3102
3103 #[error("The type \"{ty}\" is not allowed in storage.")]
3104 TypeNotAllowedInContractStorage { ty: String },
3105
3106 #[error("`str` or a type containing `str` on `main()` arguments is not allowed.")]
3107 StringSliceInMainParameters,
3108
3109 #[error("Returning `str` or a type containing `str` from `main()` is not allowed.")]
3110 StringSliceInMainReturn,
3111
3112 #[error("`str` or a type containing `str` on `configurables` is not allowed.")]
3113 StringSliceInConfigurables,
3114
3115 #[error("`str` or a type containing `str` on `const` is not allowed.")]
3116 StringSliceInConst,
3117
3118 #[error("slices or types containing slices on `const` are not allowed.")]
3119 SliceInConst,
3120
3121 #[error("references, pointers, slices, string slices or types containing any of these are not allowed.")]
3122 NotAllowedInTransmute,
3123}
3124
3125#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3126pub enum StructFieldUsageContext {
3127 StructInstantiation { struct_can_be_instantiated: bool },
3128 StorageDeclaration { struct_can_be_instantiated: bool },
3129 StorageAccess,
3130 PatternMatching { has_rest_pattern: bool },
3131 StructFieldAccess,
3132 }
3137
3138#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3139pub enum InvalidImplementingForType {
3140 SelfType,
3141 Placeholder,
3142 Other,
3143}
3144
3145impl fmt::Display for InvalidImplementingForType {
3146 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3147 match self {
3148 Self::SelfType => f.write_str("\"Self\""),
3149 Self::Placeholder => f.write_str("Placeholder `_`"),
3150 Self::Other => f.write_str("This"),
3151 }
3152 }
3153}
3154
3155#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3157pub enum ShadowingSource {
3158 Const,
3160 LetVar,
3162 PatternMatchingStructFieldVar,
3165}
3166
3167impl fmt::Display for ShadowingSource {
3168 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3169 match self {
3170 Self::Const => f.write_str("Constant"),
3171 Self::LetVar => f.write_str("Variable"),
3172 Self::PatternMatchingStructFieldVar => f.write_str("Pattern variable"),
3173 }
3174 }
3175}
3176
3177#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3181pub enum StorageAccess {
3182 Clear,
3183 ReadWord,
3184 ReadSlots,
3185 WriteWord,
3186 WriteSlots,
3187 ImpureFunctionCall(Span, bool, bool),
3191}
3192
3193impl StorageAccess {
3194 pub fn is_write(&self) -> bool {
3195 matches!(
3196 self,
3197 Self::Clear | Self::WriteWord | Self::WriteSlots | Self::ImpureFunctionCall(_, _, true)
3198 )
3199 }
3200}
3201
3202impl fmt::Display for StorageAccess {
3203 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3204 match self {
3205 Self::Clear => f.write_str("Clearing the storage happens here."),
3206 Self::ReadWord => f.write_str("Reading a word from the storage happens here."),
3207 Self::ReadSlots => f.write_str("Reading storage slots happens here."),
3208 Self::WriteWord => f.write_str("Writing a word to the storage happens here."),
3209 Self::WriteSlots => f.write_str("Writing to storage slots happens here."),
3210 Self::ImpureFunctionCall(call_path, reads, writes) => f.write_fmt(format_args!(
3211 "Function \"{}\" {} the storage.",
3212 call_path_suffix_with_args(&call_path.as_str().to_string()),
3213 match (reads, writes) {
3214 (true, true) => "reads from and writes to",
3215 (true, false) => "reads from",
3216 (false, true) => "writes to",
3217 (false, false) => unreachable!(
3218 "Function \"{}\" is impure, so it must read from or write to the storage.",
3219 call_path.as_str()
3220 ),
3221 }
3222 )),
3223 }
3224 }
3225}
3226
3227fn marker_trait_name(marker_trait_full_name: &str) -> &str {
3235 const MARKER_TRAITS_MODULE: &str = "std::marker::";
3236 assert!(
3237 marker_trait_full_name.starts_with(MARKER_TRAITS_MODULE),
3238 "`marker_trait_full_name` must start with \"std::marker::\", but it was \"{}\"",
3239 marker_trait_full_name
3240 );
3241
3242 let lower_boundary = MARKER_TRAITS_MODULE.len();
3243 let name_part = &marker_trait_full_name[lower_boundary..];
3244
3245 let upper_boundary = marker_trait_full_name.len() - lower_boundary;
3246 let only_name_len = std::cmp::min(
3247 name_part.find(':').unwrap_or(upper_boundary),
3248 name_part.find('<').unwrap_or(upper_boundary),
3249 );
3250 let upper_boundary = lower_boundary + only_name_len;
3251
3252 &marker_trait_full_name[lower_boundary..upper_boundary]
3253}
3254
3255fn error_marker_trait_help_msg() -> Vec<String> {
3256 vec![
3257 "\"Error\" marker trait is automatically implemented by the compiler for the unit type `()`,".to_string(),
3258 "string slices, and enums annotated with the `#[error_type]` attribute.".to_string(),
3259 ]
3260}