Skip to main content

sway_error/
error.rs

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// TODO: Since moving to using Idents instead of strings, there are a lot of redundant spans in
36//       this type. When replacing Strings + Spans with Idents, be aware of the rule explained below.
37
38// When defining error structures that display identifiers, we prefer passing Idents over Strings.
39// The error span can come from that same Ident or can be a different span.
40// We handle those two cases in the following way:
41//   - If the error span equals Ident's span, we use IdentUnique and never the plain Ident.
42//   - If the error span is different then Ident's span, we pass Ident and Span as two separate fields.
43//
44// The reason for this rule is clearly communicating the difference of the two cases in every error,
45// as well as avoiding issues with the error message deduplication explained below.
46//
47// Deduplication of error messages might remove errors that are actually not duplicates because
48// although they point to the same Ident (in terms of the identifier's name), the span can be different.
49// Deduplication works on hashes and Ident's hash contains only the name and not the span.
50// That's why we always use IdentUnique whenever we extract the span from the provided Ident.
51// Using IdentUnique also clearly communicates that we are extracting the span from the
52// provided identifier.
53#[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        /// The description of the unimplemented feature,
88        /// formulated in a way that fits into common ending
89        /// "is currently not implemented."
90        /// E.g., "Using something".
91        feature: String,
92        /// Help lines. Empty if there is no additional help.
93        /// To get an empty line between the help lines,
94        /// insert a [String] containing only a space: `" ".to_string()`.
95        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, new: Span, old: 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        /// Variable name pointing to the name in the variable declaration.
144        decl_name: Ident,
145        /// The complete left-hand side of the assignment.
146        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        /// Constant or configurable name pointing to the name in the constant declaration.
163        decl_name: Ident,
164        is_configurable: bool,
165        /// The complete left-hand side of the assignment.
166        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        /// Name of the declared variant, pointing to the name in the declaration.
179        decl_name: Option<Ident>,
180        /// Friendly name of the type of the declaration. E.g., "function", or "struct".
181        decl_friendly_type_name: &'static str,
182        /// The complete left-hand side of the assignment.
183        lhs_span: Span,
184    },
185    #[error("This reference is not a reference to a mutable value (`&mut`).")]
186    AssignmentViaNonMutableReference {
187        /// Name of the reference, if the left-hand side of the assignment is a reference variable,
188        /// pointing to the name in the reference variable declaration.
189        ///
190        /// `None` if the assignment LHS is an arbitrary expression and not a variable.
191        decl_reference_name: Option<Ident>,
192        /// [Span] of the right-hand side of the reference variable definition,
193        /// if the left-hand side of the assignment is a reference variable.
194        decl_reference_rhs: Option<Span>,
195        /// The type of the reference, if the left-hand side of the assignment is a reference variable,
196        /// expected to start with `&`.
197        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, as accessed in code. E.g.:
220        ///  - `MY_CONST`
221        ///  - `LIB_CONST_ALIAS`
222        ///  - `::lib::module::SOME_CONST`
223        constant: String,
224        span: Span,
225    },
226    #[error("Reference to a mutable value cannot reference an immutable variable.")]
227    RefMutCannotReferenceImmutableVariable {
228        /// Variable name pointing to the name in the variable declaration.
229        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    /// This error is used only for error recovery and is not emitted as a compiler
327    /// error to the final compilation output. The compiler emits the cumulative error
328    /// [CompileError::StructInstantiationMissingFields] given below, and that one also
329    /// only if the struct can actually be instantiated.
330    #[error("Instantiation of the struct \"{struct_name}\" is missing field \"{field_name}\".")]
331    StructInstantiationMissingFieldForErrorRecovery {
332        field_name: Ident,
333        /// Original, non-aliased struct name.
334        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        /// Original, non-aliased struct name.
343        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        /// Original, non-aliased struct name.
351        struct_name: Ident,
352        span: Span,
353        struct_decl_span: Span,
354        private_fields: Vec<Ident>,
355        /// All available public constructors if `is_in_storage_declaration` is false,
356        /// or only the public constructors that potentially evaluate to a constant
357        /// if `is_in_storage_declaration` is true.
358        constructors: Vec<String>,
359        /// True if the struct has only private fields.
360        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        /// Original, non-aliased struct name.
368        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        /// Only public fields if `is_public_struct_access` is true.
377        available_fields: Vec<Ident>,
378        is_public_struct_access: bool,
379        /// Original, non-aliased struct name.
380        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 function \"{expected_signature}\" found for type \"{type_name}\".{}", 
388        if matching_methods.is_empty() {
389            "".to_string()
390        } else {
391            format!("\nDid you mean:\n{}",
392            matching_methods.iter().map(|m| format!("{}{m}", Indent::Double)).collect::<Vec<_>>().join("\n"))
393        }
394    )]
395    /// Note that _method_ here means **any function associated to a type**, with or without
396    /// the `self` argument.
397    MethodNotFound {
398        called_method: IdentUnique,
399        expected_signature: String,
400        type_name: String,
401        matching_methods: Vec<String>,
402    },
403    #[error("Module \"{name}\" could not be found.")]
404    ModuleNotFound { span: Span, name: String },
405    #[error("This expression has type \"{actually}\", which is not a struct. Fields can only be accessed on structs.")]
406    FieldAccessOnNonStruct {
407        actually: String,
408        /// Name of the storage variable, if the field access
409        /// happens within the access to a storage variable.
410        storage_variable: Option<String>,
411        /// Name of the field that is tried to be accessed.
412        field_name: IdentUnique,
413        span: Span,
414    },
415    #[error("This expression has type \"{actually}\", which is not a tuple. Elements can only be accessed on tuples.")]
416    TupleElementAccessOnNonTuple {
417        actually: String,
418        span: Span,
419        index: usize,
420        index_span: Span,
421    },
422    #[error("This expression has type \"{actually}\", which is not an indexable type.")]
423    NotIndexable { actually: String, span: Span },
424    #[error("\"{name}\" is a {actually}, not an enum.")]
425    NotAnEnum {
426        name: String,
427        span: Span,
428        actually: String,
429    },
430    #[error("This is a {actually}, not a struct.")]
431    NotAStruct { span: Span, actually: String },
432    #[error("This is a {actually}, not an enum.")]
433    DeclIsNotAnEnum { actually: String, span: Span },
434    #[error("This is a {actually}, not a struct.")]
435    DeclIsNotAStruct { actually: String, span: Span },
436    #[error("This is a {actually}, not a function.")]
437    DeclIsNotAFunction { actually: String, span: Span },
438    #[error("This is a {actually}, not a variable.")]
439    DeclIsNotAVariable { actually: String, span: Span },
440    #[error("This is a {actually}, not an ABI.")]
441    DeclIsNotAnAbi { actually: String, span: Span },
442    #[error("This is a {actually}, not a trait.")]
443    DeclIsNotATrait { actually: String, span: Span },
444    #[error("This is a {actually}, not an impl block.")]
445    DeclIsNotAnImplTrait { actually: String, span: Span },
446    #[error("This is a {actually}, not a trait function.")]
447    DeclIsNotATraitFn { actually: String, span: Span },
448    #[error("This is a {actually}, not storage.")]
449    DeclIsNotStorage { actually: String, span: Span },
450    #[error("This is a {actually}, not a constant")]
451    DeclIsNotAConstant { actually: String, span: Span },
452    #[error("This is a {actually}, not a type alias")]
453    DeclIsNotATypeAlias { actually: String, span: Span },
454    #[error("Could not find symbol \"{name}\" in this scope.")]
455    SymbolNotFound { name: Ident, span: Span },
456    #[error("Found multiple bindings for \"{name}\" in this scope.")]
457    SymbolWithMultipleBindings {
458        name: Ident,
459        paths: Vec<String>,
460        span: Span,
461    },
462    #[error("Symbol \"{name}\" is private.")]
463    ImportPrivateSymbol { name: Ident, span: Span },
464    #[error("Module \"{name}\" is private.")]
465    ImportPrivateModule { name: Ident, span: Span },
466    #[error(
467        "Because this if expression's value is used, an \"else\" branch is required and it must \
468         return type \"{r#type}\""
469    )]
470    NoElseBranch { span: Span, r#type: String },
471    #[error(
472        "Symbol \"{name}\" does not refer to a type, it refers to a {actually_is}. It cannot be \
473         used in this position."
474    )]
475    NotAType {
476        span: Span,
477        name: String,
478        actually_is: &'static str,
479    },
480    #[error(
481        "This enum variant requires an instantiation expression. Try initializing it with \
482         arguments in parentheses."
483    )]
484    MissingEnumInstantiator { span: Span },
485    #[error(
486        "This path must return a value of type \"{ty}\" from function \"{function_name}\", but it \
487         does not."
488    )]
489    PathDoesNotReturn {
490        span: Span,
491        ty: String,
492        function_name: Ident,
493    },
494    #[error(
495        "This register was not initialized in the initialization section of the ASM expression. \
496         Initialized registers are: {initialized_registers}"
497    )]
498    UnknownRegister {
499        span: Span,
500        initialized_registers: String,
501    },
502    #[error("This opcode takes an immediate value but none was provided.")]
503    MissingImmediate { span: Span },
504    #[error("This immediate value is invalid.")]
505    InvalidImmediateValue { span: Span },
506    #[error("Variant \"{variant_name}\" does not exist on enum \"{enum_name}\"")]
507    UnknownEnumVariant {
508        enum_name: Ident,
509        variant_name: Ident,
510        span: Span,
511    },
512    #[error("Unknown opcode: \"{op_name}\".")]
513    UnrecognizedOp { op_name: Ident, span: Span },
514    #[error("Cannot infer type for type parameter \"{ty}\". Insufficient type information provided. Try annotating its type.")]
515    UnableToInferGeneric { ty: String, span: Span },
516    #[error("The generic type parameter \"{ty}\" is unconstrained.")]
517    UnconstrainedGenericParameter { ty: String, span: Span },
518    #[error("Trait \"{trait_name}\" is not implemented for type \"{ty}\".")]
519    TraitConstraintNotSatisfied {
520        type_id: usize, // Used to filter errors in method application type check.
521        ty: String,
522        trait_name: String,
523        span: Span,
524    },
525    #[error(
526        "Expects trait constraint \"{param}: {trait_name}\" which is missing from type parameter \"{param}\"."
527    )]
528    TraitConstraintMissing {
529        param: String,
530        trait_name: String,
531        span: Span,
532    },
533    #[error("The value \"{val}\" is too large to fit in this 6-bit immediate spot.")]
534    Immediate06TooLarge { val: u64, span: Span },
535    #[error("The value \"{val}\" is too large to fit in this 12-bit immediate spot.")]
536    Immediate12TooLarge { val: u64, span: Span },
537    #[error("The value \"{val}\" is too large to fit in this 18-bit immediate spot.")]
538    Immediate18TooLarge { val: u64, span: Span },
539    #[error("The value \"{val}\" is too large to fit in this 24-bit immediate spot.")]
540    Immediate24TooLarge { val: u64, span: Span },
541    #[error(
542        "This op expects {expected} register(s) as arguments, but you provided {received} register(s)."
543    )]
544    IncorrectNumberOfAsmRegisters {
545        span: Span,
546        expected: usize,
547        received: usize,
548    },
549    #[error("This op does not take an immediate value.")]
550    UnnecessaryImmediate { span: Span },
551    #[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.")]
552    AmbiguousPath { span: Span },
553    #[error("This is a module path, and not an expression.")]
554    ModulePathIsNotAnExpression { module_path: String, span: Span },
555    #[error("Unknown type name.")]
556    UnknownType { span: Span },
557    #[error("Unknown type name \"{name}\".")]
558    UnknownTypeName { name: String, span: Span },
559    #[error("The file {file_path} could not be read: {stringified_error}")]
560    FileCouldNotBeRead {
561        span: Span,
562        file_path: String,
563        stringified_error: String,
564    },
565    #[error("This imported file must be a library. It must start with \"library;\"")]
566    ImportMustBeLibrary { span: Span },
567    #[error("An enum instantiaton cannot contain more than one value. This should be a single value of type {ty}.")]
568    MoreThanOneEnumInstantiator { span: Span, ty: String },
569    #[error("This enum variant represents the unit type, so it should not be instantiated with any value.")]
570    UnnecessaryEnumInstantiator { span: Span },
571    #[error("The enum variant `{ty}` is of type `unit`, so its constructor does not take arguments or parentheses. Try removing the ().")]
572    UnitVariantWithParenthesesEnumInstantiator { span: Span, ty: String },
573    #[error("Cannot find trait \"{name}\" in this scope.")]
574    TraitNotFound { name: String, span: Span },
575    #[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.")]
576    TraitNotImportedAtFunctionApplication {
577        trait_name: String,
578        function_name: String,
579        function_call_site_span: Span,
580        trait_constraint_span: Span,
581        trait_candidates: Vec<String>,
582    },
583    #[error("This expression is not valid on the left hand side of a reassignment.")]
584    InvalidExpressionOnLhs { span: Span },
585    #[error("This code cannot be evaluated to a constant")]
586    CannotBeEvaluatedToConst { span: Span },
587    #[error(
588        "This code cannot be evaluated to a configurable because its size is not always limited."
589    )]
590    CannotBeEvaluatedToConfigurableSizeUnknown { span: Span },
591    #[error("{} \"{method_name}\" expects {expected} {} but you provided {received}.",
592        if *dot_syntax_used { "Method" } else { "Function" },
593        if *expected == 1usize { "argument" } else {"arguments"},
594    )]
595    TooManyArgumentsForFunction {
596        span: Span,
597        method_name: Ident,
598        dot_syntax_used: bool,
599        expected: usize,
600        received: usize,
601    },
602    #[error("{} \"{method_name}\" expects {expected} {} but you provided {received}.",
603        if *dot_syntax_used { "Method" } else { "Function" },
604        if *expected == 1usize { "argument" } else {"arguments"},
605    )]
606    TooFewArgumentsForFunction {
607        span: Span,
608        method_name: Ident,
609        dot_syntax_used: bool,
610        expected: usize,
611        received: usize,
612    },
613    #[error("The function \"{method_name}\" was called without parentheses. Try adding ().")]
614    MissingParenthesesForFunction { span: Span, method_name: Ident },
615    #[error("This type is invalid in a function selector. A contract ABI function selector must be a known sized type, not generic.")]
616    InvalidAbiType { span: Span },
617    #[error("This is a {actually_is}, not an ABI. An ABI cast requires a valid ABI to cast the address to.")]
618    NotAnAbi {
619        span: Span,
620        actually_is: &'static str,
621    },
622    #[error("An ABI can only be implemented for the `Contract` type, so this implementation of an ABI for type \"{ty}\" is invalid.")]
623    ImplAbiForNonContract { span: Span, ty: String },
624    #[error("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\".")]
625    ConflictingImplsForTraitAndType {
626        trait_name: String,
627        type_implementing_for: String,
628        type_implementing_for_unaliased: String,
629        existing_impl_span: Span,
630        second_impl_span: Span,
631    },
632    #[error(
633        "\"{marker_trait_full_name}\" is a marker trait and cannot be explicitly implemented."
634    )]
635    MarkerTraitExplicitlyImplemented {
636        marker_trait_full_name: String,
637        span: Span,
638    },
639    #[error("Duplicate definitions for the {decl_kind} \"{decl_name}\" for type \"{type_implementing_for}\".")]
640    DuplicateDeclDefinedForType {
641        decl_kind: String,
642        decl_name: String,
643        type_implementing_for: String,
644        type_implementing_for_unaliased: String,
645        existing_impl_span: Span,
646        second_impl_span: Span,
647    },
648    #[error("The function \"{fn_name}\" in {interface_name} is defined with {num_parameters} parameters, but the provided implementation has {provided_parameters} parameters.")]
649    IncorrectNumberOfInterfaceSurfaceFunctionParameters {
650        fn_name: Ident,
651        interface_name: InterfaceName,
652        num_parameters: usize,
653        provided_parameters: usize,
654        span: Span,
655    },
656    #[error("This parameter was declared as type {should_be}, but argument of type {provided} was provided.")]
657    ArgumentParameterTypeMismatch {
658        span: Span,
659        should_be: String,
660        provided: String,
661    },
662    #[error("Function {fn_name} is recursive, which is unsupported at this time.")]
663    RecursiveCall { fn_name: Ident, span: Span },
664    #[error(
665        "Function {fn_name} is recursive via {call_chain}, which is unsupported at this time."
666    )]
667    RecursiveCallChain {
668        fn_name: Ident,
669        call_chain: String, // Pretty list of symbols, e.g., "a, b and c".
670        span: Span,
671    },
672    #[error("Type {name} is recursive, which is unsupported at this time.")]
673    RecursiveType { name: Ident, span: Span },
674    #[error("Type {name} is recursive via {type_chain}, which is unsupported at this time.")]
675    RecursiveTypeChain {
676        name: Ident,
677        type_chain: String, // Pretty list of symbols, e.g., "a, b and c".
678        span: Span,
679    },
680    #[error("The GM (get-metadata) opcode, when called from an external context, will cause the VM to panic.")]
681    GMFromExternalContext { span: Span },
682    #[error("The MINT opcode cannot be used in an external context.")]
683    MintFromExternalContext { span: Span },
684    #[error("The BURN opcode cannot be used in an external context.")]
685    BurnFromExternalContext { span: Span },
686    #[error("Contract storage cannot be used in an external context.")]
687    ContractStorageFromExternalContext { span: Span },
688    #[error("The {opcode} opcode cannot be used in a predicate.")]
689    InvalidOpcodeFromPredicate { opcode: String, span: Span },
690    #[error("Index out of bounds; the length is {count} but the index is {index}.")]
691    ArrayOutOfBounds { index: u64, count: u64, span: Span },
692    #[error(
693        "Invalid range; the range end at index {end} is smaller than its start at index {start}"
694    )]
695    InvalidRangeEndGreaterThanStart { start: u64, end: u64, span: Span },
696    #[error("Tuple index {index} is out of bounds. The tuple has {count} element{}.", plural_s(*count))]
697    TupleIndexOutOfBounds {
698        index: usize,
699        count: usize,
700        tuple_type: String,
701        span: Span,
702        prefix_span: Span,
703    },
704    #[error("Constant requires expression.")]
705    ConstantRequiresExpression { span: Span },
706    #[error("Constants cannot be shadowed. {shadowing_source} \"{name}\" shadows constant of the same name.")]
707    ConstantsCannotBeShadowed {
708        /// Defines what shadows the constant.
709        ///
710        /// Although being ready in the diagnostic, the `PatternMatchingStructFieldVar` option
711        /// is currently not used. Getting the information about imports and aliases while
712        /// type checking match branches is too much effort at the moment, compared to gained
713        /// additional clarity of the error message. We might add support for this option in
714        /// the future.
715        shadowing_source: ShadowingSource,
716        name: IdentUnique,
717        constant_span: Span,
718        constant_decl_span: Span,
719        is_alias: bool,
720    },
721    #[error("Configurables cannot be shadowed. {shadowing_source} \"{name}\" shadows configurable of the same name.")]
722    ConfigurablesCannotBeShadowed {
723        /// Defines what shadows the configurable.
724        ///
725        /// Using configurable in pattern matching, expecting to behave same as a constant,
726        /// will result in [CompileError::ConfigurablesCannotBeMatchedAgainst].
727        /// Otherwise, we would end up with a very confusing error message that
728        /// a configurable cannot be shadowed by a variable.
729        /// In the, unlikely but equally confusing, case of a struct field pattern variable
730        /// named same as the configurable we also want to provide a better explanation
731        /// and `shadowing_source` helps us distinguish that case as well.
732        shadowing_source: ShadowingSource,
733        name: IdentUnique,
734        configurable_span: Span,
735    },
736    #[error("Configurables cannot be matched against. Configurable \"{name}\" cannot be used in pattern matching.")]
737    ConfigurablesCannotBeMatchedAgainst {
738        name: IdentUnique,
739        configurable_span: Span,
740    },
741    #[error(
742        "Constants cannot shadow variables. Constant \"{name}\" shadows variable of the same name."
743    )]
744    ConstantShadowsVariable {
745        name: IdentUnique,
746        variable_span: Span,
747    },
748    #[error("{existing_constant_or_configurable} of the name \"{name}\" already exists.")]
749    ConstantDuplicatesConstantOrConfigurable {
750        /// Text "Constant" or "Configurable". Denotes already declared constant or configurable.
751        existing_constant_or_configurable: &'static str,
752        /// Text "Constant" or "Configurable". Denotes constant or configurable attempted to be declared.
753        new_constant_or_configurable: &'static str,
754        name: IdentUnique,
755        existing_span: Span,
756    },
757    #[error("Imported symbol \"{name}\" shadows another symbol of the same name.")]
758    ShadowsOtherSymbol { name: IdentUnique },
759    #[error("The name \"{name}\" is already used for a generic parameter in this scope.")]
760    GenericShadowsGeneric { name: IdentUnique },
761    #[error("Non-exhaustive match expression. Missing patterns {missing_patterns}")]
762    MatchExpressionNonExhaustive {
763        missing_patterns: String,
764        span: Span,
765    },
766    #[error("Struct pattern is missing the {}field{} {}.",
767        if *missing_fields_are_public { "public " } else { "" },
768        plural_s(missing_fields.len()),
769        sequence_to_str(missing_fields, Enclosing::DoubleQuote, 2)
770    )]
771    MatchStructPatternMissingFields {
772        missing_fields: Vec<Ident>,
773        missing_fields_are_public: bool,
774        /// Original, non-aliased struct name.
775        struct_name: Ident,
776        struct_decl_span: Span,
777        total_number_of_fields: usize,
778        span: Span,
779    },
780    #[error("Struct pattern must ignore inaccessible private field{} {}.",
781        plural_s(private_fields.len()),
782        sequence_to_str(private_fields, Enclosing::DoubleQuote, 2))]
783    MatchStructPatternMustIgnorePrivateFields {
784        private_fields: Vec<Ident>,
785        /// Original, non-aliased struct name.
786        struct_name: Ident,
787        struct_decl_span: Span,
788        all_fields_are_private: bool,
789        span: Span,
790    },
791    #[error("Variable \"{variable}\" is not defined in all alternatives.")]
792    MatchArmVariableNotDefinedInAllAlternatives {
793        match_value: Span,
794        match_type: String,
795        variable: Ident,
796        missing_in_alternatives: Vec<Span>,
797    },
798    #[error(
799        "Variable \"{variable}\" is expected to be of type \"{expected}\", but is \"{received}\"."
800    )]
801    MatchArmVariableMismatchedType {
802        match_value: Span,
803        match_type: String,
804        variable: Ident,
805        first_definition: Span,
806        expected: String,
807        received: String,
808    },
809    #[error("This cannot be matched.")]
810    MatchedValueIsNotValid {
811        /// Common message describing which Sway types
812        /// are currently supported in match expressions.
813        supported_types_message: Vec<&'static str>,
814        span: Span,
815    },
816    #[error(
817        "The function \"{fn_name}\" in {interface_name} is pure, but this \
818        implementation is not.  The \"storage\" annotation must be \
819        removed, or the trait declaration must be changed to \
820        \"#[storage({attrs})]\"."
821    )]
822    TraitDeclPureImplImpure {
823        fn_name: Ident,
824        interface_name: InterfaceName,
825        attrs: String,
826        span: Span,
827    },
828    #[error(
829        "Storage attribute access mismatch. The function \"{fn_name}\" in \
830        {interface_name} requires the storage attribute(s) #[storage({attrs})]."
831    )]
832    TraitImplPurityMismatch {
833        fn_name: Ident,
834        interface_name: InterfaceName,
835        attrs: String,
836        span: Span,
837    },
838    #[error("Impure function inside of non-contract. Contract storage is only accessible from contracts.")]
839    ImpureInNonContract { span: Span },
840    #[error(
841        "This function performs storage access but does not have the required storage \
842        attribute(s). Try adding \"#[storage({suggested_attributes})]\" to the function \
843        declaration."
844    )]
845    StorageAccessMismatched {
846        /// True if the function with mismatched access is pure.
847        is_pure: bool,
848        storage_access_violations: Vec<(Span, StorageAccess)>,
849        suggested_attributes: String,
850        /// Span pointing to the name of the function in the function declaration,
851        /// whose storage attributes mismatch the storage access patterns.
852        span: Span,
853    },
854    #[error(
855        "Parameter reference type or mutability mismatch between the trait function declaration and its implementation."
856    )]
857    ParameterRefMutabilityMismatch { span: Span },
858    #[error("Literal value is too large for type {ty}.")]
859    IntegerTooLarge { span: Span, ty: String },
860    #[error("Literal value underflows type {ty}.")]
861    IntegerTooSmall { span: Span, ty: String },
862    #[error("Literal value contains digits which are not valid for type {ty}.")]
863    IntegerContainsInvalidDigit { span: Span, ty: String },
864    #[error("A trait cannot be a subtrait of an ABI.")]
865    AbiAsSupertrait { span: Span },
866    #[error(
867        "Implementation of trait \"{supertrait_name}\" is required by this bound in \"{trait_name}\""
868    )]
869    SupertraitImplRequired {
870        supertrait_name: String,
871        trait_name: Ident,
872        span: Span,
873    },
874    #[error(
875        "Contract ABI method parameter \"{param_name}\" is set multiple times for this contract ABI method call"
876    )]
877    ContractCallParamRepeated { param_name: String, span: Span },
878    #[error(
879        "Unrecognized contract ABI method parameter \"{param_name}\". The only available parameters are \"gas\", \"coins\", and \"asset_id\""
880    )]
881    UnrecognizedContractParam { param_name: String, span: Span },
882    #[error("Attempting to specify a contract method parameter for a non-contract function call")]
883    CallParamForNonContractCallMethod { span: Span },
884    #[error("Storage field \"{field_name}\" does not exist.")]
885    StorageFieldDoesNotExist {
886        field_name: IdentUnique,
887        available_fields: Vec<(Vec<Ident>, Ident)>,
888        storage_decl_span: Span,
889    },
890    #[error("No storage has been declared")]
891    NoDeclaredStorage { span: Span },
892    #[error("Multiple storage declarations were found")]
893    MultipleStorageDeclarations { span: Span },
894    #[error("Type {ty} can only be declared directly as a storage field")]
895    InvalidStorageOnlyTypeDecl { ty: String, span: Span },
896    #[error(
897        "Internal compiler error: Unexpected {decl_type} declaration found.\n\
898        Please file an issue on the repository and include the code that triggered this error."
899    )]
900    UnexpectedDeclaration { decl_type: &'static str, span: Span },
901    #[error("This contract caller has no known address. Try instantiating a contract caller with a known contract address instead.")]
902    ContractAddressMustBeKnown { span: Span },
903    #[error("{}", error)]
904    ConvertParseTree {
905        #[from]
906        error: ConvertParseTreeError,
907    },
908    #[error("{}", error)]
909    Lex { error: LexError },
910    #[error("{}", error)]
911    Parse { error: ParseError },
912    #[error("Could not evaluate initializer to a const declaration.")]
913    NonConstantDeclValue { span: Span },
914    #[error("Declaring storage in a {program_kind} is not allowed.")]
915    StorageDeclarationInNonContract { program_kind: String, span: Span },
916    #[error("Unsupported argument type to intrinsic \"{name}\".{}", if hint.is_empty() { "".to_string() } else { format!(" Hint: {hint}") })]
917    IntrinsicUnsupportedArgType {
918        name: String,
919        span: Span,
920        hint: String,
921    },
922    #[error("Call to \"{name}\" expects {expected} argument(s)")]
923    IntrinsicIncorrectNumArgs {
924        name: String,
925        expected: u64,
926        span: Span,
927    },
928    #[error("Call to \"{name}\" expects {expected} type arguments")]
929    IntrinsicIncorrectNumTArgs {
930        name: String,
931        expected: u64,
932        span: Span,
933    },
934    #[error("\"__{intrinsic}\" intrinsic's argument \"{arg}\" must be a constant of type `{expected_type}`.")]
935    IntrinsicArgNotConstant {
936        intrinsic: String,
937        arg: String,
938        expected_type: String,
939        span: Span,
940    },
941    #[error("Expected string literal")]
942    ExpectedStringLiteral { span: Span },
943    #[error("\"break\" used outside of a loop")]
944    BreakOutsideLoop { span: Span },
945    #[error("\"continue\" used outside of a loop")]
946    ContinueOutsideLoop { span: Span },
947    /// This will be removed once loading contract IDs in a dependency namespace is refactored and no longer manual:
948    /// https://github.com/FuelLabs/sway/issues/3077
949    #[error("Contract ID value is not a literal.")]
950    ContractIdValueNotALiteral { span: Span },
951
952    #[error("{reason}")]
953    TypeNotAllowed {
954        reason: TypeNotAllowedReason,
955        span: Span,
956    },
957    #[error("ref mut parameter not allowed for main()")]
958    RefMutableNotAllowedInMain { param_name: Ident, span: Span },
959    #[error(
960        "Register \"{name}\" is initialized and later reassigned which is not allowed. \
961            Consider assigning to a different register inside the ASM block."
962    )]
963    InitializedRegisterReassignment { name: String, span: Span },
964    #[error("Control flow VM instructions are not allowed in assembly blocks.")]
965    DisallowedControlFlowInstruction { name: String, span: Span },
966    #[error("Calling private library method {name} is not allowed.")]
967    CallingPrivateLibraryMethod { name: String, span: Span },
968    #[error("Using intrinsic \"{intrinsic}\" in a predicate is not allowed.")]
969    DisallowedIntrinsicInPredicate { intrinsic: String, span: Span },
970    #[error("Possibly non-zero amount of coins transferred to non-payable contract method \"{fn_name}\".")]
971    CoinsPassedToNonPayableMethod { fn_name: Ident, span: Span },
972    #[error(
973        "Payable attribute mismatch. The \"{fn_name}\" method implementation \
974         {} in its signature in {interface_name}.",
975        if *missing_impl_attribute {
976            "is missing #[payable] attribute specified"
977        } else {
978            "has extra #[payable] attribute not mentioned"
979        }
980    )]
981    TraitImplPayabilityMismatch {
982        fn_name: Ident,
983        interface_name: InterfaceName,
984        missing_impl_attribute: bool,
985        span: Span,
986    },
987    #[error("Configurable constants are not allowed in libraries.")]
988    ConfigurableInLibrary { span: Span },
989    #[error("Multiple applicable items in scope. {}", {
990        let mut candidates = "".to_string();
991        let mut as_traits = as_traits.clone();
992        // Make order deterministic
993        as_traits.sort_by_key(|a| a.0.to_lowercase());
994        for (index, as_trait) in as_traits.iter().enumerate() {
995            candidates = format!("{candidates}\n  Disambiguate the associated {item_kind} for candidate #{index}\n    <{} as {}>::{item_name}", as_trait.1, as_trait.0);
996        }
997        candidates
998    })]
999    MultipleApplicableItemsInScope {
1000        span: Span,
1001        item_name: String,
1002        item_kind: String,
1003        as_traits: Vec<(String, String)>,
1004    },
1005    #[error("Provided generic type is not of type str.")]
1006    NonStrGenericType { span: Span },
1007    #[error("A contract method cannot call methods belonging to the same ABI")]
1008    ContractCallsItsOwnMethod { span: Span },
1009    #[error("ABI cannot define a method of the same name as its super-ABI \"{superabi}\"")]
1010    AbiShadowsSuperAbiMethod { span: Span, superabi: Ident },
1011    #[error("ABI cannot inherit samely named method (\"{method_name}\") from several super-ABIs: \"{superabi1}\" and \"{superabi2}\"")]
1012    ConflictingSuperAbiMethods {
1013        span: Span,
1014        method_name: String,
1015        superabi1: String,
1016        superabi2: String,
1017    },
1018    #[error("Associated types not supported in ABI.")]
1019    AssociatedTypeNotSupportedInAbi { span: Span },
1020    #[error("Cannot call ABI supertrait's method as a contract method: \"{fn_name}\"")]
1021    AbiSupertraitMethodCallAsContractCall { fn_name: Ident, span: Span },
1022    #[error(
1023        "Methods {method_name} and {other_method_name} name have clashing function selectors."
1024    )]
1025    FunctionSelectorClash {
1026        method_name: Ident,
1027        span: Span,
1028        other_method_name: Ident,
1029        other_span: Span,
1030    },
1031    #[error("{invalid_type} is not a valid type in the self type of an impl block.")]
1032    TypeIsNotValidAsImplementingFor {
1033        invalid_type: InvalidImplementingForType,
1034        /// Name of the trait if the impl implements a trait, `None` otherwise.
1035        trait_name: Option<String>,
1036        span: Span,
1037    },
1038    #[error("Uninitialized register is being read before being written")]
1039    UninitRegisterInAsmBlockBeingRead { span: Span },
1040    #[error("Expression of type \"{expression_type}\" cannot be dereferenced.")]
1041    ExpressionCannotBeDereferenced { expression_type: String, span: Span },
1042    #[error("Fallback functions can only exist in contracts")]
1043    FallbackFnsAreContractOnly { span: Span },
1044    #[error("Fallback functions cannot have parameters")]
1045    FallbackFnsCannotHaveParameters { span: Span },
1046    #[error("Could not generate the entry method. See errors above for more details.")]
1047    CouldNotGenerateEntry { span: Span },
1048    #[error("Missing `std` in dependencies.")]
1049    CouldNotGenerateEntryMissingStd { span: Span },
1050    #[error("Type \"{ty}\" does not implement AbiEncode or AbiDecode.")]
1051    CouldNotGenerateEntryMissingImpl { ty: String, span: Span },
1052    #[error("Only bool, u8, u16, u32, u64, u256, b256, string arrays and string slices can be used here.")]
1053    EncodingUnsupportedType { span: Span },
1054    #[error("Configurables need a function named \"abi_decode_in_place\" to be in scope.")]
1055    ConfigurableMissingAbiDecodeInPlace { span: Span },
1056    #[error("Invalid name found for renamed ABI type.\n")]
1057    ABIInvalidName { span: Span, name: String },
1058    #[error("Duplicated name found for renamed ABI type.\n")]
1059    ABIDuplicateName {
1060        span: Span,
1061        other_span: Span,
1062        is_attribute: bool,
1063    },
1064    #[error("Collision detected between two different types.\n  Shared hash:{hash}\n  First type:{first_type}\n  Second type:{second_type}")]
1065    ABIHashCollision {
1066        span: Span,
1067        hash: String,
1068        first_type: String,
1069        second_type: String,
1070    },
1071    #[error("Type must be known at this point")]
1072    TypeMustBeKnownAtThisPoint { span: Span, internal: String },
1073    #[error("Multiple impls satisfying trait for type.")]
1074    MultipleImplsSatisfyingTraitForType {
1075        span: Span,
1076        type_annotation: String,
1077        trait_names: Vec<String>,
1078        trait_types_and_names: Vec<(String, String)>,
1079    },
1080    #[error("Multiple contracts methods with the same name.")]
1081    MultipleContractsMethodsWithTheSameName { spans: Vec<Span> },
1082    #[error("Error type enum \"{enum_name}\" has non-error variant{} {}. All variants must be marked as `#[error]`.",
1083        plural_s(non_error_variants.len()),
1084        sequence_to_str(non_error_variants, Enclosing::DoubleQuote, 2)
1085    )]
1086    ErrorTypeEnumHasNonErrorVariants {
1087        enum_name: IdentUnique,
1088        non_error_variants: Vec<IdentUnique>,
1089    },
1090    #[error("Enum variant \"{enum_variant_name}\" is marked as `#[error]`, but \"{enum_name}\" is not an `#[error_type]` enum.")]
1091    ErrorAttributeInNonErrorEnum {
1092        enum_name: IdentUnique,
1093        enum_variant_name: IdentUnique,
1094    },
1095    #[error("This expression has type \"{argument_type}\", which does not implement \"std::marker::Error\". Panic expression arguments must implement \"Error\".")]
1096    PanicExpressionArgumentIsNotError { argument_type: String, span: Span },
1097    #[error("This is the {current}{} `panic` expression occurred during the compilation.\nSway projects can have up to {max_num} `panic` expressions.\nConsider refactoring your code to reduce the number of `panic` expressions.",
1098        ord_num_suffix(*current as usize)
1099    )]
1100    MaxNumOfPanicExpressionsReached {
1101        current: u64,
1102        max_num: u64,
1103        span: Span,
1104    },
1105    #[error("This is the {current}{} panicking call occurred during the compilation.\nSway projects can have up to {max_num} panicking calls.\nConsider compiling the project with the `backtrace` build option set to `only_always` or `none`.",
1106        ord_num_suffix(*current as usize)
1107    )]
1108    MaxNumOfPanickingCallsReached {
1109        current: u64,
1110        max_num: u64,
1111        span: Span,
1112    },
1113    #[error("Coherence violation: only traits defined in this package can be implemented for external types.")]
1114    IncoherentImplDueToOrphanRule {
1115        trait_name: String,
1116        type_name: String,
1117        span: Span,
1118    },
1119    #[error("Field \"{field_name}\" is marked as `#[indexed]`, but \"{struct_name}\" is not an `#[event]` struct.")]
1120    IndexedFieldInNonEventStruct {
1121        field_name: IdentUnique,
1122        struct_name: IdentUnique,
1123    },
1124    #[error(
1125        "Field \"{field_name}\" is marked as `#[indexed]`, but indexed fields must come before all non-indexed fields in an `#[event]` struct."
1126    )]
1127    IndexedFieldMustPrecedeNonIndexedField { field_name: IdentUnique },
1128    #[error("Field \"{field_name}\" is marked as `#[indexed]`, but not a fixed-size type.")]
1129    IndexedFieldIsNotFixedSizeABIType { field_name: IdentUnique },
1130    #[error("Too many indexed fields on event for current metadata format.")]
1131    IndexedFieldOffsetTooLarge { field_name: IdentUnique },
1132}
1133
1134impl std::convert::From<TypeError> for CompileError {
1135    fn from(other: TypeError) -> CompileError {
1136        CompileError::TypeError(other)
1137    }
1138}
1139
1140impl Spanned for CompileError {
1141    fn span(&self) -> Span {
1142        use CompileError::*;
1143        match self {
1144            ConstGenericNotSupportedHere { span } => span.clone(),
1145            LengthExpressionNotSupported { span } => span.clone(),
1146            FeatureIsDisabled { span, .. } => span.clone(),
1147            ModuleDepGraphEvaluationError { .. } => Span::dummy(),
1148            ModuleDepGraphCyclicReference { .. } => Span::dummy(),
1149            UnknownVariable { span, .. } => span.clone(),
1150            NotAVariable { span, .. } => span.clone(),
1151            Unimplemented { span, .. } => span.clone(),
1152            TypeError(err) => err.span(),
1153            ParseError { span, .. } => span.clone(),
1154            Internal(_, span) => span.clone(),
1155            InternalOwned(_, span) => span.clone(),
1156            NoPredicateMainFunction(span) => span.clone(),
1157            PredicateMainDoesNotReturnBool(span) => span.clone(),
1158            NoScriptMainFunction(span) => span.clone(),
1159            MultipleDefinitionsOfFunction { span, .. } => span.clone(),
1160            MultipleDefinitionsOfName { span, .. } => span.clone(),
1161            MultipleDefinitionsOfConstant { new: span, .. } => span.clone(),
1162            MultipleDefinitionsOfType { span, .. } => span.clone(),
1163            MultipleDefinitionsOfMatchArmVariable { duplicate, .. } => duplicate.clone(),
1164            MultipleDefinitionsOfFallbackFunction { span, .. } => span.clone(),
1165            AssignmentToNonMutableVariable { lhs_span, .. } => lhs_span.clone(),
1166            AssignmentToConstantOrConfigurable { lhs_span, .. } => lhs_span.clone(),
1167            DeclAssignmentTargetCannotBeAssignedTo { lhs_span, .. } => lhs_span.clone(),
1168            AssignmentViaNonMutableReference { span, .. } => span.clone(),
1169            MutableParameterNotSupported { span, .. } => span.clone(),
1170            ImmutableArgumentToMutableParameter { span } => span.clone(),
1171            RefMutableNotAllowedInContractAbi { span, .. } => span.clone(),
1172            RefMutCannotReferenceConstant { span, .. } => span.clone(),
1173            RefMutCannotReferenceImmutableVariable { span, .. } => span.clone(),
1174            MethodRequiresMutableSelf { span, .. } => span.clone(),
1175            AssociatedFunctionCalledAsMethod { span, .. } => span.clone(),
1176            TypeParameterNotInTypeScope { span, .. } => span.clone(),
1177            MismatchedTypeInInterfaceSurface { span, .. } => span.clone(),
1178            UnknownTrait { span, .. } => span.clone(),
1179            FunctionNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1180            ConstantNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1181            TypeNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1182            MissingInterfaceSurfaceConstants { span, .. } => span.clone(),
1183            MissingInterfaceSurfaceTypes { span, .. } => span.clone(),
1184            MissingInterfaceSurfaceMethods { span, .. } => span.clone(),
1185            IncorrectNumberOfTypeArguments { span, .. } => span.clone(),
1186            DoesNotTakeTypeArguments { span, .. } => span.clone(),
1187            DoesNotTakeTypeArgumentsAsPrefix { span, .. } => span.clone(),
1188            TypeArgumentsNotAllowed { span } => span.clone(),
1189            NeedsTypeArguments { span, .. } => span.clone(),
1190            StructInstantiationMissingFieldForErrorRecovery { span, .. } => span.clone(),
1191            StructInstantiationMissingFields { span, .. } => span.clone(),
1192            StructCannotBeInstantiated { span, .. } => span.clone(),
1193            StructFieldIsPrivate { field_name, .. } => field_name.span(),
1194            StructFieldDoesNotExist { field_name, .. } => field_name.span(),
1195            StructFieldDuplicated { field_name, .. } => field_name.span(),
1196            MethodNotFound { called_method, .. } => called_method.span(),
1197            ModuleNotFound { span, .. } => span.clone(),
1198            TupleElementAccessOnNonTuple { span, .. } => span.clone(),
1199            NotAStruct { span, .. } => span.clone(),
1200            NotIndexable { span, .. } => span.clone(),
1201            FieldAccessOnNonStruct { span, .. } => span.clone(),
1202            SymbolNotFound { span, .. } => span.clone(),
1203            SymbolWithMultipleBindings { span, .. } => span.clone(),
1204            ImportPrivateSymbol { span, .. } => span.clone(),
1205            ImportPrivateModule { span, .. } => span.clone(),
1206            NoElseBranch { span, .. } => span.clone(),
1207            NotAType { span, .. } => span.clone(),
1208            MissingEnumInstantiator { span, .. } => span.clone(),
1209            PathDoesNotReturn { span, .. } => span.clone(),
1210            UnknownRegister { span, .. } => span.clone(),
1211            MissingImmediate { span, .. } => span.clone(),
1212            InvalidImmediateValue { span, .. } => span.clone(),
1213            UnknownEnumVariant { span, .. } => span.clone(),
1214            UnrecognizedOp { span, .. } => span.clone(),
1215            UnableToInferGeneric { span, .. } => span.clone(),
1216            UnconstrainedGenericParameter { span, .. } => span.clone(),
1217            TraitConstraintNotSatisfied { span, .. } => span.clone(),
1218            TraitConstraintMissing { span, .. } => span.clone(),
1219            Immediate06TooLarge { span, .. } => span.clone(),
1220            Immediate12TooLarge { span, .. } => span.clone(),
1221            Immediate18TooLarge { span, .. } => span.clone(),
1222            Immediate24TooLarge { span, .. } => span.clone(),
1223            IncorrectNumberOfAsmRegisters { span, .. } => span.clone(),
1224            UnnecessaryImmediate { span, .. } => span.clone(),
1225            AmbiguousPath { span } => span.clone(),
1226            ModulePathIsNotAnExpression { span, .. } => span.clone(),
1227            UnknownType { span, .. } => span.clone(),
1228            UnknownTypeName { span, .. } => span.clone(),
1229            FileCouldNotBeRead { span, .. } => span.clone(),
1230            ImportMustBeLibrary { span, .. } => span.clone(),
1231            MoreThanOneEnumInstantiator { span, .. } => span.clone(),
1232            UnnecessaryEnumInstantiator { span, .. } => span.clone(),
1233            UnitVariantWithParenthesesEnumInstantiator { span, .. } => span.clone(),
1234            TraitNotFound { span, .. } => span.clone(),
1235            TraitNotImportedAtFunctionApplication {
1236                function_call_site_span,
1237                ..
1238            } => function_call_site_span.clone(),
1239            InvalidExpressionOnLhs { span, .. } => span.clone(),
1240            TooManyArgumentsForFunction { span, .. } => span.clone(),
1241            TooFewArgumentsForFunction { span, .. } => span.clone(),
1242            MissingParenthesesForFunction { span, .. } => span.clone(),
1243            InvalidAbiType { span, .. } => span.clone(),
1244            NotAnAbi { span, .. } => span.clone(),
1245            ImplAbiForNonContract { span, .. } => span.clone(),
1246            ConflictingImplsForTraitAndType {
1247                second_impl_span, ..
1248            } => second_impl_span.clone(),
1249            MarkerTraitExplicitlyImplemented { span, .. } => span.clone(),
1250            DuplicateDeclDefinedForType {
1251                second_impl_span, ..
1252            } => second_impl_span.clone(),
1253            IncorrectNumberOfInterfaceSurfaceFunctionParameters { span, .. } => span.clone(),
1254            ArgumentParameterTypeMismatch { span, .. } => span.clone(),
1255            RecursiveCall { span, .. } => span.clone(),
1256            RecursiveCallChain { span, .. } => span.clone(),
1257            RecursiveType { span, .. } => span.clone(),
1258            RecursiveTypeChain { span, .. } => span.clone(),
1259            GMFromExternalContext { span, .. } => span.clone(),
1260            MintFromExternalContext { span, .. } => span.clone(),
1261            BurnFromExternalContext { span, .. } => span.clone(),
1262            ContractStorageFromExternalContext { span, .. } => span.clone(),
1263            InvalidOpcodeFromPredicate { span, .. } => span.clone(),
1264            ArrayOutOfBounds { span, .. } => span.clone(),
1265            ConstantRequiresExpression { span, .. } => span.clone(),
1266            ConstantsCannotBeShadowed { name, .. } => name.span(),
1267            ConfigurablesCannotBeShadowed { name, .. } => name.span(),
1268            ConfigurablesCannotBeMatchedAgainst { name, .. } => name.span(),
1269            ConstantShadowsVariable { name, .. } => name.span(),
1270            ConstantDuplicatesConstantOrConfigurable { name, .. } => name.span(),
1271            ShadowsOtherSymbol { name } => name.span(),
1272            GenericShadowsGeneric { name } => name.span(),
1273            MatchExpressionNonExhaustive { span, .. } => span.clone(),
1274            MatchStructPatternMissingFields { span, .. } => span.clone(),
1275            MatchStructPatternMustIgnorePrivateFields { span, .. } => span.clone(),
1276            MatchArmVariableNotDefinedInAllAlternatives { variable, .. } => variable.span(),
1277            MatchArmVariableMismatchedType { variable, .. } => variable.span(),
1278            MatchedValueIsNotValid { span, .. } => span.clone(),
1279            NotAnEnum { span, .. } => span.clone(),
1280            TraitDeclPureImplImpure { span, .. } => span.clone(),
1281            TraitImplPurityMismatch { span, .. } => span.clone(),
1282            DeclIsNotAnEnum { span, .. } => span.clone(),
1283            DeclIsNotAStruct { span, .. } => span.clone(),
1284            DeclIsNotAFunction { span, .. } => span.clone(),
1285            DeclIsNotAVariable { span, .. } => span.clone(),
1286            DeclIsNotAnAbi { span, .. } => span.clone(),
1287            DeclIsNotATrait { span, .. } => span.clone(),
1288            DeclIsNotAnImplTrait { span, .. } => span.clone(),
1289            DeclIsNotATraitFn { span, .. } => span.clone(),
1290            DeclIsNotStorage { span, .. } => span.clone(),
1291            DeclIsNotAConstant { span, .. } => span.clone(),
1292            DeclIsNotATypeAlias { span, .. } => span.clone(),
1293            ImpureInNonContract { span, .. } => span.clone(),
1294            StorageAccessMismatched { span, .. } => span.clone(),
1295            ParameterRefMutabilityMismatch { span, .. } => span.clone(),
1296            IntegerTooLarge { span, .. } => span.clone(),
1297            IntegerTooSmall { span, .. } => span.clone(),
1298            IntegerContainsInvalidDigit { span, .. } => span.clone(),
1299            AbiAsSupertrait { span, .. } => span.clone(),
1300            SupertraitImplRequired { span, .. } => span.clone(),
1301            ContractCallParamRepeated { span, .. } => span.clone(),
1302            UnrecognizedContractParam { span, .. } => span.clone(),
1303            CallParamForNonContractCallMethod { span, .. } => span.clone(),
1304            StorageFieldDoesNotExist { field_name, .. } => field_name.span(),
1305            InvalidStorageOnlyTypeDecl { span, .. } => span.clone(),
1306            NoDeclaredStorage { span, .. } => span.clone(),
1307            MultipleStorageDeclarations { span, .. } => span.clone(),
1308            UnexpectedDeclaration { span, .. } => span.clone(),
1309            ContractAddressMustBeKnown { span, .. } => span.clone(),
1310            ConvertParseTree { error } => error.span(),
1311            Lex { error } => error.span(),
1312            Parse { error } => error.span.clone(),
1313            EnumNotFound { span, .. } => span.clone(),
1314            TupleIndexOutOfBounds { span, .. } => span.clone(),
1315            NonConstantDeclValue { span, .. } => span.clone(),
1316            StorageDeclarationInNonContract { span, .. } => span.clone(),
1317            IntrinsicUnsupportedArgType { span, .. } => span.clone(),
1318            IntrinsicIncorrectNumArgs { span, .. } => span.clone(),
1319            IntrinsicIncorrectNumTArgs { span, .. } => span.clone(),
1320            IntrinsicArgNotConstant { span, .. } => span.clone(),
1321            BreakOutsideLoop { span } => span.clone(),
1322            ContinueOutsideLoop { span } => span.clone(),
1323            ContractIdValueNotALiteral { span } => span.clone(),
1324            RefMutableNotAllowedInMain { span, .. } => span.clone(),
1325            InitializedRegisterReassignment { span, .. } => span.clone(),
1326            DisallowedControlFlowInstruction { span, .. } => span.clone(),
1327            CallingPrivateLibraryMethod { span, .. } => span.clone(),
1328            DisallowedIntrinsicInPredicate { span, .. } => span.clone(),
1329            CoinsPassedToNonPayableMethod { span, .. } => span.clone(),
1330            TraitImplPayabilityMismatch { span, .. } => span.clone(),
1331            ConfigurableInLibrary { span } => span.clone(),
1332            MultipleApplicableItemsInScope { span, .. } => span.clone(),
1333            NonStrGenericType { span } => span.clone(),
1334            CannotBeEvaluatedToConst { span } => span.clone(),
1335            ContractCallsItsOwnMethod { span } => span.clone(),
1336            AbiShadowsSuperAbiMethod { span, .. } => span.clone(),
1337            ConflictingSuperAbiMethods { span, .. } => span.clone(),
1338            AssociatedTypeNotSupportedInAbi { span, .. } => span.clone(),
1339            AbiSupertraitMethodCallAsContractCall { span, .. } => span.clone(),
1340            FunctionSelectorClash { span, .. } => span.clone(),
1341            TypeNotAllowed { span, .. } => span.clone(),
1342            ExpectedStringLiteral { span } => span.clone(),
1343            TypeIsNotValidAsImplementingFor { span, .. } => span.clone(),
1344            UninitRegisterInAsmBlockBeingRead { span } => span.clone(),
1345            ExpressionCannotBeDereferenced { span, .. } => span.clone(),
1346            FallbackFnsAreContractOnly { span } => span.clone(),
1347            FallbackFnsCannotHaveParameters { span } => span.clone(),
1348            CouldNotGenerateEntry { span } => span.clone(),
1349            CouldNotGenerateEntryMissingStd { span } => span.clone(),
1350            CouldNotGenerateEntryMissingImpl { span, .. } => span.clone(),
1351            CannotBeEvaluatedToConfigurableSizeUnknown { span } => span.clone(),
1352            EncodingUnsupportedType { span } => span.clone(),
1353            ConfigurableMissingAbiDecodeInPlace { span } => span.clone(),
1354            ABIInvalidName { span, .. } => span.clone(),
1355            ABIDuplicateName { span, .. } => span.clone(),
1356            ABIHashCollision { span, .. } => span.clone(),
1357            InvalidRangeEndGreaterThanStart { span, .. } => span.clone(),
1358            TypeMustBeKnownAtThisPoint { span, .. } => span.clone(),
1359            MultipleImplsSatisfyingTraitForType { span, .. } => span.clone(),
1360            MultipleContractsMethodsWithTheSameName { spans } => spans[0].clone(),
1361            ErrorTypeEnumHasNonErrorVariants { enum_name, .. } => enum_name.span(),
1362            ErrorAttributeInNonErrorEnum {
1363                enum_variant_name, ..
1364            } => enum_variant_name.span(),
1365            PanicExpressionArgumentIsNotError { span, .. } => span.clone(),
1366            MaxNumOfPanicExpressionsReached { span, .. } => span.clone(),
1367            MaxNumOfPanickingCallsReached { span, .. } => span.clone(),
1368            IndexedFieldInNonEventStruct { field_name, .. } => field_name.span(),
1369            IndexedFieldMustPrecedeNonIndexedField { field_name } => field_name.span(),
1370            IndexedFieldIsNotFixedSizeABIType { field_name } => field_name.span(),
1371            IndexedFieldOffsetTooLarge { field_name } => field_name.span(),
1372            IncoherentImplDueToOrphanRule { span, .. } => span.clone(),
1373        }
1374    }
1375}
1376
1377// When implementing diagnostics, follow these two guidelines outlined in the Expressive Diagnostics RFC:
1378// - Guide-level explanation: https://github.com/FuelLabs/sway-rfcs/blob/master/rfcs/0011-expressive-diagnostics.md#guide-level-explanation
1379// - Wording guidelines: https://github.com/FuelLabs/sway-rfcs/blob/master/rfcs/0011-expressive-diagnostics.md#wording-guidelines
1380// For concrete examples, look at the existing diagnostics.
1381//
1382// The issue and the hints are not displayed if set to `Span::dummy()`.
1383//
1384// NOTE: Issue level should actually be the part of the reason. But it would complicate handling of labels in the transitional
1385//       period when we still have "old-style" diagnostics.
1386//       Let's leave it like this. Refactoring currently doesn't pay off.
1387//       And our #[error] macro will anyhow encapsulate it and ensure consistency.
1388impl ToDiagnostic for CompileError {
1389    fn to_diagnostic(&self, source_engine: &SourceEngine) -> Diagnostic {
1390        let code = Code::semantic_analysis;
1391        use CompileError::*;
1392        match self {
1393            ConstantsCannotBeShadowed { shadowing_source, name, constant_span, constant_decl_span, is_alias } => Diagnostic {
1394                reason: Some(Reason::new(code(1), "Constants cannot be shadowed".to_string())),
1395                issue: Issue::error(
1396                    source_engine,
1397                    name.span(),
1398                    format!(
1399                        // Variable "x" shadows constant with of same name.
1400                        //  or
1401                        // Constant "x" shadows imported constant of the same name.
1402                        //  or
1403                        // ...
1404                        "{shadowing_source} \"{name}\" shadows {}constant of the same name.",
1405                        if constant_decl_span.clone() != Span::dummy() { "imported " } else { "" }
1406                    )
1407                ),
1408                hints: vec![
1409                    Hint::info(
1410                        source_engine,
1411                        constant_span.clone(),
1412                        format!(
1413                            // Shadowed constant "x" is declared here.
1414                            //  or
1415                            // Shadowed constant "x" gets imported here.
1416                            //  or
1417                            // ...
1418                            "Shadowed constant \"{name}\" {} here{}.",
1419                            if constant_decl_span.clone() != Span::dummy() { "gets imported" } else { "is declared" },
1420                            if *is_alias { " as alias" } else { "" }
1421                        )
1422                    ),
1423                    if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1424                        Hint::help(
1425                            source_engine,
1426                            name.span(),
1427                            format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1428                        )
1429                    } else {
1430                        Hint::none()
1431                    },
1432                    Hint::info( // Ignored if the `constant_decl_span` is `Span::dummy()`.
1433                        source_engine,
1434                        constant_decl_span.clone(),
1435                        format!("This is the original declaration of the imported constant \"{name}\".")
1436                    ),
1437                ],
1438                help: vec![
1439                    "Unlike variables, constants cannot be shadowed by other constants or variables.".to_string(),
1440                    match (shadowing_source, *constant_decl_span != Span::dummy()) {
1441                        (LetVar | PatternMatchingStructFieldVar, false) => format!("Consider renaming either the {} \"{name}\" or the constant \"{name}\".", 
1442                            format!("{shadowing_source}").to_lowercase(),
1443                        ),
1444                        (Const, false) => "Consider renaming one of the constants.".to_string(),
1445                        (shadowing_source, true) => format!(
1446                            "Consider renaming the {} \"{name}\" or using {} for the imported constant.",
1447                            format!("{shadowing_source}").to_lowercase(),
1448                            if *is_alias { "a different alias" } else { "an alias" }
1449                        ),
1450                    },
1451                    if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1452                        format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1453                    } else {
1454                        Diagnostic::help_none()
1455                    }
1456                ],
1457            },
1458            ConfigurablesCannotBeShadowed { shadowing_source, name, configurable_span } => Diagnostic {
1459                reason: Some(Reason::new(code(1), "Configurables cannot be shadowed".to_string())),
1460                issue: Issue::error(
1461                    source_engine,
1462                    name.span(),
1463                    format!("{shadowing_source} \"{name}\" shadows configurable of the same name.")
1464                ),
1465                hints: vec![
1466                    Hint::info(
1467                        source_engine,
1468                        configurable_span.clone(),
1469                        format!("Shadowed configurable \"{name}\" is declared here.")
1470                    ),
1471                    if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1472                        Hint::help(
1473                            source_engine,
1474                            name.span(),
1475                            format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1476                        )
1477                    } else {
1478                        Hint::none()
1479                    },
1480                ],
1481                help: vec![
1482                    "Unlike variables, configurables cannot be shadowed by constants or variables.".to_string(),
1483                    format!(
1484                        "Consider renaming either the {} \"{name}\" or the configurable \"{name}\".",
1485                        format!("{shadowing_source}").to_lowercase()
1486                    ),
1487                    if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1488                        format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1489                    } else {
1490                        Diagnostic::help_none()
1491                    }
1492                ],
1493            },
1494            ConfigurablesCannotBeMatchedAgainst { name, configurable_span } => Diagnostic {
1495                reason: Some(Reason::new(code(1), "Configurables cannot be matched against".to_string())),
1496                issue: Issue::error(
1497                    source_engine,
1498                    name.span(),
1499                    format!("\"{name}\" is a configurable and configurables cannot be matched against.")
1500                ),
1501                hints: {
1502                    let mut hints = vec![
1503                        Hint::info(
1504                            source_engine,
1505                            configurable_span.clone(),
1506                            format!("Configurable \"{name}\" is declared here.")
1507                        ),
1508                    ];
1509
1510                    hints.append(&mut Hint::multi_help(source_engine, &name.span(), vec![
1511                        format!("Are you trying to define a pattern variable named \"{name}\"?"),
1512                        format!("In that case, use some other name for the pattern variable,"),
1513                        format!("or consider renaming the configurable \"{name}\"."),
1514                    ]));
1515
1516                    hints
1517                },
1518                help: vec![
1519                    "Unlike constants, configurables cannot be matched against in pattern matching.".to_string(),
1520                    "That's not possible, because patterns to match against must be compile-time constants.".to_string(),
1521                    "Configurables are run-time constants. Their values are defined during the deployment.".to_string(),
1522                    Diagnostic::help_empty_line(),
1523                    "To test against a configurable, consider:".to_string(),
1524                    format!("{}- replacing the `match` expression with `if-else`s altogether.", Indent::Single),
1525                    format!("{}- matching against a variable and comparing that variable afterwards with the configurable.", Indent::Single),
1526                    format!("{}  E.g., instead of:", Indent::Single),
1527                    Diagnostic::help_empty_line(),
1528                    format!("{}  SomeStruct {{ x: A_CONFIGURABLE, y: 42 }} => {{", Indent::Double),
1529                    format!("{}      do_something();", Indent::Double),
1530                    format!("{}  }}", Indent::Double),
1531                    Diagnostic::help_empty_line(),
1532                    format!("{}  to have:", Indent::Single),
1533                    Diagnostic::help_empty_line(),
1534                    format!("{}  SomeStruct {{ x, y: 42 }} => {{", Indent::Double),
1535                    format!("{}      if x == A_CONFIGURABLE {{", Indent::Double),
1536                    format!("{}          do_something();", Indent::Double),
1537                    format!("{}      }}", Indent::Double),
1538                    format!("{}  }}", Indent::Double),
1539                ],
1540            },
1541            ConstantShadowsVariable { name , variable_span } => Diagnostic {
1542                reason: Some(Reason::new(code(1), "Constants cannot shadow variables".to_string())),
1543                issue: Issue::error(
1544                    source_engine,
1545                    name.span(),
1546                    format!("Constant \"{name}\" shadows variable of the same name.")
1547                ),
1548                hints: vec![
1549                    Hint::info(
1550                        source_engine,
1551                        variable_span.clone(),
1552                        format!("This is the shadowed variable \"{name}\".")
1553                    ),
1554                ],
1555                help: vec![
1556                    format!("Variables can shadow other variables, but constants cannot."),
1557                    format!("Consider renaming either the variable or the constant."),
1558                ],
1559            },
1560            ConstantDuplicatesConstantOrConfigurable { existing_constant_or_configurable, new_constant_or_configurable, name, existing_span } => Diagnostic {
1561                reason: Some(Reason::new(code(1), match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1562                    ("Constant", "Constant") => "Constant of the same name already exists".to_string(),
1563                    ("Constant", "Configurable") => "Constant of the same name as configurable already exists".to_string(),
1564                    ("Configurable", "Constant") => "Configurable of the same name as constant already exists".to_string(),
1565                    _ => unreachable!("We can have only the listed combinations. Configurable duplicating configurable is not a valid combination.")
1566                })),
1567                issue: Issue::error(
1568                    source_engine,
1569                    name.span(),
1570                    format!("{new_constant_or_configurable} \"{name}\" has the same name as an already declared {}.",
1571                        existing_constant_or_configurable.to_lowercase()
1572                    )
1573                ),
1574                hints: vec![
1575                    Hint::info(
1576                        source_engine,
1577                        existing_span.clone(),
1578                        format!("{existing_constant_or_configurable} \"{name}\" is {}declared here.",
1579                            // If a constant clashes with an already declared constant.
1580                            if existing_constant_or_configurable == new_constant_or_configurable {
1581                                "already "
1582                            } else {
1583                                ""
1584                            }
1585                        )
1586                    ),
1587                ],
1588                help: vec![
1589                    match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1590                        ("Constant", "Constant") => "Consider renaming one of the constants, or in case of imported constants, using an alias.".to_string(),
1591                        _ => "Consider renaming either the configurable or the constant, or in case of an imported constant, using an alias.".to_string(),
1592                    },
1593                ],
1594            },
1595            MultipleDefinitionsOfMatchArmVariable { match_value, match_type, first_definition, first_definition_is_struct_field, duplicate, duplicate_is_struct_field } => Diagnostic {
1596                reason: Some(Reason::new(code(1), "Match pattern variable is already defined".to_string())),
1597                issue: Issue::error(
1598                    source_engine,
1599                    duplicate.clone(),
1600                    format!("Variable \"{}\" is already defined in this match arm.", first_definition.as_str())
1601                ),
1602                hints: vec![
1603                    Hint::help(
1604                        source_engine,
1605                        if *duplicate_is_struct_field {
1606                            duplicate.clone()
1607                        }
1608                        else {
1609                            Span::dummy()
1610                        },
1611                        format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str())
1612                    ),
1613                    Hint::info(
1614                        source_engine,
1615                        first_definition.clone(),
1616                        format!(
1617                            "This {}is the first definition of the variable \"{}\".",
1618                            if *first_definition_is_struct_field {
1619                                format!("struct field \"{}\" ", first_definition.as_str())
1620                            }
1621                            else {
1622                                "".to_string()
1623                            },
1624                            first_definition.as_str(),
1625                        )
1626                    ),
1627                    Hint::help(
1628                        source_engine,
1629                        if *first_definition_is_struct_field && !*duplicate_is_struct_field {
1630                            first_definition.clone()
1631                        }
1632                        else {
1633                            Span::dummy()
1634                        },
1635                        format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str()),
1636                    ),
1637                    Hint::info(
1638                        source_engine,
1639                        match_value.clone(),
1640                        format!("The expression to match on is of type \"{match_type}\".")
1641                    ),
1642                ],
1643                help: vec![
1644                    format!("Variables used in match arm patterns must be unique within a pattern, except in alternatives."),
1645                    match (*first_definition_is_struct_field, *duplicate_is_struct_field) {
1646                        (true, true) => format!("Consider declaring a variable with different name for either of the fields. E.g., `{0}: var_{0}`.", first_definition.as_str()),
1647                        (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()),
1648                        (false, false) => "Consider renaming either of the variables.".to_string(),
1649                    },
1650                ],
1651            },
1652            MatchArmVariableMismatchedType { match_value, match_type, variable, first_definition, expected, received } => Diagnostic {
1653                reason: Some(Reason::new(code(1), "Match pattern variable has mismatched type".to_string())),
1654                issue: Issue::error(
1655                    source_engine,
1656                    variable.span(),
1657                    format!("Variable \"{variable}\" is expected to be of type \"{expected}\", but is \"{received}\".")
1658                ),
1659                hints: vec![
1660                    Hint::info(
1661                        source_engine,
1662                        first_definition.clone(),
1663                        format!("\"{variable}\" is first defined here with the type \"{}\".",
1664                            short_name(expected),
1665                        )
1666                    ),
1667                    Hint::info(
1668                        source_engine,
1669                        match_value.clone(),
1670                        format!("The expression to match on is of type \"{match_type}\".")
1671                    ),
1672                ],
1673                help: vec![
1674                    format!("In the same match arm, a variable must have the same type in all alternatives."),
1675                ],
1676            },
1677            MatchArmVariableNotDefinedInAllAlternatives { match_value, match_type, variable, missing_in_alternatives} => Diagnostic {
1678                reason: Some(Reason::new(code(1), "Match pattern variable is not defined in all alternatives".to_string())),
1679                issue: Issue::error(
1680                    source_engine,
1681                    variable.span(),
1682                    format!("Variable \"{variable}\" is not defined in all alternatives.")
1683                ),
1684                hints: {
1685                    let mut hints = vec![
1686                        Hint::info(
1687                            source_engine,
1688                            match_value.clone(),
1689                            format!("The expression to match on is of type \"{match_type}\".")
1690                        ),
1691                    ];
1692
1693                    for (i, alternative) in missing_in_alternatives.iter().enumerate() {
1694                        hints.push(
1695                            Hint::info(
1696                                source_engine,
1697                                alternative.clone(),
1698                                format!("\"{variable}\" is {}missing in this alternative.", if i != 0 { "also " } else { "" }),
1699                            )
1700                        )
1701                    }
1702
1703                    hints
1704                },
1705                help: vec![
1706                    format!("Consider removing the variable \"{variable}\" altogether, or adding it to all alternatives."),
1707                ],
1708            },
1709            MatchStructPatternMissingFields { missing_fields, missing_fields_are_public, struct_name, struct_decl_span, total_number_of_fields, span } => Diagnostic {
1710                reason: Some(Reason::new(code(1), "Struct pattern has missing fields".to_string())),
1711                issue: Issue::error(
1712                    source_engine,
1713                    span.clone(),
1714                    format!("Struct pattern is missing the {}field{} {}.",
1715                        if *missing_fields_are_public { "public " } else { "" },
1716                        plural_s(missing_fields.len()),
1717                        sequence_to_str(missing_fields, Enclosing::DoubleQuote, 2)
1718                    )
1719                ),
1720                hints: vec![
1721                    Hint::help(
1722                        source_engine,
1723                        span.clone(),
1724                        "Struct pattern must either contain or ignore each struct field.".to_string()
1725                    ),
1726                    Hint::info(
1727                        source_engine,
1728                        struct_decl_span.clone(),
1729                        format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1730                            num_to_str(*total_number_of_fields),
1731                            plural_s(*total_number_of_fields),
1732                        )
1733                    ),
1734                ],
1735                help: vec![
1736                    // Consider ignoring the field "x_1" by using the `_` pattern: `x_1: _`.
1737                    //  or
1738                    // Consider ignoring individual fields by using the `_` pattern. E.g, `x_1: _`.
1739                    format!("Consider ignoring {} field{} {}by using the `_` pattern{} `{}: _`.",
1740                        singular_plural(missing_fields.len(), "the", "individual"),
1741                        plural_s(missing_fields.len()),
1742                        singular_plural(missing_fields.len(), &format!("\"{}\" ", missing_fields[0]), ""),
1743                        singular_plural(missing_fields.len(), ":", ". E.g.,"),
1744                        missing_fields[0]
1745                    ),
1746                    "Alternatively, consider ignoring all the missing fields by ending the struct pattern with `..`.".to_string(),
1747                ],
1748            },
1749            MatchStructPatternMustIgnorePrivateFields { private_fields, struct_name, struct_decl_span, all_fields_are_private, span } => Diagnostic {
1750                reason: Some(Reason::new(code(1), "Struct pattern must ignore inaccessible private fields".to_string())),
1751                issue: Issue::error(
1752                    source_engine,
1753                    span.clone(),
1754                    format!("Struct pattern must ignore inaccessible private field{} {}.",
1755                        plural_s(private_fields.len()),
1756                        sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1757                    )
1758                ),
1759                hints: vec![
1760                    Hint::help(
1761                        source_engine,
1762                        span.clone(),
1763                        format!("To ignore the private field{}, end the struct pattern with `..`.",
1764                            plural_s(private_fields.len()),
1765                        )
1766                    ),
1767                    Hint::info(
1768                        source_engine,
1769                        struct_decl_span.clone(),
1770                        format!("Struct \"{struct_name}\" is declared here, and has {}.",
1771                            if *all_fields_are_private {
1772                                "all private fields".to_string()
1773                            } else {
1774                                format!("private field{} {}",
1775                                    plural_s(private_fields.len()),
1776                                    sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1777                                )
1778                            }
1779                        )
1780                    ),
1781                ],
1782                help: vec![],
1783            },
1784            TraitNotImportedAtFunctionApplication { trait_name, function_name, function_call_site_span, trait_constraint_span, trait_candidates } => {
1785                // Make candidates order deterministic.
1786                let mut trait_candidates = trait_candidates.clone();
1787                trait_candidates.sort();
1788                let trait_candidates = &trait_candidates; // Remove mutability.
1789
1790                Diagnostic {
1791                    reason: Some(Reason::new(code(1), "Trait is not imported".to_string())),
1792                    issue: Issue::error(
1793                        source_engine,
1794                        function_call_site_span.clone(),
1795                        format!(
1796                            "Trait \"{trait_name}\" is not imported {}when calling \"{function_name}\".",
1797                            get_file_name(source_engine, function_call_site_span.source_id())
1798                                .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1799                        )
1800                    ),
1801                    hints: {
1802                        let mut hints = vec![
1803                            Hint::help(
1804                                source_engine,
1805                                function_call_site_span.clone(),
1806                                format!("This import is needed because \"{function_name}\" requires \"{trait_name}\" in one of its trait constraints.")
1807                            ),
1808                            Hint::info(
1809                                source_engine,
1810                                trait_constraint_span.clone(),
1811                                format!("In the definition of \"{function_name}\", \"{trait_name}\" is used in this trait constraint.")
1812                            ),
1813                        ];
1814
1815                        match trait_candidates.len() {
1816                            // If no candidates are found, that means that an alias was used in the trait constraint definition.
1817                            // The way how constraint checking works now, the trait will not be found when we try to check if
1818                            // the trait constraints are satisfied for type, and we will never end up in this case here.
1819                            // So we will simply ignore it.
1820                            0 => (),
1821                            // The most common case. Exactly one known trait with the given name.
1822                            1 => hints.push(Hint::help(
1823                                    source_engine,
1824                                    function_call_site_span.clone(),
1825                                    format!(
1826                                        "Import the \"{trait_name}\" trait {}by using: `use {};`.",
1827                                        get_file_name(source_engine, function_call_site_span.source_id())
1828                                            .map_or("".to_string(), |file_name| format!("into \"{file_name}\" ")),
1829                                        trait_candidates[0]
1830                                    )
1831                                )),
1832                            // Unlikely (for now) case of having several traits with the same name.
1833                            _ => hints.push(Hint::help(
1834                                    source_engine,
1835                                    function_call_site_span.clone(),
1836                                    format!(
1837                                        "To import the proper \"{trait_name}\" {}follow the detailed instructions given below.",
1838                                        get_file_name(source_engine, function_call_site_span.source_id())
1839                                            .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1840                                    )
1841                                )),
1842                        }
1843
1844                        hints
1845                    },
1846                    help: {
1847                        let mut help = vec![];
1848
1849                        if trait_candidates.len() > 1 {
1850                            help.push(format!("There are these {} traits with the name \"{trait_name}\" available in the modules:", num_to_str(trait_candidates.len())));
1851                            for trait_candidate in trait_candidates.iter() {
1852                                help.push(format!("{}- {trait_candidate}", Indent::Single));
1853                            }
1854                            help.push("To import the proper one follow these steps:".to_string());
1855                            help.push(format!(
1856                                "{}1. Look at the definition of the \"{function_name}\"{}.",
1857                                    Indent::Single,
1858                                    get_file_name(source_engine, trait_constraint_span.source_id())
1859                                        .map_or("".to_string(), |file_name| format!(" in the \"{file_name}\""))
1860                            ));
1861                            help.push(format!(
1862                                "{}2. Detect which exact \"{trait_name}\" is used in the trait constraint in the \"{function_name}\".",
1863                                Indent::Single
1864                            ));
1865                            help.push(format!(
1866                                "{}3. Import that \"{trait_name}\"{}.",
1867                                Indent::Single,
1868                                get_file_name(source_engine, function_call_site_span.source_id())
1869                                    .map_or("".to_string(), |file_name| format!(" into \"{file_name}\""))
1870                            ));
1871                            help.push(format!("{} E.g., assuming it is the first one on the list, use: `use {};`", Indent::Double, trait_candidates[0]));
1872                        }
1873
1874                        help
1875                    },
1876                }
1877            },
1878            // TODO: (REFERENCES) Extend error messages to pointers, once typed pointers are defined and can be dereferenced.
1879            ExpressionCannotBeDereferenced { expression_type, span } => Diagnostic {
1880                reason: Some(Reason::new(code(1), "Expression cannot be dereferenced".to_string())),
1881                issue: Issue::error(
1882                    source_engine,
1883                    span.clone(),
1884                    format!("This expression cannot be dereferenced, because it is of type \"{expression_type}\", which is not a reference type.")
1885                ),
1886                hints: vec![
1887                    Hint::help(
1888                        source_engine,
1889                        span.clone(),
1890                        "In Sway, only references can be dereferenced.".to_string()
1891                    ),
1892                    Hint::help(
1893                        source_engine,
1894                        span.clone(),
1895                        "Are you missing the reference operator `&` somewhere in the code?".to_string()
1896                    ),
1897                ],
1898                help: vec![],
1899            },
1900            StructInstantiationMissingFields { field_names, struct_name, span, struct_decl_span, total_number_of_fields } => Diagnostic {
1901                reason: Some(Reason::new(code(1), "Struct instantiation has missing fields".to_string())),
1902                issue: Issue::error(
1903                    source_engine,
1904                    span.clone(),
1905                    format!("Instantiation of the struct \"{struct_name}\" is missing the field{} {}.",
1906                            plural_s(field_names.len()),
1907                            sequence_to_str(field_names, Enclosing::DoubleQuote, 2)
1908                        )
1909                ),
1910                hints: vec![
1911                    Hint::help(
1912                        source_engine,
1913                        span.clone(),
1914                        "Struct instantiation must initialize all the fields of the struct.".to_string()
1915                    ),
1916                    Hint::info(
1917                        source_engine,
1918                        struct_decl_span.clone(),
1919                        format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1920                            num_to_str(*total_number_of_fields),
1921                            plural_s(*total_number_of_fields),
1922                        )
1923                    ),
1924                ],
1925                help: vec![],
1926            },
1927            StructCannotBeInstantiated { struct_name, span, struct_decl_span, private_fields, constructors, all_fields_are_private, is_in_storage_declaration, struct_can_be_changed } => Diagnostic {
1928                reason: Some(Reason::new(code(1), "Struct cannot be instantiated due to inaccessible private fields".to_string())),
1929                issue: Issue::error(
1930                    source_engine,
1931                    span.clone(),
1932                    format!("\"{struct_name}\" cannot be {}instantiated in this {}, due to {}inaccessible private field{}.",
1933                        if *is_in_storage_declaration { "" } else { "directly " },
1934                        if *is_in_storage_declaration { "storage declaration" } else { "module" },
1935                        singular_plural(private_fields.len(), "an ", ""),
1936                        plural_s(private_fields.len())
1937                    )
1938                ),
1939                hints: vec![
1940                    Hint::help(
1941                        source_engine,
1942                        span.clone(),
1943                        format!("Inaccessible field{} {} {}.",
1944                            plural_s(private_fields.len()),
1945                            is_are(private_fields.len()),
1946                            sequence_to_str(private_fields, Enclosing::DoubleQuote, 5)
1947                        )
1948                    ),
1949                    Hint::help(
1950                        source_engine,
1951                        span.clone(),
1952                        if *is_in_storage_declaration {
1953                            "Structs with private fields can be instantiated in storage declarations only if they are declared in the same module as the storage.".to_string()
1954                        } else {
1955                            "Structs with private fields can be instantiated only within the module in which they are declared.".to_string()
1956                        }
1957                    ),
1958                    if *is_in_storage_declaration {
1959                        Hint::help(
1960                            source_engine,
1961                            span.clone(),
1962                            "They can still be initialized in storage declarations if they have public constructors that evaluate to a constant.".to_string()
1963                        )
1964                    } else {
1965                        Hint::none()
1966                    },
1967                    if *is_in_storage_declaration {
1968                        Hint::help(
1969                            source_engine,
1970                            span.clone(),
1971                            "They can always be stored in storage by using the `read` and `write` functions provided in the `std::storage::storage_api`.".to_string()
1972                        )
1973                    } else {
1974                        Hint::none()
1975                    },
1976                    if !*is_in_storage_declaration && !constructors.is_empty() {
1977                        Hint::help(
1978                            source_engine,
1979                            span.clone(),
1980                            format!("\"{struct_name}\" can be instantiated via public constructors suggested below.")
1981                        )
1982                    } else {
1983                        Hint::none()
1984                    },
1985                    Hint::info(
1986                        source_engine,
1987                        struct_decl_span.clone(),
1988                        format!("Struct \"{struct_name}\" is declared here, and has {}.",
1989                            if *all_fields_are_private {
1990                                "all private fields".to_string()
1991                            } else {
1992                                format!("private field{} {}",
1993                                    plural_s(private_fields.len()),
1994                                    sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1995                                )
1996                            }
1997                        )
1998                    ),
1999                ],
2000                help: {
2001                    let mut help = vec![];
2002
2003                    if *is_in_storage_declaration {
2004                        help.push(format!("Consider initializing \"{struct_name}\" by finding an available constructor that evaluates to a constant{}.",
2005                            if *struct_can_be_changed {
2006                                ", or implement a new one"
2007                            } else {
2008                                ""
2009                            }
2010                        ));
2011
2012                        if !constructors.is_empty() {
2013                            help.push("Check these already available constructors. They might evaluate to a constant:".to_string());
2014                            // We always expect a very few candidates here. So let's list all of them by using `usize::MAX`.
2015                            for constructor in sequence_to_list(constructors, Indent::Single, usize::MAX) {
2016                                help.push(constructor);
2017                            }
2018                        };
2019
2020                        help.push(Diagnostic::help_empty_line());
2021
2022                        help.push(format!("Or you can always store instances of \"{struct_name}\" in the contract storage, by using the `std::storage::storage_api`:"));
2023                        help.push(format!("{}use std::storage::storage_api::{{read, write}};", Indent::Single));
2024                        help.push(format!("{}write(STORAGE_KEY, 0, my_{});", Indent::Single, to_snake_case(struct_name.as_str())));
2025                        help.push(format!("{}let my_{}_option = read::<{struct_name}>(STORAGE_KEY, 0);", Indent::Single, to_snake_case(struct_name.as_str())));
2026                    }
2027                    else if !constructors.is_empty() {
2028                        help.push(format!("Consider instantiating \"{struct_name}\" by using one of the available constructors{}:",
2029                            if *struct_can_be_changed {
2030                                ", or implement a new one"
2031                            } else {
2032                                ""
2033                            }
2034                        ));
2035                        for constructor in sequence_to_list(constructors, Indent::Single, 5) {
2036                            help.push(constructor);
2037                        }
2038                    }
2039
2040                    if *struct_can_be_changed {
2041                        if *is_in_storage_declaration || !constructors.is_empty() {
2042                            help.push(Diagnostic::help_empty_line());
2043                        }
2044
2045                        if !*is_in_storage_declaration && constructors.is_empty() {
2046                            help.push(format!("Consider implementing a public constructor for \"{struct_name}\"."));
2047                        };
2048
2049                        help.push(
2050                            // Alternatively, consider declaring the field "f" as public in "Struct": `pub f: ...,`.
2051                            //  or
2052                            // Alternatively, consider declaring the fields "f" and "g" as public in "Struct": `pub <field>: ...,`.
2053                            //  or
2054                            // Alternatively, consider declaring all fields as public in "Struct": `pub <field>: ...,`.
2055                            format!("Alternatively, consider declaring {} as public in \"{struct_name}\": `pub {}: ...,`.",
2056                                if *all_fields_are_private {
2057                                    "all fields".to_string()
2058                                } else {
2059                                    format!("{} {}",
2060                                        singular_plural(private_fields.len(), "the field", "the fields"),
2061                                        sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
2062                                    )
2063                                },
2064                                if *all_fields_are_private {
2065                                    "<field>".to_string()
2066                                } else {
2067                                    match &private_fields[..] {
2068                                        [field] => format!("{field}"),
2069                                        _ => "<field>".to_string(),
2070                                    }
2071                                },
2072                            )
2073                        )
2074                    };
2075
2076                    help
2077                }
2078            },
2079            StructFieldIsPrivate { field_name, struct_name, field_decl_span, struct_can_be_changed, usage_context } => Diagnostic {
2080                reason: Some(Reason::new(code(1), "Private struct field is inaccessible".to_string())),
2081                issue: Issue::error(
2082                    source_engine,
2083                    field_name.span(),
2084                    format!("Private field \"{field_name}\" {}is inaccessible in this module.",
2085                        match usage_context {
2086                            StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => "".to_string(),
2087                            StorageAccess | StructFieldAccess => format!("of the struct \"{struct_name}\" "),
2088                        }
2089                    )
2090                ),
2091                hints: vec![
2092                    Hint::help(
2093                        source_engine,
2094                        field_name.span(),
2095                        format!("Private fields can only be {} within the module in which their struct is declared.",
2096                            match usage_context {
2097                                StructInstantiation { .. } | StorageDeclaration { .. } => "initialized",
2098                                StorageAccess | StructFieldAccess => "accessed",
2099                                PatternMatching { .. } => "matched",
2100                            }
2101                        )
2102                    ),
2103                    if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2104                        Hint::help(
2105                            source_engine,
2106                            field_name.span(),
2107                            "Otherwise, they must be ignored by ending the struct pattern with `..`.".to_string()
2108                        )
2109                    } else {
2110                        Hint::none()
2111                    },
2112                    Hint::info(
2113                        source_engine,
2114                        field_decl_span.clone(),
2115                        format!("Field \"{field_name}\" {}is declared here as private.",
2116                            match usage_context {
2117                                StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => format!("of the struct \"{struct_name}\" "),
2118                                StorageAccess | StructFieldAccess => "".to_string(),
2119                            }
2120                        )
2121                    ),
2122                ],
2123                help: vec![
2124                    if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2125                        format!("Consider removing the field \"{field_name}\" from the struct pattern, and ending the pattern with `..`.")
2126                    } else {
2127                        Diagnostic::help_none()
2128                    },
2129                    if *struct_can_be_changed {
2130                        match usage_context {
2131                            StorageAccess | StructFieldAccess | PatternMatching { .. } => {
2132                                format!("{} declaring the field \"{field_name}\" as public in \"{struct_name}\": `pub {field_name}: ...,`.",
2133                                    if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2134                                        "Alternatively, consider"
2135                                    } else {
2136                                        "Consider"
2137                                    }
2138                                )
2139                            },
2140                            // For all other usages, detailed instructions are already given in specific messages.
2141                            _ => Diagnostic::help_none(),
2142                        }
2143                    } else {
2144                        Diagnostic::help_none()
2145                    },
2146                ],
2147            },
2148            StructFieldDoesNotExist { field_name, available_fields, is_public_struct_access, struct_name, struct_decl_span, struct_is_empty, usage_context } => Diagnostic {
2149                reason: Some(Reason::new(code(1), "Struct field does not exist".to_string())),
2150                issue: Issue::error(
2151                    source_engine,
2152                    field_name.span(),
2153                    format!("Field \"{field_name}\" does not exist in the struct \"{struct_name}\".")
2154                ),
2155                hints: {
2156                    let public = if *is_public_struct_access { "public " } else { "" };
2157
2158                    let (hint, show_struct_decl) = if *struct_is_empty {
2159                        (Some(format!("\"{struct_name}\" is an empty struct. It doesn't have any fields.")), false)
2160                    }
2161                    // If the struct anyhow cannot be instantiated (in the struct instantiation or storage declaration),
2162                    // we don't show any additional hints.
2163                    // Showing any available fields would be inconsistent and misleading, because they anyhow cannot be used.
2164                    // Besides, "Struct cannot be instantiated" error will provide all the explanations and suggestions.
2165                    else if (matches!(usage_context, StorageAccess) && *is_public_struct_access && available_fields.is_empty())
2166                            ||
2167                            (matches!(usage_context, StructInstantiation { struct_can_be_instantiated: false } | StorageDeclaration { struct_can_be_instantiated: false })) {
2168                        // If the struct anyhow cannot be instantiated in the storage, don't show any additional hint
2169                        // if there is an attempt to access a non existing field of such non-instantiable struct.
2170                        //   or
2171                        // Likewise, if we are in the struct instantiation or storage declaration and the struct
2172                        // cannot be instantiated.
2173                        (None, false)
2174                    } else if !available_fields.is_empty() {
2175                        // In all other cases, show the available fields.
2176                        const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2177                        match &available_fields[..] {
2178                            [field] => (Some(format!("Only available {public}field is \"{field}\".")), false),
2179                            _ => (Some(format!("Available {public}fields are {}.", sequence_to_str(available_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY))),
2180                                    available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2181                                ),
2182                        }
2183                    }
2184                    else {
2185                        (None, false)
2186                    };
2187
2188                    let mut hints = vec![];
2189
2190                    if let Some(hint) = hint {
2191                        hints.push(Hint::help(source_engine, field_name.span(), hint));
2192                    };
2193
2194                    if show_struct_decl {
2195                        hints.push(Hint::info(
2196                            source_engine,
2197                            struct_decl_span.clone(),
2198                            format!("Struct \"{struct_name}\" is declared here, and has {} {public}fields.",
2199                                num_to_str(available_fields.len())
2200                            )
2201                        ));
2202                    }
2203
2204                    hints
2205                },
2206                help: vec![],
2207            },
2208            StructFieldDuplicated { field_name, duplicate } => Diagnostic {
2209                reason: Some(Reason::new(code(1), "Struct field has multiple definitions".to_string())),
2210                issue: Issue::error(
2211                    source_engine,
2212                    field_name.span(),
2213                    format!("Field \"{field_name}\" has multiple definitions.")
2214                ),
2215                hints: {
2216                    vec![
2217                        Hint::info(
2218                            source_engine,
2219                            duplicate.span(),
2220                            "Field definition duplicated here.".into(),
2221                        )
2222                   ]
2223                },
2224                help: vec![],
2225            },
2226            NotIndexable { actually, span } => Diagnostic {
2227                reason: Some(Reason::new(code(1), "Type is not indexable".to_string())),
2228                issue: Issue::error(
2229                    source_engine,
2230                    span.clone(),
2231                    format!("This expression has type \"{actually}\", which is not an indexable type.")
2232                ),
2233                hints: vec![],
2234                help: vec![
2235                    "Index operator `[]` can be used only on indexable types.".to_string(),
2236                    "In Sway, indexable types are:".to_string(),
2237                    format!("{}- arrays. E.g., `[u64;3]`.", Indent::Single),
2238                    format!("{}- references, direct or indirect, to arrays. E.g., `&[u64;3]` or `&&&[u64;3]`.", Indent::Single),
2239                ],
2240            },
2241            FieldAccessOnNonStruct { actually, storage_variable, field_name, span } => Diagnostic {
2242                reason: Some(Reason::new(code(1), "Field access requires a struct".to_string())),
2243                issue: Issue::error(
2244                    source_engine,
2245                    span.clone(),
2246                    format!("{} has type \"{actually}\", which is not a struct{}.",
2247                        if let Some(storage_variable) = storage_variable {
2248                            format!("Storage variable \"{storage_variable}\"")
2249                        } else {
2250                            "This expression".to_string()
2251                        },
2252                        if storage_variable.is_some() {
2253                            ""
2254                        } else {
2255                            " or a reference to a struct"
2256                        }
2257                    )
2258                ),
2259                hints: vec![
2260                    Hint::info(
2261                        source_engine,
2262                        field_name.span(),
2263                        format!("Field access happens here, on \"{field_name}\".")
2264                    )
2265                ],
2266                help: if storage_variable.is_some() {
2267                    vec![
2268                        "Fields can only be accessed on storage variables that are structs.".to_string(),
2269                    ]
2270                } else {
2271                    vec![
2272                        "In Sway, fields can be accessed on:".to_string(),
2273                        format!("{}- structs. E.g., `my_struct.field`.", Indent::Single),
2274                        format!("{}- references, direct or indirect, to structs. E.g., `(&my_struct).field` or `(&&&my_struct).field`.", Indent::Single),
2275                    ]
2276                }
2277            },
2278            SymbolWithMultipleBindings { name, paths, span } => Diagnostic {
2279                reason: Some(Reason::new(code(1), "Multiple bindings exist for symbol in the scope".to_string())),
2280                issue: Issue::error(
2281                    source_engine,
2282                    span.clone(),
2283                    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)),
2284                ),
2285                hints: vec![],
2286                help: vec![format!("Consider using a fully qualified name, e.g., `{}::{}`.", paths[0], name)],
2287            },
2288            StorageFieldDoesNotExist { field_name, available_fields, storage_decl_span } => Diagnostic {
2289                reason: Some(Reason::new(code(1), "Storage field does not exist".to_string())),
2290                issue: Issue::error(
2291                    source_engine,
2292                    field_name.span(),
2293                    format!("Storage field \"{field_name}\" does not exist in the storage.")
2294                ),
2295                hints: {
2296                    let (hint, show_storage_decl) = if available_fields.is_empty() {
2297                        ("The storage is empty. It doesn't have any fields.".to_string(), false)
2298                    } else {
2299                        const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2300                        let display_fields = available_fields.iter().map(|(path, field_name)| {
2301                            let path = path.iter().map(ToString::to_string).collect::<Vec<_>>().join("::");
2302                            if path.is_empty() {
2303                                format!("storage.{field_name}")
2304                            } else {
2305                                format!("storage::{path}.{field_name}")
2306                            }
2307                        }).collect::<Vec<_>>();
2308                        match &display_fields[..] {
2309                            [field] => (format!("Only available storage field is \"{field}\"."), false),
2310                            _ => (format!("Available storage fields are {}.", sequence_to_str(&display_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY)),
2311                                    available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2312                                ),
2313                        }
2314                    };
2315
2316                    let mut hints = vec![];
2317
2318                    hints.push(Hint::help(source_engine, field_name.span(), hint));
2319
2320                    if show_storage_decl {
2321                        hints.push(Hint::info(
2322                            source_engine,
2323                            storage_decl_span.clone(),
2324                            format!("Storage is declared here, and has {} fields.",
2325                                num_to_str(available_fields.len())
2326                            )
2327                        ));
2328                    }
2329
2330                    hints
2331                },
2332                help: vec![],
2333            },
2334            TupleIndexOutOfBounds { index, count, tuple_type, span, prefix_span } => Diagnostic {
2335                reason: Some(Reason::new(code(1), "Tuple index is out of bounds".to_string())),
2336                issue: Issue::error(
2337                    source_engine,
2338                    span.clone(),
2339                    format!("Tuple index {index} is out of bounds. The tuple has only {count} element{}.", plural_s(*count))
2340                ),
2341                hints: vec![
2342                    Hint::info(
2343                        source_engine,
2344                        prefix_span.clone(),
2345                        format!("This expression has type \"{tuple_type}\".")
2346                    ),
2347                ],
2348                help: vec![],
2349            },
2350            TupleElementAccessOnNonTuple { actually, span, index, index_span } => Diagnostic {
2351                reason: Some(Reason::new(code(1), "Tuple element access requires a tuple".to_string())),
2352                issue: Issue::error(
2353                    source_engine,
2354                    span.clone(),
2355                    format!("This expression has type \"{actually}\", which is not a tuple or a reference to a tuple.")
2356                ),
2357                hints: vec![
2358                    Hint::info(
2359                        source_engine,
2360                        index_span.clone(),
2361                        format!("Tuple element access happens here, on the index {index}.")
2362                    )
2363                ],
2364                help: vec![
2365                    "In Sway, tuple elements can be accessed on:".to_string(),
2366                    format!("{}- tuples. E.g., `my_tuple.1`.", Indent::Single),
2367                    format!("{}- references, direct or indirect, to tuples. E.g., `(&my_tuple).1` or `(&&&my_tuple).1`.", Indent::Single),
2368                ],
2369            },
2370            RefMutCannotReferenceConstant { constant, span } => Diagnostic {
2371                reason: Some(Reason::new(code(1), "References to mutable values cannot reference constants".to_string())),
2372                issue: Issue::error(
2373                    source_engine,
2374                    span.clone(),
2375                    format!("\"{constant}\" is a constant. `&mut` cannot reference constants.")
2376                ),
2377                hints: vec![],
2378                help: vec![
2379                    "Consider:".to_string(),
2380                    format!("{}- taking a reference without `mut`: `&{constant}`.", Indent::Single),
2381                    format!("{}- referencing a mutable copy of the constant, by returning it from a block: `&mut {{ {constant} }}`.", Indent::Single)
2382                ],
2383            },
2384            RefMutCannotReferenceImmutableVariable { decl_name, span } => Diagnostic {
2385                reason: Some(Reason::new(code(1), "References to mutable values cannot reference immutable variables".to_string())),
2386                issue: Issue::error(
2387                    source_engine,
2388                    span.clone(),
2389                    format!("\"{decl_name}\" is an immutable variable. `&mut` cannot reference immutable variables.")
2390                ),
2391                hints: vec![
2392                    Hint::info(
2393                        source_engine,
2394                        decl_name.span(),
2395                        format!("Variable \"{decl_name}\" is declared here as immutable.")
2396                    ),
2397                ],
2398                help: vec![
2399                    "Consider:".to_string(),
2400                    // TODO: (REFERENCES) Once desugaring information becomes available, do not show the first suggestion if declaring variable as mutable is not possible.
2401                    format!("{}- declaring \"{decl_name}\" as mutable.", Indent::Single),
2402                    format!("{}- taking a reference without `mut`: `&{decl_name}`.", Indent::Single),
2403                    format!("{}- referencing a mutable copy of \"{decl_name}\", by returning it from a block: `&mut {{ {decl_name} }}`.", Indent::Single)
2404                ],
2405            },
2406            ConflictingImplsForTraitAndType { trait_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => Diagnostic {
2407                reason: Some(Reason::new(code(1), "Trait is already implemented for type".to_string())),
2408                issue: Issue::error(
2409                    source_engine,
2410                    second_impl_span.clone(),
2411                    format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\"."),
2412                ),
2413                hints: vec![
2414                    if type_implementing_for != type_implementing_for_unaliased {
2415                        Hint::help(
2416                            source_engine,
2417                            second_impl_span.clone(),
2418                            format!("\"{}\" is an alias for \"{type_implementing_for_unaliased}\".",
2419                                short_name(type_implementing_for),
2420                            ))
2421                    } else {
2422                        Hint::none()
2423                    },
2424                    Hint::info(
2425                        source_engine,
2426                        existing_impl_span.clone(),
2427                        format!("This is the already existing implementation of \"{}\" for \"{}\".",
2428                            short_name(trait_name),
2429                            short_name(type_implementing_for),
2430                        ),
2431                    ),
2432                ],
2433                help: vec![
2434                    "In Sway, there can be at most one implementation of a trait for any given type.".to_string(),
2435                    "This property is called \"trait coherence\".".to_string(),
2436                ],
2437            },
2438            DuplicateDeclDefinedForType { decl_kind, decl_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => {
2439                let decl_kind_snake_case = sway_types::style::to_upper_camel_case(decl_kind);
2440                Diagnostic {
2441                    reason: Some(Reason::new(code(1), "Type contains duplicate declarations".to_string())),
2442                    issue: Issue::error(
2443                        source_engine,
2444                        second_impl_span.clone(),
2445                        if type_implementing_for == type_implementing_for_unaliased {
2446                            format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\".")
2447                        } else {
2448                            format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").")
2449                        }
2450                    ),
2451                    hints: vec![
2452                        Hint::info(
2453                            source_engine,
2454                            existing_impl_span.clone(),
2455                            format!("\"{decl_name}\" previously defined here.")
2456                        )
2457                    ],
2458                    help: vec![
2459                        "A type may not contain two or more declarations of the same name".to_string(),
2460                    ],
2461                }
2462            },
2463            MarkerTraitExplicitlyImplemented { marker_trait_full_name, span} => Diagnostic {
2464                reason: Some(Reason::new(code(1), "Marker traits cannot be explicitly implemented".to_string())),
2465                issue: Issue::error(
2466                    source_engine,
2467                    span.clone(),
2468                    format!("Trait \"{marker_trait_full_name}\" is a marker trait and cannot be explicitly implemented.")
2469                ),
2470                hints: vec![],
2471                help: match marker_trait_name(marker_trait_full_name) {
2472                    "Error" => error_marker_trait_help_msg(),
2473                    "Enum" => vec![
2474                        "\"Enum\" marker trait is automatically implemented by the compiler for all enum types.".to_string(),
2475                    ],
2476                    _ => vec![],
2477                }
2478            },
2479            AssignmentToNonMutableVariable { lhs_span, decl_name } => Diagnostic {
2480                reason: Some(Reason::new(code(1), "Immutable variables cannot be assigned to".to_string())),
2481                issue: Issue::error(
2482                    source_engine,
2483                    lhs_span.clone(),
2484                    // "x" cannot be assigned to, because it is an immutable variable.
2485                    //  or
2486                    // This expression cannot be assigned to, because "x" is an immutable variable.
2487                    format!("{} cannot be assigned to, because {} is an immutable variable.",
2488                        if decl_name.as_str() == lhs_span.as_str() { // We have just a single variable in the expression.
2489                            format!("\"{decl_name}\"")
2490                        } else {
2491                            "This expression".to_string()
2492                        },
2493                        if decl_name.as_str() == lhs_span.as_str() {
2494                            "it".to_string()
2495                        } else {
2496                            format!("\"{decl_name}\"")
2497                        }
2498                    )
2499                ),
2500                hints: vec![
2501                    Hint::info(
2502                        source_engine,
2503                        decl_name.span(),
2504                        format!("Variable \"{decl_name}\" is declared here as immutable.")
2505                    ),
2506                ],
2507                help: vec![
2508                    // TODO: (DESUGARING) Once desugaring information becomes available, do not show this suggestion if declaring variable as mutable is not possible.
2509                    format!("Consider declaring \"{decl_name}\" as mutable."),
2510                ],
2511            },
2512            AssignmentToConstantOrConfigurable { lhs_span, is_configurable, decl_name } => Diagnostic {
2513                reason: Some(Reason::new(code(1), format!("{} cannot be assigned to",
2514                    if *is_configurable {
2515                        "Configurables"
2516                    } else {
2517                        "Constants"
2518                    }
2519                ))),
2520                issue: Issue::error(
2521                    source_engine,
2522                    lhs_span.clone(),
2523                    // "x" cannot be assigned to, because it is a constant/configurable.
2524                    //  or
2525                    // This expression cannot be assigned to, because "x" is a constant/configurable.
2526                    format!("{} cannot be assigned to, because {} is a {}.",
2527                        if decl_name.as_str() == lhs_span.as_str() { // We have just the constant in the expression.
2528                            format!("\"{decl_name}\"")
2529                        } else {
2530                            "This expression".to_string()
2531                        },
2532                        if decl_name.as_str() == lhs_span.as_str() {
2533                            "it".to_string()
2534                        } else {
2535                            format!("\"{decl_name}\"")
2536                        },
2537                        if *is_configurable {
2538                            "configurable"
2539                        } else {
2540                            "constant"
2541                        }
2542                    )
2543                ),
2544                hints: vec![
2545                    Hint::info(
2546                        source_engine,
2547                        decl_name.span(),
2548                        format!("{} \"{decl_name}\" is declared here.",
2549                            if *is_configurable {
2550                                "Configurable"
2551                            } else {
2552                                "Constant"
2553                            }
2554                        )
2555                    ),
2556                ],
2557                help: vec![],
2558            },
2559            DeclAssignmentTargetCannotBeAssignedTo { decl_name, decl_friendly_type_name, lhs_span } => Diagnostic {
2560                reason: Some(Reason::new(code(1), "Assignment target cannot be assigned to".to_string())),
2561                issue: Issue::error(
2562                    source_engine,
2563                    lhs_span.clone(),
2564                    // "x" cannot be assigned to, because it is a trait/function/ etc and not a mutable variable.
2565                    //  or
2566                    // This cannot be assigned to, because "x" is a trait/function/ etc and not a mutable variable.
2567                    format!("{} cannot be assigned to, because {} is {}{decl_friendly_type_name} and not a mutable variable.",
2568                        match decl_name {
2569                            Some(decl_name) if decl_name.as_str() == lhs_span.as_str() => // We have just the decl name in the expression.
2570                                format!("\"{decl_name}\""),
2571                            _ => "This".to_string(),
2572                        },
2573                        match decl_name {
2574                            Some(decl_name) if decl_name.as_str() == lhs_span.as_str() =>
2575                                "it".to_string(),
2576                            Some(decl_name) => format!("\"{}\"", decl_name.as_str()),
2577                            _ => "it".to_string(),
2578                        },
2579                        a_or_an(decl_friendly_type_name)
2580                    )
2581                ),
2582                hints: vec![
2583                    match decl_name {
2584                        Some(decl_name) => Hint::info(
2585                            source_engine,
2586                            decl_name.span(),
2587                            format!("{} \"{decl_name}\" is declared here.", ascii_sentence_case(&decl_friendly_type_name.to_string()))
2588                        ),
2589                        _ => Hint::none(),
2590                    }
2591                ],
2592                help: vec![],
2593            },
2594            AssignmentViaNonMutableReference { decl_reference_name, decl_reference_rhs, decl_reference_type, span } => Diagnostic {
2595                reason: Some(Reason::new(code(1), "Reference is not a reference to a mutable value (`&mut`)".to_string())),
2596                issue: Issue::error(
2597                    source_engine,
2598                    span.clone(),
2599                    // This reference expression is not a reference to a mutable value (`&mut`).
2600                    //  or
2601                    // Reference "ref_xyz" is not a reference to a mutable value (`&mut`).
2602                    format!("{} is not a reference to a mutable value (`&mut`).",
2603                        match decl_reference_name {
2604                            Some(decl_reference_name) => format!("Reference \"{decl_reference_name}\""),
2605                            _ => "This reference expression".to_string(),
2606                        }
2607                    )
2608                ),
2609                hints: vec![
2610                    match decl_reference_name {
2611                        Some(decl_reference_name) => Hint::info(
2612                            source_engine,
2613                            decl_reference_name.span(),
2614                            format!("Reference \"{decl_reference_name}\" is declared here as a reference to immutable value.")
2615                        ),
2616                        _ => Hint::none(),
2617                    },
2618                    match decl_reference_rhs {
2619                        Some(decl_reference_rhs) => Hint::info(
2620                            source_engine,
2621                            decl_reference_rhs.clone(),
2622                            format!("This expression has type \"{decl_reference_type}\" instead of \"&mut {}\".",
2623                                &decl_reference_type[1..]
2624                            )
2625                        ),
2626                        _ => Hint::info(
2627                            source_engine,
2628                            span.clone(),
2629                            format!("It has type \"{decl_reference_type}\" instead of \"&mut {}\".",
2630                                &decl_reference_type[1..]
2631                            )
2632                        ),
2633                    },
2634                    match decl_reference_rhs {
2635                        Some(decl_reference_rhs) if decl_reference_rhs.as_str().starts_with('&') => Hint::help(
2636                            source_engine,
2637                            decl_reference_rhs.clone(),
2638                            format!("Consider taking here a reference to a mutable value: `&mut {}`.",
2639                                first_line(decl_reference_rhs.as_str()[1..].trim(), true)
2640                            )
2641                        ),
2642                        _ => Hint::none(),
2643                    },
2644                ],
2645                help: vec![
2646                    format!("{} dereferenced in assignment targets must {} references to mutable values (`&mut`).",
2647                        if decl_reference_name.is_some() {
2648                            "References"
2649                        } else {
2650                            "Reference expressions"
2651                        },
2652                        if decl_reference_name.is_some() {
2653                            "be"
2654                        } else {
2655                            "result in"
2656                        }
2657                    ),
2658                ],
2659            },
2660            Unimplemented { feature, help, span } => Diagnostic {
2661                reason: Some(Reason::new(code(1), "Used feature is currently not implemented".to_string())),
2662                issue: Issue::error(
2663                    source_engine,
2664                    span.clone(),
2665                    format!("{feature} is currently not implemented.")
2666                ),
2667                hints: vec![],
2668                help: help.clone(),
2669            },
2670            MatchedValueIsNotValid { supported_types_message, span } => Diagnostic {
2671                reason: Some(Reason::new(code(1), "Matched value is not valid".to_string())),
2672                issue: Issue::error(
2673                    source_engine,
2674                    span.clone(),
2675                    "This cannot be matched.".to_string()
2676                ),
2677                hints: vec![],
2678                help: {
2679                    let mut help = vec![];
2680
2681                    help.push("Matched value must be an expression whose result is of one of the types supported in pattern matching.".to_string());
2682                    help.push(Diagnostic::help_empty_line());
2683                    for msg in supported_types_message {
2684                        help.push(msg.to_string());
2685                    }
2686
2687                    help
2688                }
2689            },
2690            TypeIsNotValidAsImplementingFor { invalid_type, trait_name, span } => Diagnostic {
2691                reason: Some(Reason::new(code(1), "Self type of an impl block is not valid".to_string())),
2692                issue: Issue::error(
2693                    source_engine,
2694                    span.clone(),
2695                    format!("{invalid_type} is not a valid type in the self type of {} impl block.",
2696                        match trait_name {
2697                            Some(_) => "a trait",
2698                            None => "an",
2699                        }
2700                    )
2701                ),
2702                hints: vec![
2703                    if matches!(invalid_type, InvalidImplementingForType::SelfType) {
2704                        Hint::help(
2705                            source_engine,
2706                            span.clone(),
2707                            format!("Replace {invalid_type} with the actual type that you want to implement for.")
2708                        )
2709                    } else {
2710                        Hint::none()
2711                    }
2712                ],
2713                help: {
2714                    if matches!(invalid_type, InvalidImplementingForType::Placeholder) {
2715                        vec![
2716                            format!("Are you trying to implement {} for any type?",
2717                                match trait_name {
2718                                    Some(trait_name) => format!("trait \"{trait_name}\""),
2719                                    None => "functionality".to_string(),
2720                                }
2721                            ),
2722                            Diagnostic::help_empty_line(),
2723                            "If so, use generic type parameters instead.".to_string(),
2724                            "E.g., instead of:".to_string(),
2725                            // The trait `trait_name` could represent an arbitrary complex trait.
2726                            // E.g., `with generic arguments, etc. So we don't want to deal
2727                            // with the complexity of representing it properly
2728                            // but rather use a simplified but clearly instructive
2729                            // sample trait name here, `SomeTrait`.
2730                            // impl _
2731                            //   or
2732                            // impl SomeTrait for _
2733                            format!("{}impl {}_",
2734                                Indent::Single,
2735                                match trait_name {
2736                                    Some(_) => "SomeTrait for ",
2737                                    None => "",
2738                                }
2739                            ),
2740                            "use:".to_string(),
2741                            format!("{}impl<T> {}T",
2742                                Indent::Single,
2743                                match trait_name {
2744                                    Some(_) => "SomeTrait for ",
2745                                    None => "",
2746                                }
2747                            ),
2748                        ]
2749                    } else {
2750                        vec![]
2751                    }
2752                }
2753            },
2754            ModulePathIsNotAnExpression { module_path, span } => Diagnostic {
2755                reason: Some(Reason::new(code(1), "Module path is not an expression".to_string())),
2756                issue: Issue::error(
2757                    source_engine,
2758                    span.clone(),
2759                    "This is a module path, and not an expression.".to_string()
2760                ),
2761                hints: vec![
2762                    Hint::help(
2763                        source_engine,
2764                        span.clone(),
2765                        "An expression is expected at this location, but a module path is found.".to_string()
2766                    ),
2767                ],
2768                help: vec![
2769                    "In expressions, module paths can only be used to fully qualify names with a path.".to_string(),
2770                    format!("E.g., `{module_path}::SOME_CONSTANT` or `{module_path}::some_function()`."),
2771                ]
2772            },
2773            Parse { error } => {
2774                match &error.kind {
2775                    ParseErrorKind::MissingColonInEnumTypeField { variant_name, tuple_contents } => Diagnostic {
2776                        reason: Some(Reason::new(code(1), "Enum variant declaration is not valid".to_string())),
2777                        issue: Issue::error(
2778                            source_engine,
2779                            error.span.clone(),
2780                            format!("`{}` is not a valid enum variant declaration.", error.span.as_str()),
2781                        ),
2782                        hints: vec![
2783                            if let Some(tuple_contents) = tuple_contents {
2784                                Hint::help(
2785                                    source_engine,
2786                                    error.span.clone(),
2787                                    format!("Did you mean `{}: ({})`?", variant_name, tuple_contents.as_str())
2788                                )
2789                            } else {
2790                                Hint::none()
2791                            }
2792                        ],
2793                        help: vec![
2794                            "In Sway, enum variants are in the form `Variant: ()`, `Variant: <type>`, or `Variant: (<type1>, ..., <typeN>)`.".to_string(),
2795                            "E.g., `Foo: (), `Bar: u64`, or `Bar: (bool, u32)`.".to_string(),
2796                        ],
2797                    },
2798                    ParseErrorKind::UnassignableExpression { erroneous_expression_kind, erroneous_expression_span } => Diagnostic {
2799                        reason: Some(Reason::new(code(1), "Expression cannot be assigned to".to_string())),
2800                        // A bit of a special handling for parentheses, because they are the only
2801                        // expression kind whose friendly name is in plural. Having it in singular
2802                        // or without this simple special handling gives very odd sounding sentences.
2803                        // Therefore, just a bit of a special handling.
2804                        issue: Issue::error(
2805                            source_engine,
2806                            error.span.clone(),
2807                            format!("This expression cannot be assigned to, because it {} {}{}.",
2808                                if &error.span == erroneous_expression_span { // If the whole expression is erroneous.
2809                                    "is"
2810                                } else {
2811                                    "contains"
2812                                },
2813                                if *erroneous_expression_kind == "parentheses" {
2814                                    ""
2815                                } else {
2816                                    a_or_an(erroneous_expression_kind)
2817                                },
2818                                erroneous_expression_kind
2819                            )
2820                        ),
2821                        hints: vec![
2822                            if &error.span != erroneous_expression_span {
2823                                Hint::info(
2824                                    source_engine,
2825                                    erroneous_expression_span.clone(),
2826                                    format!("{} the contained {erroneous_expression_kind}.",
2827                                        if *erroneous_expression_kind == "parentheses" {
2828                                            "These are"
2829                                        } else {
2830                                            "This is"
2831                                        }
2832                                    )
2833                                )
2834                            } else {
2835                                Hint::none()
2836                            },
2837                        ],
2838                        help: vec![
2839                            format!("{} cannot be {}an assignment target.",
2840                                ascii_sentence_case(&erroneous_expression_kind.to_string()),
2841                                if &error.span == erroneous_expression_span {
2842                                    ""
2843                                } else {
2844                                    "a part of "
2845                                }
2846                            ),
2847                            Diagnostic::help_empty_line(),
2848                            "In Sway, assignment targets must be one of the following:".to_string(),
2849                            format!("{}- Expressions starting with a mutable variable, optionally having", Indent::Single),
2850                            format!("{}  array or tuple element accesses, struct field accesses,", Indent::Single),
2851                            format!("{}  or arbitrary combinations of those.", Indent::Single),
2852                            format!("{}  E.g., `mut_var` or `mut_struct.field` or `mut_array[x + y].field.1`.", Indent::Single),
2853                            Diagnostic::help_empty_line(),
2854                            format!("{}- Dereferencing of an arbitrary expression that results", Indent::Single),
2855                            format!("{}  in a reference to a mutable value.", Indent::Single),
2856                            format!("{}  E.g., `*ref_to_mutable_value` or `*max_mut(&mut x, &mut y)`.", Indent::Single),
2857                        ]
2858                    },
2859                    ParseErrorKind::UnrecognizedOpCode { known_op_codes } => Diagnostic {
2860                        reason: Some(Reason::new(code(1), "Assembly instruction is unknown".to_string())),
2861                        issue: Issue::error(
2862                            source_engine,
2863                            error.span.clone(),
2864                            format!("\"{}\" is not a known assembly instruction.",
2865                                error.span.as_str()
2866                            )
2867                        ),
2868                        hints: vec![did_you_mean_help(source_engine, error.span.clone(), known_op_codes.iter(), 2, Enclosing::DoubleQuote)],
2869                        help: vec![]
2870                    },
2871                    _ => Diagnostic {
2872                                // TODO: Temporary we use `self` here to achieve backward compatibility.
2873                                //       In general, `self` must not be used. All the values for the formatting
2874                                //       of a diagnostic must come from its enum variant parameters.
2875                                issue: Issue::error(source_engine, self.span(), format!("{self}")),
2876                                ..Default::default()
2877                        },
2878                }
2879            },
2880            ConvertParseTree { error } => {
2881                match error {
2882                    ConvertParseTreeError::InvalidAttributeTarget { span, attribute, target_friendly_name, can_only_annotate_help } => Diagnostic {
2883                        reason: Some(Reason::new(code(1), match get_attribute_type(attribute) {
2884                            AttributeType::InnerDocComment => "Inner doc comment (`//!`) cannot document item",
2885                            AttributeType::OuterDocComment => "Outer doc comment (`///`) cannot document item",
2886                            AttributeType::Attribute => "Attribute cannot annotate item",
2887                        }.to_string())),
2888                        issue: Issue::error(
2889                            source_engine,
2890                            span.clone(),
2891                            match get_attribute_type(attribute) {
2892                                AttributeType::InnerDocComment => format!("Inner doc comment (`//!`) cannot document {}{target_friendly_name}.", a_or_an(&target_friendly_name)),
2893                                AttributeType::OuterDocComment => format!("Outer doc comment (`///`) cannot document {}{target_friendly_name}.", a_or_an(&target_friendly_name)),
2894                                AttributeType::Attribute => format!("\"{attribute}\" attribute cannot annotate {}{target_friendly_name}.", a_or_an(&target_friendly_name)),
2895                            }.to_string()
2896                        ),
2897                        hints: vec![],
2898                        help: can_only_annotate_help.iter().map(|help| help.to_string()).collect(),
2899                    },
2900                    ConvertParseTreeError::InvalidAttributeMultiplicity { last_occurrence, previous_occurrences } => Diagnostic {
2901                        reason: Some(Reason::new(code(1), "Attribute can be applied only once".to_string())),
2902                        issue: Issue::error(
2903                            source_engine,
2904                            last_occurrence.span(),
2905                            format!("\"{last_occurrence}\" attribute can be applied only once, but is applied {} times.", num_to_str(previous_occurrences.len() + 1))
2906                        ),
2907                        hints: {
2908                            let (first_occurrence, other_occurrences) = previous_occurrences.split_first().expect("there is at least one previous occurrence in `previous_occurrences`");
2909                            let mut hints = vec![Hint::info(source_engine, first_occurrence.span(), "It is already applied here.".to_string())];
2910                            other_occurrences.iter().for_each(|occurrence| hints.push(Hint::info(source_engine, occurrence.span(), "And here.".to_string())));
2911                            hints
2912                        },
2913                        help: vec![],
2914                    },
2915                    ConvertParseTreeError::InvalidAttributeArgsMultiplicity { span, attribute, args_multiplicity, num_of_args } => Diagnostic {
2916                        reason: Some(Reason::new(code(1), "Number of attribute arguments is invalid".to_string())),
2917                        issue: Issue::error(
2918                            source_engine,
2919                            span.clone(),
2920                            format!("\"{attribute}\" attribute must {}, but has {}.", get_expected_attributes_args_multiplicity_msg(args_multiplicity), num_to_str_or_none(*num_of_args))
2921                        ),
2922                        hints: vec![],
2923                        help: vec![],
2924                    },
2925                    ConvertParseTreeError::InvalidAttributeArg { attribute, arg, expected_args } => Diagnostic {
2926                        reason: Some(Reason::new(code(1), "Attribute argument is invalid".to_string())),
2927                        issue: Issue::error(
2928                            source_engine,
2929                            arg.span(),
2930                            format!("\"{arg}\" is an invalid argument for attribute \"{attribute}\".")
2931                        ),
2932                        hints: {
2933                            let mut hints = vec![did_you_mean_help(source_engine, arg.span(), expected_args, 2, Enclosing::DoubleQuote)];
2934                            if expected_args.len() == 1 {
2935                                hints.push(Hint::help(source_engine, arg.span(), format!("The only valid argument is \"{}\".", expected_args[0])));
2936                            } else if expected_args.len() <= 3 {
2937                                hints.push(Hint::help(source_engine, arg.span(), format!("Valid arguments are {}.", sequence_to_str(expected_args, Enclosing::DoubleQuote, usize::MAX))));
2938                            } else {
2939                                hints.push(Hint::help(source_engine, arg.span(), "Valid arguments are:".to_string()));
2940                                hints.append(&mut Hint::multi_help(source_engine, &arg.span(), sequence_to_list(expected_args, Indent::Single, usize::MAX)))
2941                            }
2942                            hints
2943                        },
2944                        help: vec![],
2945                    },
2946                    ConvertParseTreeError::InvalidAttributeArgExpectsValue { attribute, arg, value_span  } => Diagnostic {
2947                        reason: Some(Reason::new(code(1), format!("Attribute argument must {}have a value",
2948                            match value_span {
2949                                Some(_) => "not ",
2950                                None => "",
2951                            }
2952                        ))),
2953                        issue: Issue::error(
2954                            source_engine,
2955                            arg.span(),
2956                            format!("\"{arg}\" argument of the attribute \"{attribute}\" must {}have a value.",
2957                                match value_span {
2958                                    Some(_) => "not ",
2959                                    None => "",
2960                                }
2961                            )
2962                        ),
2963                        hints: vec![
2964                            match &value_span {
2965                                Some(value_span) => Hint::help(source_engine, value_span.clone(), format!("Remove the value: `= {}`.", value_span.as_str())),
2966                                None => Hint::help(source_engine, arg.span(), format!("To set the value, use the `=` operator: `{arg} = <value>`.")),
2967                            }
2968                        ],
2969                        help: vec![],
2970                    },
2971                    ConvertParseTreeError::InvalidAttributeArgValueType { span, arg, expected_type, received_type } => Diagnostic {
2972                        reason: Some(Reason::new(code(1), "Attribute argument value has a wrong type".to_string())),
2973                        issue: Issue::error(
2974                            source_engine,
2975                            span.clone(),
2976                            format!("\"{arg}\" argument must have a value of type \"{expected_type}\".")
2977                        ),
2978                        hints: vec![
2979                            Hint::help(
2980                                source_engine,
2981                                span.clone(),
2982                                format!("This value has type \"{received_type}\"."),
2983                            )
2984                        ],
2985                        help: vec![],
2986                    },
2987                    ConvertParseTreeError::InvalidAttributeArgValue { span, arg, expected_values } => Diagnostic {
2988                        reason: Some(Reason::new(code(1), "Attribute argument value is invalid".to_string())),
2989                        issue: Issue::error(
2990                            source_engine,
2991                            span.clone(),
2992                            format!("\"{}\" is an invalid value for argument \"{arg}\".", span.as_str())
2993                        ),
2994                        hints: {
2995                            let mut hints = vec![did_you_mean_help(source_engine, span.clone(), expected_values, 2, Enclosing::DoubleQuote)];
2996                            if expected_values.len() == 1 {
2997                                hints.push(Hint::help(source_engine, span.clone(), format!("The only valid argument value is \"{}\".", expected_values[0])));
2998                            } else if expected_values.len() <= 3 {
2999                                hints.push(Hint::help(source_engine, span.clone(), format!("Valid argument values are {}.", sequence_to_str(expected_values, Enclosing::DoubleQuote, usize::MAX))));
3000                            } else {
3001                                hints.push(Hint::help(source_engine, span.clone(), "Valid argument values are:".to_string()));
3002                                hints.append(&mut Hint::multi_help(source_engine, span, sequence_to_list(expected_values, Indent::Single, usize::MAX)))
3003                            }
3004                            hints
3005                        },
3006                        help: vec![],
3007                    },
3008                    _ => Diagnostic {
3009                                // TODO: Temporarily we use `self` here to achieve backward compatibility.
3010                                //       In general, `self` must not be used. All the values for the formatting
3011                                //       of a diagnostic must come from its enum variant parameters.
3012                                issue: Issue::error(source_engine, self.span(), format!("{self}")),
3013                                ..Default::default()
3014                        },
3015                }
3016            }
3017            ConfigurableMissingAbiDecodeInPlace { span } => Diagnostic {
3018                reason: Some(Reason::new(code(1), "Configurables need a function named \"abi_decode_in_place\" to be in scope".to_string())),
3019                issue: Issue::error(
3020                    source_engine,
3021                    span.clone(),
3022                    String::new()
3023                ),
3024                hints: vec![],
3025                help: vec![
3026                    "The function \"abi_decode_in_place\" is usually defined in the standard library module \"std::codec\".".into(),
3027                    "Verify that you are using a version of the \"std\" standard library that contains this function.".into(),
3028                ],
3029            },
3030            StorageAccessMismatched { span, is_pure, suggested_attributes, storage_access_violations } => Diagnostic {
3031                // Pure function cannot access storage
3032                //   or
3033                // Storage read-only function cannot write to storage
3034                reason: Some(Reason::new(code(1), format!("{} function cannot {} storage",
3035                    if *is_pure {
3036                        "Pure"
3037                    } else {
3038                        "Storage read-only"
3039                    },
3040                    if *is_pure {
3041                        "access"
3042                    } else {
3043                        "write to"
3044                    }
3045                ))),
3046                issue: Issue::error(
3047                    source_engine,
3048                    span.clone(),
3049                    format!("Function \"{}\" is {} and cannot {} storage.",
3050                        span.as_str(),
3051                        if *is_pure {
3052                            "pure"
3053                        } else {
3054                            "declared as `#[storage(read)]`"
3055                        },
3056                        if *is_pure {
3057                            "access"
3058                        } else {
3059                            "write to"
3060                        },
3061                    )
3062                ),
3063                hints: storage_access_violations
3064                    .iter()
3065                    .map(|(span, storage_access)| Hint::info(
3066                        source_engine,
3067                        span.clone(),
3068                        format!("{storage_access}")
3069                    ))
3070                    .collect(),
3071                help: vec![
3072                    format!("Consider declaring the function \"{}\" as `#[storage({suggested_attributes})]`,",
3073                        span.as_str()
3074                    ),
3075                    format!("or removing the {} from the function body.",
3076                        if *is_pure {
3077                            "storage access code".to_string()
3078                        } else {
3079                            format!("storage write{}", plural_s(storage_access_violations.len()))
3080                        }
3081                    ),
3082                ],
3083            },
3084            MultipleImplsSatisfyingTraitForType { span, type_annotation , trait_names, trait_types_and_names: trait_types_and_spans } => Diagnostic {
3085                reason: Some(Reason::new(code(1), format!("Multiple impls satisfying {} for {}", trait_names.join("+"), type_annotation))),
3086                issue: Issue::error(
3087                    source_engine,
3088                    span.clone(),
3089                    String::new()
3090                ),
3091                hints: vec![],
3092                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))| 
3093                    format!("#{} {} for {}", e, name, type_id.clone())
3094                ).collect::<Vec<_>>().join("\n"))],
3095            },
3096            MultipleContractsMethodsWithTheSameName { spans } => Diagnostic {
3097                reason: Some(Reason::new(code(1), "Multiple contracts methods with the same name.".into())),
3098                issue: Issue::error(
3099                    source_engine,
3100                    spans[0].clone(),
3101                    "This is the first method".into()
3102                ),
3103                hints: spans.iter().skip(1).map(|span| {
3104                    Hint::error(source_engine, span.clone(), "This is the duplicated method.".into())
3105                }).collect(),
3106                help: vec!["Contract methods names must be unique, even when implementing multiple ABIs.".into()],
3107            },
3108            FunctionSelectorClash { method_name, span, other_method_name, other_span } => Diagnostic {
3109                reason: Some(Reason::new(code(1), format!("Methods {method_name} and {other_method_name} have clashing function selectors."))),
3110                issue: Issue::error(
3111                    source_engine,
3112                    span.clone(),
3113                    String::new()
3114                ),
3115                hints: vec![Hint::error(source_engine, other_span.clone(), format!("The declaration of {other_method_name} is here"))],
3116                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")]
3117            },
3118            ErrorTypeEnumHasNonErrorVariants { enum_name, non_error_variants } => Diagnostic {
3119                reason: Some(Reason::new(code(1), "Error type enum cannot have non-error variants".to_string())),
3120                issue: Issue::error(
3121                    source_engine,
3122                    enum_name.span(),
3123                    format!("Error type enum \"{enum_name}\" has non-error variant{} {}.",
3124                        plural_s(non_error_variants.len()),
3125                        sequence_to_str(non_error_variants, Enclosing::DoubleQuote, 2)
3126                    )
3127                ),
3128                hints: non_error_variants.iter().map(|variant| Hint::underscored_info(source_engine, variant.span())).collect(),
3129                help: vec![
3130                    "All error type enum's variants must be marked as errors.".to_string(),
3131                    "To mark error variants as errors, annotate them with the `#[error]` attribute.".to_string(),
3132                ]
3133            },
3134            ErrorAttributeInNonErrorEnum { enum_name, enum_variant_name } => Diagnostic {
3135                reason: Some(Reason::new(code(1), "Error enum variants must be in error type enums".to_string())),
3136                issue: Issue::error(
3137                    source_engine,
3138                    enum_variant_name.span(),
3139                    format!("Enum variant \"{enum_variant_name}\" is marked as `#[error]`, but its enum is not an error type enum.")
3140                ),
3141                hints: vec![
3142                    Hint::help(
3143                        source_engine,
3144                        enum_name.span(),
3145                        format!("Consider annotating \"{enum_name}\" enum with the `#[error_type]` attribute."),
3146                    )
3147                ],
3148                help: vec![
3149                    "Enum variants can be marked as `#[error]` only if their parent enum is annotated with the `#[error_type]` attribute.".to_string(),
3150                ]
3151            },
3152            PanicExpressionArgumentIsNotError { argument_type, span } => Diagnostic {
3153                reason: Some(Reason::new(code(1), "Panic expression arguments must implement \"Error\" marker trait".into())),
3154                issue: Issue::error(
3155                    source_engine,
3156                    span.clone(),
3157                    format!("This expression has type \"{argument_type}\", which does not implement \"std::marker::Error\" trait."),
3158                ),
3159                hints: vec![],
3160                help: {
3161                    let mut help = vec![
3162                        "Panic expression accepts only arguments that implement \"std::marker::Error\" trait.".to_string(),
3163                        Diagnostic::help_empty_line(),
3164                    ];
3165                    help.append(&mut error_marker_trait_help_msg());
3166                    help
3167                },
3168            },
3169            MaxNumOfPanicExpressionsReached { current, max_num, span } => Diagnostic {
3170                reason: Some(Reason::new(code(1), format!("Project contains more than {max_num} `panic` expressions"))),
3171                issue: Issue::error(
3172                    source_engine,
3173                    span.clone(),
3174                    format!("This is the {current}{} `panic` expression occurred during the compilation.",
3175                        ord_num_suffix(*current as usize)
3176                    ),
3177                ),
3178                hints: vec![],
3179                help: vec![
3180                    format!("Sway projects can have up to {max_num} `panic` expressions."),
3181                    "In practice, this limit should never be reached, even for large Sway programs.".to_string(),
3182                    Diagnostic::help_empty_line(),
3183                    "Consider refactoring your code to reduce the number of `panic` expressions.".to_string(),
3184                ],
3185            },
3186            MaxNumOfPanickingCallsReached { current, max_num, span } => Diagnostic {
3187                reason: Some(Reason::new(code(1), format!("Project contains more than {max_num} panicking calls"))),
3188                issue: Issue::error(
3189                    source_engine,
3190                    span.clone(),
3191                    format!("This is the {current}{} panicking call occurred during the compilation.",
3192                        ord_num_suffix(*current as usize)
3193                    ),
3194                ),
3195                hints: vec![],
3196                help: vec![
3197                    format!("Sway projects can have up to {max_num} panicking calls."),
3198                    "In practice, this limit should never be reached, even for large Sway programs.".to_string(),
3199                    Diagnostic::help_empty_line(),
3200                    "Consider compiling the project with the `backtrace` build option".to_string(),
3201                    "set to `only_always` or `none`.".to_string(),
3202                ],
3203            },
3204            IncoherentImplDueToOrphanRule { trait_name, type_name, span } => Diagnostic {
3205                reason: Some(Reason::new(
3206                    code(1),
3207                    "coherence violation: only traits defined in this package can be implemented for external types".into()
3208                )),
3209                issue: Issue::error(
3210                    source_engine,
3211                    span.clone(),
3212                    format!(
3213                        "cannot implement `{trait_name}` for `{type_name}`: both originate outside this package"
3214                    ),
3215                ),
3216                hints: vec![],
3217                help: {
3218                    let help = vec![
3219                        "only traits defined in this package can be implemented for external types".to_string(),
3220                        Diagnostic::help_empty_line(),
3221                        format!(
3222                            "move this impl into the package that defines `{type_name}`"
3223                        ),
3224                        format!(
3225                            "or define and use a local trait instead of `{trait_name}` to avoid the orphan rule"
3226                        ),
3227                    ];
3228                    help
3229                },
3230            },
3231            ABIDuplicateName { span, other_span: other, is_attribute } => Diagnostic {
3232                reason: Some(Reason::new(code(1), "Duplicated name found for renamed ABI type".into())),
3233                issue: Issue::error(
3234                    source_engine,
3235                    span.clone(),
3236                    String::new()
3237                ),
3238                hints: vec![
3239                    Hint::help(
3240                        source_engine,
3241                        other.clone(),
3242                        format!("This is the existing {} with conflicting name.", if *is_attribute { "attribute" } else { "type" }),
3243                    )
3244                ],
3245                help: vec![],
3246            },
3247            ABIInvalidName { span, name } => Diagnostic {
3248                reason: Some(Reason::new(code(1), "Invalid name found for renamed ABI type.".into())),
3249                issue: Issue::error(
3250                    source_engine,
3251                    span.clone(),
3252                    String::new()
3253                ),
3254                hints: vec![],
3255                help: vec![format!("The name must be a valid Sway identifier{}.", if name.is_empty() { " and cannot be empty" } else { "" })],
3256            },
3257            IndexedFieldInNonEventStruct { field_name, struct_name } => Diagnostic {
3258                reason: Some(Reason::new(code(1), "Indexed fields must be in event structs".to_string())),
3259                issue: Issue::error(
3260                    source_engine,
3261                    field_name.span(),
3262                    format!("Field \"{field_name}\" is marked as `#[indexed]`, but its struct is not an event.")
3263                ),
3264                hints: vec![
3265                    Hint::help(
3266                        source_engine,
3267                        struct_name.span(),
3268                        format!("Consider annotating \"{struct_name}\" struct with the `#[event]` attribute."),
3269                    )
3270                ],
3271                help: vec![
3272                    "Fields can be marked as `#[indexed]` only if their parent struct is annotated with the `#[event]` attribute.".to_string(),
3273                ]
3274            },
3275            IndexedFieldMustPrecedeNonIndexedField { field_name } => Diagnostic {
3276                reason: Some(Reason::new(code(1), "Indexed fields must precede non-indexed fields".to_string())),
3277                issue: Issue::error(
3278                    source_engine,
3279                    field_name.span(),
3280                    format!("Field \"{field_name}\" cannot be marked as `#[indexed]` because a non-indexed field appears before it."),
3281                ),
3282                hints: vec![],
3283                help: vec![
3284                    "Event structs must list their `#[indexed]` fields first, followed by non-indexed fields.".to_string(),
3285                ],
3286            },
3287            IndexedFieldIsNotFixedSizeABIType { field_name } => Diagnostic {
3288                reason: Some(Reason::new(
3289                    code(1),
3290                    "Indexed fields must be fixed-size ABI types.".to_string(),
3291                )),
3292                issue: Issue::error(
3293                    source_engine,
3294                    field_name.span(),
3295                    format!(
3296                        "Field \"{field_name}\" is marked as `#[indexed]`, but is not a fixed-size ABI type."
3297                    ),
3298                ),
3299                hints: vec![],
3300                help: vec![
3301                    "Indexed fields in event structs must be fixed-size ABI types.".to_string(),
3302                    "Fixed-size types include: bool, u8, u16, u32, u64, u256, b256, and Address.".to_string(),
3303                ],
3304            },
3305            IndexedFieldOffsetTooLarge { field_name } => Diagnostic {
3306                reason: Some(Reason::new(
3307                    code(1),
3308                    "Too many indexed fields on event for current metadata format.".to_string(),
3309                )),
3310                issue: Issue::error(
3311                    source_engine,
3312                    field_name.span(),
3313                    "Too many indexed fields on event for current metadata format.".to_string(),
3314                ),
3315                hints: vec![],
3316                help: vec![],
3317            },
3318            MultipleDefinitionsOfConstant { name, old, new } => Diagnostic {
3319                reason: Some(Reason::new(code(1), "Multiple definitions of constant".into())),
3320                issue: Issue::error(
3321                    source_engine,
3322                    new.clone(),
3323                    format!("Constant \"{name}\" was already defined"),
3324                ),
3325                hints: vec![
3326                    Hint::error(
3327                        source_engine,
3328                        old.clone(),
3329                        "Its first definition is here.".into(),
3330                    ),
3331                ],
3332                help: vec![],
3333            },
3334            MethodNotFound { called_method, expected_signature, type_name, matching_methods } => Diagnostic {
3335                reason: Some(Reason::new(code(1), "Associated function or method is not found".into())),
3336                issue: Issue::error(
3337                    source_engine,
3338                    called_method.span(),
3339                    format!("\"{expected_signature}\" is not found for type \"{type_name}\"."),
3340                ),
3341                hints: if matching_methods.is_empty() {
3342                    vec![]
3343                } else {
3344                    Hint::multi_help(
3345                        source_engine,
3346                        &called_method.span(),
3347                        std::iter::once(
3348                                format!("{} \"{called_method}\" function{} {} implemented for the type:",
3349                                    singular_plural(matching_methods.len(), "Only this", "These"),
3350                                    plural_s(matching_methods.len()),
3351                                    is_are(matching_methods.len()),
3352                                )
3353                            )
3354                            .chain(matching_methods
3355                                .iter()
3356                                .map(|m| format!("- {m}"))
3357                            )
3358                            .chain(std::iter::once(
3359                                format!("Did you mean to call {}?",
3360                                    singular_plural(matching_methods.len(), "that function", "one of those functions"),
3361                                )
3362                            ))
3363                            .collect()
3364                    )
3365                },
3366                help: vec![],
3367            },
3368            IntrinsicArgNotConstant { intrinsic, arg, expected_type, span } => Diagnostic {
3369                reason: Some(Reason::new(code(1), "Intrinsic argument is not a compile-time constant".into())),
3370                issue: Issue::error(
3371                    source_engine,
3372                    span.clone(),
3373                    format!("\"__{intrinsic}\" intrinsic's argument \"{arg}\" must be a constant of type `{expected_type}`."),
3374                ),
3375                hints: vec![],
3376                help: vec![],
3377            },
3378            _ => Diagnostic {
3379                    // TODO: Temporarily we use `self` here to achieve backward compatibility.
3380                    //       In general, `self` must not be used. All the values for the formatting
3381                    //       of a diagnostic must come from its enum variant parameters.
3382                    issue: Issue::error(source_engine, self.span(), format!("{self}")),
3383                    ..Default::default()
3384            }
3385        }
3386    }
3387}
3388
3389#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
3390pub enum TypeNotAllowedReason {
3391    #[error(
3392        "Returning a type containing `raw_slice` from `main()` is not allowed. \
3393            Consider converting it into a flat `raw_slice` first."
3394    )]
3395    NestedSliceReturnNotAllowedInMain,
3396
3397    #[error("The type \"{ty}\" is not allowed in storage.")]
3398    TypeNotAllowedInContractStorage { ty: String },
3399
3400    #[error("`str` or a type containing `str` on `main()` arguments is not allowed.")]
3401    StringSliceInMainParameters,
3402
3403    #[error("Returning `str` or a type containing `str` from `main()` is not allowed.")]
3404    StringSliceInMainReturn,
3405
3406    #[error("`str` or a type containing `str` on `configurables` is not allowed.")]
3407    StringSliceInConfigurables,
3408
3409    #[error("`str` or a type containing `str` on `const` is not allowed.")]
3410    StringSliceInConst,
3411
3412    #[error("slices or types containing slices on `const` are not allowed.")]
3413    SliceInConst,
3414
3415    #[error("references, pointers, slices, string slices or types containing any of these are not allowed.")]
3416    NotAllowedInTransmute,
3417}
3418
3419#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3420pub enum StructFieldUsageContext {
3421    StructInstantiation { struct_can_be_instantiated: bool },
3422    StorageDeclaration { struct_can_be_instantiated: bool },
3423    StorageAccess,
3424    PatternMatching { has_rest_pattern: bool },
3425    StructFieldAccess,
3426    // TODO: Distinguish between struct field access and destructing
3427    //       once https://github.com/FuelLabs/sway/issues/5478 is implemented
3428    //       and provide specific suggestions for these two cases.
3429    //       (Destructing desugars to plain struct field access.)
3430}
3431
3432#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3433pub enum InvalidImplementingForType {
3434    SelfType,
3435    Placeholder,
3436    Other,
3437}
3438
3439impl fmt::Display for InvalidImplementingForType {
3440    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3441        match self {
3442            Self::SelfType => f.write_str("\"Self\""),
3443            Self::Placeholder => f.write_str("Placeholder `_`"),
3444            Self::Other => f.write_str("This"),
3445        }
3446    }
3447}
3448
3449/// Defines what shadows a constant or a configurable.
3450#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3451pub enum ShadowingSource {
3452    /// A constant or a configurable is shadowed by a constant.
3453    Const,
3454    /// A constant or a configurable is shadowed by a local variable declared with the `let` keyword.
3455    LetVar,
3456    /// A constant or a configurable is shadowed by a variable declared in pattern matching,
3457    /// being a struct field. E.g., `S { some_field }`.
3458    PatternMatchingStructFieldVar,
3459}
3460
3461impl fmt::Display for ShadowingSource {
3462    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3463        match self {
3464            Self::Const => f.write_str("Constant"),
3465            Self::LetVar => f.write_str("Variable"),
3466            Self::PatternMatchingStructFieldVar => f.write_str("Pattern variable"),
3467        }
3468    }
3469}
3470
3471/// Defines how a storage gets accessed within a function body.
3472/// E.g., calling `__state_clear` intrinsic or using `scwq` ASM instruction
3473/// represent a [StorageAccess::Clear] access.
3474#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3475pub enum StorageAccess {
3476    Clear,
3477    ReadWord,
3478    ReadSlots,
3479    WriteWord,
3480    WriteSlots,
3481    /// Storage access happens via call to an impure function.
3482    /// The parameters are the call path span and if the called function
3483    /// reads from and writes to the storage: (call_path, reads, writes).
3484    ImpureFunctionCall(Span, bool, bool),
3485}
3486
3487impl StorageAccess {
3488    pub fn is_write(&self) -> bool {
3489        matches!(
3490            self,
3491            Self::Clear | Self::WriteWord | Self::WriteSlots | Self::ImpureFunctionCall(_, _, true)
3492        )
3493    }
3494}
3495
3496impl fmt::Display for StorageAccess {
3497    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3498        match self {
3499            Self::Clear => f.write_str("Clearing the storage happens here."),
3500            Self::ReadWord => f.write_str("Reading a word from the storage happens here."),
3501            Self::ReadSlots => f.write_str("Reading storage slots happens here."),
3502            Self::WriteWord => f.write_str("Writing a word to the storage happens here."),
3503            Self::WriteSlots => f.write_str("Writing to storage slots happens here."),
3504            Self::ImpureFunctionCall(call_path, reads, writes) => f.write_fmt(format_args!(
3505                "Function \"{}\" {} the storage.",
3506                short_name(call_path.as_str()),
3507                match (reads, writes) {
3508                    (true, true) => "reads from and writes to",
3509                    (true, false) => "reads from",
3510                    (false, true) => "writes to",
3511                    (false, false) => unreachable!(
3512                        "Function \"{}\" is impure, so it must read from or write to the storage.",
3513                        call_path.as_str()
3514                    ),
3515                }
3516            )),
3517        }
3518    }
3519}
3520
3521/// Extracts only the suffix part of the `marker_trait_full_name`, without the arguments.
3522/// E.g.:
3523/// - `std::marker::Error` => `Error`
3524/// - `std::marker::SomeMarkerTrait::<T>` => `SomeMarkerTrait`
3525/// - `std::marker::SomeMarkerTrait<T>` => `SomeMarkerTrait`
3526///
3527/// Panics if the `marker_trait_full_name` does not start with "std::marker::".
3528fn marker_trait_name(marker_trait_full_name: &str) -> &str {
3529    const MARKER_TRAITS_MODULE: &str = "std::marker::";
3530    assert!(
3531        marker_trait_full_name.starts_with(MARKER_TRAITS_MODULE),
3532        "`marker_trait_full_name` must start with \"std::marker::\", but it was \"{marker_trait_full_name}\""
3533    );
3534
3535    let lower_boundary = MARKER_TRAITS_MODULE.len();
3536    let name_part = &marker_trait_full_name[lower_boundary..];
3537
3538    let upper_boundary = marker_trait_full_name.len() - lower_boundary;
3539    let only_name_len = std::cmp::min(
3540        name_part.find(':').unwrap_or(upper_boundary),
3541        name_part.find('<').unwrap_or(upper_boundary),
3542    );
3543    let upper_boundary = lower_boundary + only_name_len;
3544
3545    &marker_trait_full_name[lower_boundary..upper_boundary]
3546}
3547
3548fn error_marker_trait_help_msg() -> Vec<String> {
3549    vec![
3550        "\"Error\" marker trait is automatically implemented by the compiler for the unit type `()`,".to_string(),
3551        "string slices, and enums annotated with the `#[error_type]` attribute.".to_string(),
3552    ]
3553}