sway_error/
error.rs

1use crate::convert_parse_tree_error::ConvertParseTreeError;
2use crate::diagnostic::{Code, Diagnostic, Hint, Issue, Reason, ToDiagnostic};
3use crate::formatting::*;
4use crate::lex_error::LexError;
5use crate::parser_error::{ParseError, ParseErrorKind};
6use crate::type_error::TypeError;
7
8use core::fmt;
9use std::fmt::Formatter;
10use sway_types::constants::STORAGE_PURITY_ATTRIBUTE_NAME;
11use sway_types::style::to_snake_case;
12use sway_types::{BaseIdent, Ident, IdentUnique, SourceEngine, Span, Spanned};
13use thiserror::Error;
14
15use self::ShadowingSource::*;
16use self::StructFieldUsageContext::*;
17
18#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
19pub enum InterfaceName {
20    Abi(Ident),
21    Trait(Ident),
22}
23
24impl fmt::Display for InterfaceName {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        match self {
27            InterfaceName::Abi(name) => write!(f, "ABI \"{name}\""),
28            InterfaceName::Trait(name) => write!(f, "trait \"{name}\""),
29        }
30    }
31}
32
33// TODO: Since moving to using Idents instead of strings, there are a lot of redundant spans in
34//       this type. When replacing Strings + Spans with Idents, be aware of the rule explained below.
35
36// When defining error structures that display identifiers, we prefer passing Idents over Strings.
37// The error span can come from that same Ident or can be a different span.
38// We handle those two cases in the following way:
39//   - If the error span equals Ident's span, we use IdentUnique and never the plain Ident.
40//   - If the error span is different then Ident's span, we pass Ident and Span as two separate fields.
41//
42// The reason for this rule is clearly communicating the difference of the two cases in every error,
43// as well as avoiding issues with the error message deduplication explained below.
44//
45// Deduplication of error messages might remove errors that are actually not duplicates because
46// although they point to the same Ident (in terms of the identifier's name), the span can be different.
47// Deduplication works on hashes and Ident's hash contains only the name and not the span.
48// That's why we always use IdentUnique whenever we extract the span from the provided Ident.
49// Using IdentUnique also clearly communicates that we are extracting the span from the
50// provided identifier.
51#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
52pub enum CompileError {
53    #[error("\"const generics\" are not supported here.")]
54    ConstGenericNotSupportedHere { span: Span },
55    #[error("This expression is not supported as lengths.")]
56    LengthExpressionNotSupported { span: Span },
57    #[error(
58        "This needs \"{feature}\" to be enabled, but it is currently disabled. For more details go to {url}."
59    )]
60    FeatureIsDisabled {
61        feature: String,
62        url: String,
63        span: Span,
64    },
65    #[error(
66        "There was an error while evaluating the evaluation order for the module dependency graph."
67    )]
68    ModuleDepGraphEvaluationError {},
69    #[error("A cyclic reference was found between the modules: {}.",
70        modules.iter().map(|ident| ident.as_str().to_string())
71    .collect::<Vec<_>>()
72    .join(", "))]
73    ModuleDepGraphCyclicReference { modules: Vec<BaseIdent> },
74
75    #[error("Variable \"{var_name}\" does not exist in this scope.")]
76    UnknownVariable { var_name: Ident, span: Span },
77    #[error("Identifier \"{name}\" was used as a variable, but it is actually a {what_it_is}.")]
78    NotAVariable {
79        name: Ident,
80        what_it_is: &'static str,
81        span: Span,
82    },
83    #[error("{feature} is currently not implemented.")]
84    Unimplemented {
85        /// The description of the unimplemented feature,
86        /// formulated in a way that fits into common ending
87        /// "is currently not implemented."
88        /// E.g., "Using something".
89        feature: String,
90        /// Help lines. Empty if there is no additional help.
91        /// To get an empty line between the help lines,
92        /// insert a [String] containing only a space: `" ".to_string()`.
93        help: Vec<String>,
94        span: Span,
95    },
96    #[error("{0}")]
97    TypeError(TypeError),
98    #[error("Error parsing input: {err:?}")]
99    ParseError { span: Span, err: String },
100    #[error(
101        "Internal compiler error: {0}\nPlease file an issue on the repository and include the \
102         code that triggered this error."
103    )]
104    Internal(&'static str, Span),
105    #[error(
106        "Internal compiler error: {0}\nPlease file an issue on the repository and include the \
107         code that triggered this error."
108    )]
109    InternalOwned(String, Span),
110    #[error(
111        "Predicate declaration contains no main function. Predicates require a main function."
112    )]
113    NoPredicateMainFunction(Span),
114    #[error("A predicate's main function must return a boolean.")]
115    PredicateMainDoesNotReturnBool(Span),
116    #[error("Script declaration contains no main function. Scripts require a main function.")]
117    NoScriptMainFunction(Span),
118    #[error("Fallback function already defined in scope.")]
119    MultipleDefinitionsOfFallbackFunction { name: Ident, span: Span },
120    #[error("Function \"{name}\" was already defined in scope.")]
121    MultipleDefinitionsOfFunction { name: Ident, span: Span },
122    #[error("Name \"{name}\" is defined multiple times.")]
123    MultipleDefinitionsOfName { name: Ident, span: Span },
124    #[error("Constant \"{name}\" was already defined in scope.")]
125    MultipleDefinitionsOfConstant { name: Ident, span: Span },
126    #[error("Type \"{name}\" was already defined in scope.")]
127    MultipleDefinitionsOfType { name: Ident, span: Span },
128    #[error("Variable \"{}\" is already defined in match arm.", first_definition.as_str())]
129    MultipleDefinitionsOfMatchArmVariable {
130        match_value: Span,
131        match_type: String,
132        first_definition: Span,
133        first_definition_is_struct_field: bool,
134        duplicate: Span,
135        duplicate_is_struct_field: bool,
136    },
137    #[error(
138        "Assignment to an immutable variable. Variable \"{decl_name} is not declared as mutable."
139    )]
140    AssignmentToNonMutableVariable {
141        /// Variable name pointing to the name in the variable declaration.
142        decl_name: Ident,
143        /// The complete left-hand side of the assignment.
144        lhs_span: Span,
145    },
146    #[error(
147        "Assignment to a {}. {} cannot be assigned to.",
148        if *is_configurable {
149            "configurable"
150        } else {
151            "constant"
152        },
153        if *is_configurable {
154            "Configurables"
155        } else {
156            "Constants"
157        }
158    )]
159    AssignmentToConstantOrConfigurable {
160        /// Constant or configurable name pointing to the name in the constant declaration.
161        decl_name: Ident,
162        is_configurable: bool,
163        /// The complete left-hand side of the assignment.
164        lhs_span: Span,
165    },
166    #[error(
167        "This assignment target cannot be assigned to, because {} is {}{decl_friendly_type_name} and not a mutable variable.",
168        if let Some(decl_name) = decl_name {
169            format!("\"{decl_name}\"")
170        } else {
171            "this".to_string()
172        },
173        a_or_an(decl_friendly_type_name)
174    )]
175    DeclAssignmentTargetCannotBeAssignedTo {
176        /// Name of the declared variant, pointing to the name in the declaration.
177        decl_name: Option<Ident>,
178        /// Friendly name of the type of the declaration. E.g., "function", or "struct".
179        decl_friendly_type_name: &'static str,
180        /// The complete left-hand side of the assignment.
181        lhs_span: Span,
182    },
183    #[error("This reference is not a reference to a mutable value (`&mut`).")]
184    AssignmentViaNonMutableReference {
185        /// Name of the reference, if the left-hand side of the assignment is a reference variable,
186        /// pointing to the name in the reference variable declaration.
187        ///
188        /// `None` if the assignment LHS is an arbitrary expression and not a variable.
189        decl_reference_name: Option<Ident>,
190        /// [Span] of the right-hand side of the reference variable definition,
191        /// if the left-hand side of the assignment is a reference variable.
192        decl_reference_rhs: Option<Span>,
193        /// The type of the reference, if the left-hand side of the assignment is a reference variable,
194        /// expected to start with `&`.
195        decl_reference_type: String,
196        span: Span,
197    },
198    #[error(
199        "Cannot call method \"{method_name}\" on variable \"{variable_name}\" because \
200            \"{variable_name}\" is not declared as mutable."
201    )]
202    MethodRequiresMutableSelf {
203        method_name: Ident,
204        variable_name: Ident,
205        span: Span,
206    },
207    #[error(
208        "This parameter was declared as mutable, which is not supported yet, did you mean to use ref mut?"
209    )]
210    MutableParameterNotSupported { param_name: Ident, span: Span },
211    #[error("Cannot pass immutable argument to mutable parameter.")]
212    ImmutableArgumentToMutableParameter { span: Span },
213    #[error("ref mut or mut parameter is not allowed for contract ABI function.")]
214    RefMutableNotAllowedInContractAbi { param_name: Ident, span: Span },
215    #[error("Reference to a mutable value cannot reference a constant.")]
216    RefMutCannotReferenceConstant {
217        /// Constant, as accessed in code. E.g.:
218        ///  - `MY_CONST`
219        ///  - `LIB_CONST_ALIAS`
220        ///  - `::lib::module::SOME_CONST`
221        constant: String,
222        span: Span,
223    },
224    #[error("Reference to a mutable value cannot reference an immutable variable.")]
225    RefMutCannotReferenceImmutableVariable {
226        /// Variable name pointing to the name in the variable declaration.
227        decl_name: Ident,
228        span: Span,
229    },
230    #[error(
231        "Cannot call associated function \"{fn_name}\" as a method. Use associated function \
232        syntax instead."
233    )]
234    AssociatedFunctionCalledAsMethod { fn_name: Ident, span: Span },
235    #[error(
236        "Generic type \"{name}\" is not in scope. Perhaps you meant to specify type parameters in \
237         the function signature? For example: \n`fn \
238         {fn_name}<{comma_separated_generic_params}>({args}) -> ... `"
239    )]
240    TypeParameterNotInTypeScope {
241        name: Ident,
242        span: Span,
243        comma_separated_generic_params: String,
244        fn_name: Ident,
245        args: String,
246    },
247    #[error(
248        "expected: {expected} \n\
249         found:    {given} \n\
250         help:     The definition of this {decl_type} must \
251         match the one in the {interface_name} declaration."
252    )]
253    MismatchedTypeInInterfaceSurface {
254        interface_name: InterfaceName,
255        span: Span,
256        decl_type: String,
257        given: String,
258        expected: String,
259    },
260    #[error("Trait \"{name}\" cannot be found in the current scope.")]
261    UnknownTrait { span: Span, name: Ident },
262    #[error("Function \"{name}\" is not a part of {interface_name}'s interface surface.")]
263    FunctionNotAPartOfInterfaceSurface {
264        name: Ident,
265        interface_name: InterfaceName,
266        span: Span,
267    },
268    #[error("Constant \"{name}\" is not a part of {interface_name}'s interface surface.")]
269    ConstantNotAPartOfInterfaceSurface {
270        name: Ident,
271        interface_name: InterfaceName,
272        span: Span,
273    },
274    #[error("Type \"{name}\" is not a part of {interface_name}'s interface surface.")]
275    TypeNotAPartOfInterfaceSurface {
276        name: Ident,
277        interface_name: InterfaceName,
278        span: Span,
279    },
280    #[error("Constants are missing from this trait implementation: {}",
281        missing_constants.iter().map(|ident| ident.as_str().to_string())
282        .collect::<Vec<_>>()
283        .join("\n"))]
284    MissingInterfaceSurfaceConstants {
285        missing_constants: Vec<BaseIdent>,
286        span: Span,
287    },
288    #[error("Associated types are missing from this trait implementation: {}",
289        missing_types.iter().map(|ident| ident.as_str().to_string())
290        .collect::<Vec<_>>()
291        .join("\n"))]
292    MissingInterfaceSurfaceTypes {
293        missing_types: Vec<BaseIdent>,
294        span: Span,
295    },
296    #[error("Functions are missing from this trait implementation: {}",
297        missing_functions.iter().map(|ident| ident.as_str().to_string())
298        .collect::<Vec<_>>()
299        .join("\n"))]
300    MissingInterfaceSurfaceMethods {
301        missing_functions: Vec<BaseIdent>,
302        span: Span,
303    },
304    #[error("Expected {} type {} for \"{name}\", but instead found {}.", expected, if *expected == 1usize { "argument" } else { "arguments" }, given)]
305    IncorrectNumberOfTypeArguments {
306        name: Ident,
307        given: usize,
308        expected: usize,
309        span: Span,
310    },
311    #[error("\"{name}\" does not take type arguments.")]
312    DoesNotTakeTypeArguments { name: Ident, span: Span },
313    #[error("\"{name}\" does not take type arguments as prefix.")]
314    DoesNotTakeTypeArgumentsAsPrefix { name: Ident, span: Span },
315    #[error("Type arguments are not allowed for this type.")]
316    TypeArgumentsNotAllowed { span: Span },
317    #[error("\"{name}\" needs type arguments.")]
318    NeedsTypeArguments { name: Ident, span: Span },
319    #[error(
320        "Enum with name \"{name}\" could not be found in this scope. Perhaps you need to import \
321         it?"
322    )]
323    EnumNotFound { name: Ident, span: Span },
324    /// This error is used only for error recovery and is not emitted as a compiler
325    /// error to the final compilation output. The compiler emits the cumulative error
326    /// [CompileError::StructInstantiationMissingFields] given below, and that one also
327    /// only if the struct can actually be instantiated.
328    #[error("Instantiation of the struct \"{struct_name}\" is missing field \"{field_name}\".")]
329    StructInstantiationMissingFieldForErrorRecovery {
330        field_name: Ident,
331        /// Original, non-aliased struct name.
332        struct_name: Ident,
333        span: Span,
334    },
335    #[error("Instantiation of the struct \"{struct_name}\" is missing {} {}.",
336        if field_names.len() == 1 { "field" } else { "fields" },
337        field_names.iter().map(|name| format!("\"{name}\"")).collect::<Vec::<_>>().join(", "))]
338    StructInstantiationMissingFields {
339        field_names: Vec<Ident>,
340        /// Original, non-aliased struct name.
341        struct_name: Ident,
342        span: Span,
343        struct_decl_span: Span,
344        total_number_of_fields: usize,
345    },
346    #[error("Struct \"{struct_name}\" cannot be instantiated here because it has private fields.")]
347    StructCannotBeInstantiated {
348        /// Original, non-aliased struct name.
349        struct_name: Ident,
350        span: Span,
351        struct_decl_span: Span,
352        private_fields: Vec<Ident>,
353        /// All available public constructors if `is_in_storage_declaration` is false,
354        /// or only the public constructors that potentially evaluate to a constant
355        /// if `is_in_storage_declaration` is true.
356        constructors: Vec<String>,
357        /// True if the struct has only private fields.
358        all_fields_are_private: bool,
359        is_in_storage_declaration: bool,
360        struct_can_be_changed: bool,
361    },
362    #[error("Field \"{field_name}\" of the struct \"{struct_name}\" is private.")]
363    StructFieldIsPrivate {
364        field_name: IdentUnique,
365        /// Original, non-aliased struct name.
366        struct_name: Ident,
367        field_decl_span: Span,
368        struct_can_be_changed: bool,
369        usage_context: StructFieldUsageContext,
370    },
371    #[error("Field \"{field_name}\" does not exist in struct \"{struct_name}\".")]
372    StructFieldDoesNotExist {
373        field_name: IdentUnique,
374        /// Only public fields if `is_public_struct_access` is true.
375        available_fields: Vec<Ident>,
376        is_public_struct_access: bool,
377        /// Original, non-aliased struct name.
378        struct_name: Ident,
379        struct_decl_span: Span,
380        struct_is_empty: bool,
381        usage_context: StructFieldUsageContext,
382    },
383    #[error("Field \"{field_name}\" has multiple definitions.")]
384    StructFieldDuplicated { field_name: Ident, duplicate: Ident },
385    #[error("No method \"{method}\" found for type \"{type_name}\".{}", 
386        if matching_method_strings.is_empty() {
387            "".to_string()
388        } else {
389            format!("  \nMatching method{}:\n{}", if matching_method_strings.len()> 1 {"s"} else {""},
390            matching_method_strings.iter().map(|m| format!("    {m}")).collect::<Vec<_>>().join("\n"))
391        }
392    )]
393    MethodNotFound {
394        method: String,
395        type_name: String,
396        matching_method_strings: Vec<String>,
397        span: Span,
398    },
399    #[error("Module \"{name}\" could not be found.")]
400    ModuleNotFound { span: Span, name: String },
401    #[error("This expression has type \"{actually}\", which is not a struct. Fields can only be accessed on structs.")]
402    FieldAccessOnNonStruct {
403        actually: String,
404        /// Name of the storage variable, if the field access
405        /// happens within the access to a storage variable.
406        storage_variable: Option<String>,
407        /// Name of the field that is tried to be accessed.
408        field_name: IdentUnique,
409        span: Span,
410    },
411    #[error("This expression has type \"{actually}\", which is not a tuple. Elements can only be accessed on tuples.")]
412    TupleElementAccessOnNonTuple {
413        actually: String,
414        span: Span,
415        index: usize,
416        index_span: Span,
417    },
418    #[error("This expression has type \"{actually}\", which is not an indexable type.")]
419    NotIndexable { actually: String, span: Span },
420    #[error("\"{name}\" is a {actually}, not an enum.")]
421    NotAnEnum {
422        name: String,
423        span: Span,
424        actually: String,
425    },
426    #[error("This is a {actually}, not a struct.")]
427    NotAStruct { span: Span, actually: String },
428    #[error("This is a {actually}, not an enum.")]
429    DeclIsNotAnEnum { actually: String, span: Span },
430    #[error("This is a {actually}, not a struct.")]
431    DeclIsNotAStruct { actually: String, span: Span },
432    #[error("This is a {actually}, not a function.")]
433    DeclIsNotAFunction { actually: String, span: Span },
434    #[error("This is a {actually}, not a variable.")]
435    DeclIsNotAVariable { actually: String, span: Span },
436    #[error("This is a {actually}, not an ABI.")]
437    DeclIsNotAnAbi { actually: String, span: Span },
438    #[error("This is a {actually}, not a trait.")]
439    DeclIsNotATrait { actually: String, span: Span },
440    #[error("This is a {actually}, not an impl block.")]
441    DeclIsNotAnImplTrait { actually: String, span: Span },
442    #[error("This is a {actually}, not a trait function.")]
443    DeclIsNotATraitFn { actually: String, span: Span },
444    #[error("This is a {actually}, not storage.")]
445    DeclIsNotStorage { actually: String, span: Span },
446    #[error("This is a {actually}, not a constant")]
447    DeclIsNotAConstant { actually: String, span: Span },
448    #[error("This is a {actually}, not a type alias")]
449    DeclIsNotATypeAlias { actually: String, span: Span },
450    #[error("Could not find symbol \"{name}\" in this scope.")]
451    SymbolNotFound { name: Ident, span: Span },
452    #[error("Found multiple bindings for \"{name}\" in this scope.")]
453    SymbolWithMultipleBindings {
454        name: Ident,
455        paths: Vec<String>,
456        span: Span,
457    },
458    #[error("Symbol \"{name}\" is private.")]
459    ImportPrivateSymbol { name: Ident, span: Span },
460    #[error("Module \"{name}\" is private.")]
461    ImportPrivateModule { name: Ident, span: Span },
462    #[error(
463        "Because this if expression's value is used, an \"else\" branch is required and it must \
464         return type \"{r#type}\""
465    )]
466    NoElseBranch { span: Span, r#type: String },
467    #[error(
468        "Symbol \"{name}\" does not refer to a type, it refers to a {actually_is}. It cannot be \
469         used in this position."
470    )]
471    NotAType {
472        span: Span,
473        name: String,
474        actually_is: &'static str,
475    },
476    #[error(
477        "This enum variant requires an instantiation expression. Try initializing it with \
478         arguments in parentheses."
479    )]
480    MissingEnumInstantiator { span: Span },
481    #[error(
482        "This path must return a value of type \"{ty}\" from function \"{function_name}\", but it \
483         does not."
484    )]
485    PathDoesNotReturn {
486        span: Span,
487        ty: String,
488        function_name: Ident,
489    },
490    #[error(
491        "Expected Module level doc comment. All other attributes are unsupported at this level."
492    )]
493    ExpectedModuleDocComment { span: Span },
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("Conflicting implementations of trait \"{trait_name}\" 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_PURITY_ATTRIBUTE_NAME}\" annotation must be \
819        removed, or the trait declaration must be changed to \
820        \"#[{STORAGE_PURITY_ATTRIBUTE_NAME}({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_PURITY_ATTRIBUTE_NAME}({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_PURITY_ATTRIBUTE_NAME}({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} arguments")]
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("Expected string literal")]
935    ExpectedStringLiteral { span: Span },
936    #[error("\"break\" used outside of a loop")]
937    BreakOutsideLoop { span: Span },
938    #[error("\"continue\" used outside of a loop")]
939    ContinueOutsideLoop { span: Span },
940    /// This will be removed once loading contract IDs in a dependency namespace is refactored and no longer manual:
941    /// https://github.com/FuelLabs/sway/issues/3077
942    #[error("Contract ID value is not a literal.")]
943    ContractIdValueNotALiteral { span: Span },
944
945    #[error("{reason}")]
946    TypeNotAllowed {
947        reason: TypeNotAllowedReason,
948        span: Span,
949    },
950    #[error("ref mut parameter not allowed for main()")]
951    RefMutableNotAllowedInMain { param_name: Ident, span: Span },
952    #[error(
953        "Register \"{name}\" is initialized and later reassigned which is not allowed. \
954            Consider assigning to a different register inside the ASM block."
955    )]
956    InitializedRegisterReassignment { name: String, span: Span },
957    #[error("Control flow VM instructions are not allowed in assembly blocks.")]
958    DisallowedControlFlowInstruction { name: String, span: Span },
959    #[error("Calling private library method {name} is not allowed.")]
960    CallingPrivateLibraryMethod { name: String, span: Span },
961    #[error("Using intrinsic \"{intrinsic}\" in a predicate is not allowed.")]
962    DisallowedIntrinsicInPredicate { intrinsic: String, span: Span },
963    #[error("Possibly non-zero amount of coins transferred to non-payable contract method \"{fn_name}\".")]
964    CoinsPassedToNonPayableMethod { fn_name: Ident, span: Span },
965    #[error(
966        "Payable attribute mismatch. The \"{fn_name}\" method implementation \
967         {} in its signature in {interface_name}.",
968        if *missing_impl_attribute {
969            "is missing #[payable] attribute specified"
970        } else {
971            "has extra #[payable] attribute not mentioned"
972        }
973    )]
974    TraitImplPayabilityMismatch {
975        fn_name: Ident,
976        interface_name: InterfaceName,
977        missing_impl_attribute: bool,
978        span: Span,
979    },
980    #[error("Configurable constants are not allowed in libraries.")]
981    ConfigurableInLibrary { span: Span },
982    #[error("Multiple applicable items in scope. {}", {
983        let mut candidates = "".to_string();
984        let mut as_traits = as_traits.clone();
985        // Make order deterministic
986        as_traits.sort_by_key(|a| a.0.to_lowercase());
987        for (index, as_trait) in as_traits.iter().enumerate() {
988            candidates = format!("{candidates}\n  Disambiguate the associated {item_kind} for candidate #{index}\n    <{} as {}>::{item_name}", as_trait.1, as_trait.0);
989        }
990        candidates
991    })]
992    MultipleApplicableItemsInScope {
993        span: Span,
994        item_name: String,
995        item_kind: String,
996        as_traits: Vec<(String, String)>,
997    },
998    #[error("Provided generic type is not of type str.")]
999    NonStrGenericType { span: Span },
1000    #[error("A contract method cannot call methods belonging to the same ABI")]
1001    ContractCallsItsOwnMethod { span: Span },
1002    #[error("ABI cannot define a method of the same name as its super-ABI \"{superabi}\"")]
1003    AbiShadowsSuperAbiMethod { span: Span, superabi: Ident },
1004    #[error("ABI cannot inherit samely named method (\"{method_name}\") from several super-ABIs: \"{superabi1}\" and \"{superabi2}\"")]
1005    ConflictingSuperAbiMethods {
1006        span: Span,
1007        method_name: String,
1008        superabi1: String,
1009        superabi2: String,
1010    },
1011    #[error("Associated types not supported in ABI.")]
1012    AssociatedTypeNotSupportedInAbi { span: Span },
1013    #[error("Cannot call ABI supertrait's method as a contract method: \"{fn_name}\"")]
1014    AbiSupertraitMethodCallAsContractCall { fn_name: Ident, span: Span },
1015    #[error(
1016        "Methods {method_name} and {other_method_name} name have clashing function selectors."
1017    )]
1018    FunctionSelectorClash {
1019        method_name: Ident,
1020        span: Span,
1021        other_method_name: Ident,
1022        other_span: Span,
1023    },
1024    #[error("{invalid_type} is not a valid type in the self type of an impl block.")]
1025    TypeIsNotValidAsImplementingFor {
1026        invalid_type: InvalidImplementingForType,
1027        /// Name of the trait if the impl implements a trait, `None` otherwise.
1028        trait_name: Option<String>,
1029        span: Span,
1030    },
1031    #[error("Uninitialized register is being read before being written")]
1032    UninitRegisterInAsmBlockBeingRead { span: Span },
1033    #[error("Expression of type \"{expression_type}\" cannot be dereferenced.")]
1034    ExpressionCannotBeDereferenced { expression_type: String, span: Span },
1035    #[error("Fallback functions can only exist in contracts")]
1036    FallbackFnsAreContractOnly { span: Span },
1037    #[error("Fallback functions cannot have parameters")]
1038    FallbackFnsCannotHaveParameters { span: Span },
1039    #[error("Could not generate the entry method. See errors above for more details.")]
1040    CouldNotGenerateEntry { span: Span },
1041    #[error("Missing `std` in dependencies.")]
1042    CouldNotGenerateEntryMissingStd { span: Span },
1043    #[error("Type \"{ty}\" does not implement AbiEncode or AbiDecode.")]
1044    CouldNotGenerateEntryMissingImpl { ty: String, span: Span },
1045    #[error("Only bool, u8, u16, u32, u64, u256, b256, string arrays and string slices can be used here.")]
1046    EncodingUnsupportedType { span: Span },
1047    #[error("Configurables need a function named \"abi_decode_in_place\" to be in scope.")]
1048    ConfigurableMissingAbiDecodeInPlace { span: Span },
1049    #[error("Collision detected between two different types.\n  Shared hash:{hash}\n  First type:{first_type}\n  Second type:{second_type}")]
1050    ABIHashCollision {
1051        span: Span,
1052        hash: String,
1053        first_type: String,
1054        second_type: String,
1055    },
1056    #[error("Type must be known at this point")]
1057    TypeMustBeKnownAtThisPoint { span: Span, internal: String },
1058    #[error("Multiple impls satisfying trait for type.")]
1059    MultipleImplsSatisfyingTraitForType {
1060        span: Span,
1061        type_annotation: String,
1062        trait_names: Vec<String>,
1063        trait_types_and_names: Vec<(String, String)>,
1064    },
1065    #[error("Multiple contracts methods with the same name.")]
1066    MultipleContractsMethodsWithTheSameName { spans: Vec<Span> },
1067}
1068
1069impl std::convert::From<TypeError> for CompileError {
1070    fn from(other: TypeError) -> CompileError {
1071        CompileError::TypeError(other)
1072    }
1073}
1074
1075impl Spanned for CompileError {
1076    fn span(&self) -> Span {
1077        use CompileError::*;
1078        match self {
1079            ConstGenericNotSupportedHere { span } => span.clone(),
1080            LengthExpressionNotSupported { span } => span.clone(),
1081            FeatureIsDisabled { span, .. } => span.clone(),
1082            ModuleDepGraphEvaluationError { .. } => Span::dummy(),
1083            ModuleDepGraphCyclicReference { .. } => Span::dummy(),
1084            UnknownVariable { span, .. } => span.clone(),
1085            NotAVariable { span, .. } => span.clone(),
1086            Unimplemented { span, .. } => span.clone(),
1087            TypeError(err) => err.span(),
1088            ParseError { span, .. } => span.clone(),
1089            Internal(_, span) => span.clone(),
1090            InternalOwned(_, span) => span.clone(),
1091            NoPredicateMainFunction(span) => span.clone(),
1092            PredicateMainDoesNotReturnBool(span) => span.clone(),
1093            NoScriptMainFunction(span) => span.clone(),
1094            MultipleDefinitionsOfFunction { span, .. } => span.clone(),
1095            MultipleDefinitionsOfName { span, .. } => span.clone(),
1096            MultipleDefinitionsOfConstant { span, .. } => span.clone(),
1097            MultipleDefinitionsOfType { span, .. } => span.clone(),
1098            MultipleDefinitionsOfMatchArmVariable { duplicate, .. } => duplicate.clone(),
1099            MultipleDefinitionsOfFallbackFunction { span, .. } => span.clone(),
1100            AssignmentToNonMutableVariable { lhs_span, .. } => lhs_span.clone(),
1101            AssignmentToConstantOrConfigurable { lhs_span, .. } => lhs_span.clone(),
1102            DeclAssignmentTargetCannotBeAssignedTo { lhs_span, .. } => lhs_span.clone(),
1103            AssignmentViaNonMutableReference { span, .. } => span.clone(),
1104            MutableParameterNotSupported { span, .. } => span.clone(),
1105            ImmutableArgumentToMutableParameter { span } => span.clone(),
1106            RefMutableNotAllowedInContractAbi { span, .. } => span.clone(),
1107            RefMutCannotReferenceConstant { span, .. } => span.clone(),
1108            RefMutCannotReferenceImmutableVariable { span, .. } => span.clone(),
1109            MethodRequiresMutableSelf { span, .. } => span.clone(),
1110            AssociatedFunctionCalledAsMethod { span, .. } => span.clone(),
1111            TypeParameterNotInTypeScope { span, .. } => span.clone(),
1112            MismatchedTypeInInterfaceSurface { span, .. } => span.clone(),
1113            UnknownTrait { span, .. } => span.clone(),
1114            FunctionNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1115            ConstantNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1116            TypeNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1117            MissingInterfaceSurfaceConstants { span, .. } => span.clone(),
1118            MissingInterfaceSurfaceTypes { span, .. } => span.clone(),
1119            MissingInterfaceSurfaceMethods { span, .. } => span.clone(),
1120            IncorrectNumberOfTypeArguments { span, .. } => span.clone(),
1121            DoesNotTakeTypeArguments { span, .. } => span.clone(),
1122            DoesNotTakeTypeArgumentsAsPrefix { span, .. } => span.clone(),
1123            TypeArgumentsNotAllowed { span } => span.clone(),
1124            NeedsTypeArguments { span, .. } => span.clone(),
1125            StructInstantiationMissingFieldForErrorRecovery { span, .. } => span.clone(),
1126            StructInstantiationMissingFields { span, .. } => span.clone(),
1127            StructCannotBeInstantiated { span, .. } => span.clone(),
1128            StructFieldIsPrivate { field_name, .. } => field_name.span(),
1129            StructFieldDoesNotExist { field_name, .. } => field_name.span(),
1130            StructFieldDuplicated { field_name, .. } => field_name.span(),
1131            MethodNotFound { span, .. } => span.clone(),
1132            ModuleNotFound { span, .. } => span.clone(),
1133            TupleElementAccessOnNonTuple { span, .. } => span.clone(),
1134            NotAStruct { span, .. } => span.clone(),
1135            NotIndexable { span, .. } => span.clone(),
1136            FieldAccessOnNonStruct { span, .. } => span.clone(),
1137            SymbolNotFound { span, .. } => span.clone(),
1138            SymbolWithMultipleBindings { span, .. } => span.clone(),
1139            ImportPrivateSymbol { span, .. } => span.clone(),
1140            ImportPrivateModule { span, .. } => span.clone(),
1141            NoElseBranch { span, .. } => span.clone(),
1142            NotAType { span, .. } => span.clone(),
1143            MissingEnumInstantiator { span, .. } => span.clone(),
1144            PathDoesNotReturn { span, .. } => span.clone(),
1145            ExpectedModuleDocComment { span } => span.clone(),
1146            UnknownRegister { span, .. } => span.clone(),
1147            MissingImmediate { span, .. } => span.clone(),
1148            InvalidImmediateValue { span, .. } => span.clone(),
1149            UnknownEnumVariant { span, .. } => span.clone(),
1150            UnrecognizedOp { span, .. } => span.clone(),
1151            UnableToInferGeneric { span, .. } => span.clone(),
1152            UnconstrainedGenericParameter { span, .. } => span.clone(),
1153            TraitConstraintNotSatisfied { span, .. } => span.clone(),
1154            TraitConstraintMissing { span, .. } => span.clone(),
1155            Immediate06TooLarge { span, .. } => span.clone(),
1156            Immediate12TooLarge { span, .. } => span.clone(),
1157            Immediate18TooLarge { span, .. } => span.clone(),
1158            Immediate24TooLarge { span, .. } => span.clone(),
1159            IncorrectNumberOfAsmRegisters { span, .. } => span.clone(),
1160            UnnecessaryImmediate { span, .. } => span.clone(),
1161            AmbiguousPath { span } => span.clone(),
1162            ModulePathIsNotAnExpression { span, .. } => span.clone(),
1163            UnknownType { span, .. } => span.clone(),
1164            UnknownTypeName { span, .. } => span.clone(),
1165            FileCouldNotBeRead { span, .. } => span.clone(),
1166            ImportMustBeLibrary { span, .. } => span.clone(),
1167            MoreThanOneEnumInstantiator { span, .. } => span.clone(),
1168            UnnecessaryEnumInstantiator { span, .. } => span.clone(),
1169            UnitVariantWithParenthesesEnumInstantiator { span, .. } => span.clone(),
1170            TraitNotFound { span, .. } => span.clone(),
1171            TraitNotImportedAtFunctionApplication {
1172                function_call_site_span,
1173                ..
1174            } => function_call_site_span.clone(),
1175            InvalidExpressionOnLhs { span, .. } => span.clone(),
1176            TooManyArgumentsForFunction { span, .. } => span.clone(),
1177            TooFewArgumentsForFunction { span, .. } => span.clone(),
1178            MissingParenthesesForFunction { span, .. } => span.clone(),
1179            InvalidAbiType { span, .. } => span.clone(),
1180            NotAnAbi { span, .. } => span.clone(),
1181            ImplAbiForNonContract { span, .. } => span.clone(),
1182            ConflictingImplsForTraitAndType {
1183                second_impl_span, ..
1184            } => second_impl_span.clone(),
1185            MarkerTraitExplicitlyImplemented { span, .. } => span.clone(),
1186            DuplicateDeclDefinedForType {
1187                second_impl_span, ..
1188            } => second_impl_span.clone(),
1189            IncorrectNumberOfInterfaceSurfaceFunctionParameters { span, .. } => span.clone(),
1190            ArgumentParameterTypeMismatch { span, .. } => span.clone(),
1191            RecursiveCall { span, .. } => span.clone(),
1192            RecursiveCallChain { span, .. } => span.clone(),
1193            RecursiveType { span, .. } => span.clone(),
1194            RecursiveTypeChain { span, .. } => span.clone(),
1195            GMFromExternalContext { span, .. } => span.clone(),
1196            MintFromExternalContext { span, .. } => span.clone(),
1197            BurnFromExternalContext { span, .. } => span.clone(),
1198            ContractStorageFromExternalContext { span, .. } => span.clone(),
1199            InvalidOpcodeFromPredicate { span, .. } => span.clone(),
1200            ArrayOutOfBounds { span, .. } => span.clone(),
1201            ConstantRequiresExpression { span, .. } => span.clone(),
1202            ConstantsCannotBeShadowed { name, .. } => name.span(),
1203            ConfigurablesCannotBeShadowed { name, .. } => name.span(),
1204            ConfigurablesCannotBeMatchedAgainst { name, .. } => name.span(),
1205            ConstantShadowsVariable { name, .. } => name.span(),
1206            ConstantDuplicatesConstantOrConfigurable { name, .. } => name.span(),
1207            ShadowsOtherSymbol { name } => name.span(),
1208            GenericShadowsGeneric { name } => name.span(),
1209            MatchExpressionNonExhaustive { span, .. } => span.clone(),
1210            MatchStructPatternMissingFields { span, .. } => span.clone(),
1211            MatchStructPatternMustIgnorePrivateFields { span, .. } => span.clone(),
1212            MatchArmVariableNotDefinedInAllAlternatives { variable, .. } => variable.span(),
1213            MatchArmVariableMismatchedType { variable, .. } => variable.span(),
1214            MatchedValueIsNotValid { span, .. } => span.clone(),
1215            NotAnEnum { span, .. } => span.clone(),
1216            TraitDeclPureImplImpure { span, .. } => span.clone(),
1217            TraitImplPurityMismatch { span, .. } => span.clone(),
1218            DeclIsNotAnEnum { span, .. } => span.clone(),
1219            DeclIsNotAStruct { span, .. } => span.clone(),
1220            DeclIsNotAFunction { span, .. } => span.clone(),
1221            DeclIsNotAVariable { span, .. } => span.clone(),
1222            DeclIsNotAnAbi { span, .. } => span.clone(),
1223            DeclIsNotATrait { span, .. } => span.clone(),
1224            DeclIsNotAnImplTrait { span, .. } => span.clone(),
1225            DeclIsNotATraitFn { span, .. } => span.clone(),
1226            DeclIsNotStorage { span, .. } => span.clone(),
1227            DeclIsNotAConstant { span, .. } => span.clone(),
1228            DeclIsNotATypeAlias { span, .. } => span.clone(),
1229            ImpureInNonContract { span, .. } => span.clone(),
1230            StorageAccessMismatched { span, .. } => span.clone(),
1231            ParameterRefMutabilityMismatch { span, .. } => span.clone(),
1232            IntegerTooLarge { span, .. } => span.clone(),
1233            IntegerTooSmall { span, .. } => span.clone(),
1234            IntegerContainsInvalidDigit { span, .. } => span.clone(),
1235            AbiAsSupertrait { span, .. } => span.clone(),
1236            SupertraitImplRequired { span, .. } => span.clone(),
1237            ContractCallParamRepeated { span, .. } => span.clone(),
1238            UnrecognizedContractParam { span, .. } => span.clone(),
1239            CallParamForNonContractCallMethod { span, .. } => span.clone(),
1240            StorageFieldDoesNotExist { field_name, .. } => field_name.span(),
1241            InvalidStorageOnlyTypeDecl { span, .. } => span.clone(),
1242            NoDeclaredStorage { span, .. } => span.clone(),
1243            MultipleStorageDeclarations { span, .. } => span.clone(),
1244            UnexpectedDeclaration { span, .. } => span.clone(),
1245            ContractAddressMustBeKnown { span, .. } => span.clone(),
1246            ConvertParseTree { error } => error.span(),
1247            Lex { error } => error.span(),
1248            Parse { error } => error.span.clone(),
1249            EnumNotFound { span, .. } => span.clone(),
1250            TupleIndexOutOfBounds { span, .. } => span.clone(),
1251            NonConstantDeclValue { span, .. } => span.clone(),
1252            StorageDeclarationInNonContract { span, .. } => span.clone(),
1253            IntrinsicUnsupportedArgType { span, .. } => span.clone(),
1254            IntrinsicIncorrectNumArgs { span, .. } => span.clone(),
1255            IntrinsicIncorrectNumTArgs { span, .. } => span.clone(),
1256            BreakOutsideLoop { span } => span.clone(),
1257            ContinueOutsideLoop { span } => span.clone(),
1258            ContractIdValueNotALiteral { span } => span.clone(),
1259            RefMutableNotAllowedInMain { span, .. } => span.clone(),
1260            InitializedRegisterReassignment { span, .. } => span.clone(),
1261            DisallowedControlFlowInstruction { span, .. } => span.clone(),
1262            CallingPrivateLibraryMethod { span, .. } => span.clone(),
1263            DisallowedIntrinsicInPredicate { span, .. } => span.clone(),
1264            CoinsPassedToNonPayableMethod { span, .. } => span.clone(),
1265            TraitImplPayabilityMismatch { span, .. } => span.clone(),
1266            ConfigurableInLibrary { span } => span.clone(),
1267            MultipleApplicableItemsInScope { span, .. } => span.clone(),
1268            NonStrGenericType { span } => span.clone(),
1269            CannotBeEvaluatedToConst { span } => span.clone(),
1270            ContractCallsItsOwnMethod { span } => span.clone(),
1271            AbiShadowsSuperAbiMethod { span, .. } => span.clone(),
1272            ConflictingSuperAbiMethods { span, .. } => span.clone(),
1273            AssociatedTypeNotSupportedInAbi { span, .. } => span.clone(),
1274            AbiSupertraitMethodCallAsContractCall { span, .. } => span.clone(),
1275            FunctionSelectorClash { span, .. } => span.clone(),
1276            TypeNotAllowed { span, .. } => span.clone(),
1277            ExpectedStringLiteral { span } => span.clone(),
1278            TypeIsNotValidAsImplementingFor { span, .. } => span.clone(),
1279            UninitRegisterInAsmBlockBeingRead { span } => span.clone(),
1280            ExpressionCannotBeDereferenced { span, .. } => span.clone(),
1281            FallbackFnsAreContractOnly { span } => span.clone(),
1282            FallbackFnsCannotHaveParameters { span } => span.clone(),
1283            CouldNotGenerateEntry { span } => span.clone(),
1284            CouldNotGenerateEntryMissingStd { span } => span.clone(),
1285            CouldNotGenerateEntryMissingImpl { span, .. } => span.clone(),
1286            CannotBeEvaluatedToConfigurableSizeUnknown { span } => span.clone(),
1287            EncodingUnsupportedType { span } => span.clone(),
1288            ConfigurableMissingAbiDecodeInPlace { span } => span.clone(),
1289            ABIHashCollision { span, .. } => span.clone(),
1290            InvalidRangeEndGreaterThanStart { span, .. } => span.clone(),
1291            TypeMustBeKnownAtThisPoint { span, .. } => span.clone(),
1292            MultipleImplsSatisfyingTraitForType { span, .. } => span.clone(),
1293            MultipleContractsMethodsWithTheSameName { spans } => spans[0].clone(),
1294        }
1295    }
1296}
1297
1298// When implementing diagnostics, follow these two guidelines outlined in the Expressive Diagnostics RFC:
1299// - Guide-level explanation: https://github.com/FuelLabs/sway-rfcs/blob/master/rfcs/0011-expressive-diagnostics.md#guide-level-explanation
1300// - Wording guidelines: https://github.com/FuelLabs/sway-rfcs/blob/master/rfcs/0011-expressive-diagnostics.md#wording-guidelines
1301// For concrete examples, look at the existing diagnostics.
1302//
1303// The issue and the hints are not displayed if set to `Span::dummy()`.
1304//
1305// NOTE: Issue level should actually be the part of the reason. But it would complicate handling of labels in the transitional
1306//       period when we still have "old-style" diagnostics.
1307//       Let's leave it like this. Refactoring currently doesn't pay off.
1308//       And our #[error] macro will anyhow encapsulate it and ensure consistency.
1309impl ToDiagnostic for CompileError {
1310    fn to_diagnostic(&self, source_engine: &SourceEngine) -> Diagnostic {
1311        let code = Code::semantic_analysis;
1312        use CompileError::*;
1313        match self {
1314            ConstantsCannotBeShadowed { shadowing_source, name, constant_span, constant_decl_span, is_alias } => Diagnostic {
1315                reason: Some(Reason::new(code(1), "Constants cannot be shadowed".to_string())),
1316                issue: Issue::error(
1317                    source_engine,
1318                    name.span(),
1319                    format!(
1320                        // Variable "x" shadows constant with of same name.
1321                        //  or
1322                        // Constant "x" shadows imported constant of the same name.
1323                        //  or
1324                        // ...
1325                        "{shadowing_source} \"{name}\" shadows {}constant of the same name.",
1326                        if constant_decl_span.clone() != Span::dummy() { "imported " } else { "" }
1327                    )
1328                ),
1329                hints: vec![
1330                    Hint::info(
1331                        source_engine,
1332                        constant_span.clone(),
1333                        format!(
1334                            // Shadowed constant "x" is declared here.
1335                            //  or
1336                            // Shadowed constant "x" gets imported here.
1337                            //  or
1338                            // ...
1339                            "Shadowed constant \"{name}\" {} here{}.",
1340                            if constant_decl_span.clone() != Span::dummy() { "gets imported" } else { "is declared" },
1341                            if *is_alias { " as alias" } else { "" }
1342                        )
1343                    ),
1344                    if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1345                        Hint::help(
1346                            source_engine,
1347                            name.span(),
1348                            format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1349                        )
1350                    } else {
1351                        Hint::none()
1352                    },
1353                    Hint::info( // Ignored if the `constant_decl_span` is `Span::dummy()`.
1354                        source_engine,
1355                        constant_decl_span.clone(),
1356                        format!("This is the original declaration of the imported constant \"{name}\".")
1357                    ),
1358                ],
1359                help: vec![
1360                    "Unlike variables, constants cannot be shadowed by other constants or variables.".to_string(),
1361                    match (shadowing_source, *constant_decl_span != Span::dummy()) {
1362                        (LetVar | PatternMatchingStructFieldVar, false) => format!("Consider renaming either the {} \"{name}\" or the constant \"{name}\".", 
1363                            format!("{shadowing_source}").to_lowercase(),
1364                        ),
1365                        (Const, false) => "Consider renaming one of the constants.".to_string(),
1366                        (shadowing_source, true) => format!(
1367                            "Consider renaming the {} \"{name}\" or using {} for the imported constant.",
1368                            format!("{shadowing_source}").to_lowercase(),
1369                            if *is_alias { "a different alias" } else { "an alias" }
1370                        ),
1371                    },
1372                    if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1373                        format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1374                    } else {
1375                        Diagnostic::help_none()
1376                    }
1377                ],
1378            },
1379            ConfigurablesCannotBeShadowed { shadowing_source, name, configurable_span } => Diagnostic {
1380                reason: Some(Reason::new(code(1), "Configurables cannot be shadowed".to_string())),
1381                issue: Issue::error(
1382                    source_engine,
1383                    name.span(),
1384                    format!("{shadowing_source} \"{name}\" shadows configurable of the same name.")
1385                ),
1386                hints: vec![
1387                    Hint::info(
1388                        source_engine,
1389                        configurable_span.clone(),
1390                        format!("Shadowed configurable \"{name}\" is declared here.")
1391                    ),
1392                    if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1393                        Hint::help(
1394                            source_engine,
1395                            name.span(),
1396                            format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1397                        )
1398                    } else {
1399                        Hint::none()
1400                    },
1401                ],
1402                help: vec![
1403                    "Unlike variables, configurables cannot be shadowed by constants or variables.".to_string(),
1404                    format!(
1405                        "Consider renaming either the {} \"{name}\" or the configurable \"{name}\".",
1406                        format!("{shadowing_source}").to_lowercase()
1407                    ),
1408                    if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1409                        format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1410                    } else {
1411                        Diagnostic::help_none()
1412                    }
1413                ],
1414            },
1415            ConfigurablesCannotBeMatchedAgainst { name, configurable_span } => Diagnostic {
1416                reason: Some(Reason::new(code(1), "Configurables cannot be matched against".to_string())),
1417                issue: Issue::error(
1418                    source_engine,
1419                    name.span(),
1420                    format!("\"{name}\" is a configurable and configurables cannot be matched against.")
1421                ),
1422                hints: {
1423                    let mut hints = vec![
1424                        Hint::info(
1425                            source_engine,
1426                            configurable_span.clone(),
1427                            format!("Configurable \"{name}\" is declared here.")
1428                        ),
1429                    ];
1430
1431                    hints.append(&mut Hint::multi_help(source_engine, &name.span(), vec![
1432                        format!("Are you trying to define a pattern variable named \"{name}\"?"),
1433                        format!("In that case, use some other name for the pattern variable,"),
1434                        format!("or consider renaming the configurable \"{name}\"."),
1435                    ]));
1436
1437                    hints
1438                },
1439                help: vec![
1440                    "Unlike constants, configurables cannot be matched against in pattern matching.".to_string(),
1441                    "That's not possible, because patterns to match against must be compile-time constants.".to_string(),
1442                    "Configurables are run-time constants. Their values are defined during the deployment.".to_string(),
1443                    Diagnostic::help_empty_line(),
1444                    "To test against a configurable, consider:".to_string(),
1445                    format!("{}- replacing the `match` expression with `if-else`s altogether.", Indent::Single),
1446                    format!("{}- matching against a variable and comparing that variable afterwards with the configurable.", Indent::Single),
1447                    format!("{}  E.g., instead of:", Indent::Single),
1448                    Diagnostic::help_empty_line(),
1449                    format!("{}  SomeStruct {{ x: A_CONFIGURABLE, y: 42 }} => {{", Indent::Double),
1450                    format!("{}      do_something();", Indent::Double),
1451                    format!("{}  }}", Indent::Double),
1452                    Diagnostic::help_empty_line(),
1453                    format!("{}  to have:", Indent::Single),
1454                    Diagnostic::help_empty_line(),
1455                    format!("{}  SomeStruct {{ x, y: 42 }} => {{", Indent::Double),
1456                    format!("{}      if x == A_CONFIGURABLE {{", Indent::Double),
1457                    format!("{}          do_something();", Indent::Double),
1458                    format!("{}      }}", Indent::Double),
1459                    format!("{}  }}", Indent::Double),
1460                ],
1461            },
1462            ConstantShadowsVariable { name , variable_span } => Diagnostic {
1463                reason: Some(Reason::new(code(1), "Constants cannot shadow variables".to_string())),
1464                issue: Issue::error(
1465                    source_engine,
1466                    name.span(),
1467                    format!("Constant \"{name}\" shadows variable of the same name.")
1468                ),
1469                hints: vec![
1470                    Hint::info(
1471                        source_engine,
1472                        variable_span.clone(),
1473                        format!("This is the shadowed variable \"{name}\".")
1474                    ),
1475                ],
1476                help: vec![
1477                    format!("Variables can shadow other variables, but constants cannot."),
1478                    format!("Consider renaming either the variable or the constant."),
1479                ],
1480            },
1481            ConstantDuplicatesConstantOrConfigurable { existing_constant_or_configurable, new_constant_or_configurable, name, existing_span } => Diagnostic {
1482                reason: Some(Reason::new(code(1), match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1483                    ("Constant", "Constant") => "Constant of the same name already exists".to_string(),
1484                    ("Constant", "Configurable") => "Constant of the same name as configurable already exists".to_string(),
1485                    ("Configurable", "Constant") => "Configurable of the same name as constant already exists".to_string(),
1486                    _ => unreachable!("We can have only the listed combinations. Configurable duplicating configurable is not a valid combination.")
1487                })),
1488                issue: Issue::error(
1489                    source_engine,
1490                    name.span(),
1491                    format!("{new_constant_or_configurable} \"{name}\" has the same name as an already declared {}.",
1492                        existing_constant_or_configurable.to_lowercase()
1493                    )
1494                ),
1495                hints: vec![
1496                    Hint::info(
1497                        source_engine,
1498                        existing_span.clone(),
1499                        format!("{existing_constant_or_configurable} \"{name}\" is {}declared here.",
1500                            // If a constant clashes with an already declared constant.
1501                            if existing_constant_or_configurable == new_constant_or_configurable {
1502                                "already "
1503                            } else {
1504                                ""
1505                            }
1506                        )
1507                    ),
1508                ],
1509                help: vec![
1510                    match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1511                        ("Constant", "Constant") => "Consider renaming one of the constants, or in case of imported constants, using an alias.".to_string(),
1512                        _ => "Consider renaming either the configurable or the constant, or in case of an imported constant, using an alias.".to_string(),
1513                    },
1514                ],
1515            },
1516            MultipleDefinitionsOfMatchArmVariable { match_value, match_type, first_definition, first_definition_is_struct_field, duplicate, duplicate_is_struct_field } => Diagnostic {
1517                reason: Some(Reason::new(code(1), "Match pattern variable is already defined".to_string())),
1518                issue: Issue::error(
1519                    source_engine,
1520                    duplicate.clone(),
1521                    format!("Variable \"{}\" is already defined in this match arm.", first_definition.as_str())
1522                ),
1523                hints: vec![
1524                    Hint::help(
1525                        source_engine,
1526                        if *duplicate_is_struct_field {
1527                            duplicate.clone()
1528                        }
1529                        else {
1530                            Span::dummy()
1531                        },
1532                        format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str())
1533                    ),
1534                    Hint::info(
1535                        source_engine,
1536                        first_definition.clone(),
1537                        format!(
1538                            "This {}is the first definition of the variable \"{}\".",
1539                            if *first_definition_is_struct_field {
1540                                format!("struct field \"{}\" ", first_definition.as_str())
1541                            }
1542                            else {
1543                                "".to_string()
1544                            },
1545                            first_definition.as_str(),
1546                        )
1547                    ),
1548                    Hint::help(
1549                        source_engine,
1550                        if *first_definition_is_struct_field && !*duplicate_is_struct_field {
1551                            first_definition.clone()
1552                        }
1553                        else {
1554                            Span::dummy()
1555                        },
1556                        format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str()),
1557                    ),
1558                    Hint::info(
1559                        source_engine,
1560                        match_value.clone(),
1561                        format!("The expression to match on is of type \"{match_type}\".")
1562                    ),
1563                ],
1564                help: vec![
1565                    format!("Variables used in match arm patterns must be unique within a pattern, except in alternatives."),
1566                    match (*first_definition_is_struct_field, *duplicate_is_struct_field) {
1567                        (true, true) => format!("Consider declaring a variable with different name for either of the fields. E.g., `{0}: var_{0}`.", first_definition.as_str()),
1568                        (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()),
1569                        (false, false) => "Consider renaming either of the variables.".to_string(),
1570                    },
1571                ],
1572            },
1573            MatchArmVariableMismatchedType { match_value, match_type, variable, first_definition, expected, received } => Diagnostic {
1574                reason: Some(Reason::new(code(1), "Match pattern variable has mismatched type".to_string())),
1575                issue: Issue::error(
1576                    source_engine,
1577                    variable.span(),
1578                    format!("Variable \"{variable}\" is expected to be of type \"{expected}\", but is \"{received}\".")
1579                ),
1580                hints: vec![
1581                    Hint::info(
1582                        source_engine,
1583                        first_definition.clone(),
1584                        format!("\"{variable}\" is first defined here with type \"{expected}\".")
1585                    ),
1586                    Hint::info(
1587                        source_engine,
1588                        match_value.clone(),
1589                        format!("The expression to match on is of type \"{match_type}\".")
1590                    ),
1591                ],
1592                help: vec![
1593                    format!("In the same match arm, a variable must have the same type in all alternatives."),
1594                ],
1595            },
1596            MatchArmVariableNotDefinedInAllAlternatives { match_value, match_type, variable, missing_in_alternatives} => Diagnostic {
1597                reason: Some(Reason::new(code(1), "Match pattern variable is not defined in all alternatives".to_string())),
1598                issue: Issue::error(
1599                    source_engine,
1600                    variable.span(),
1601                    format!("Variable \"{variable}\" is not defined in all alternatives.")
1602                ),
1603                hints: {
1604                    let mut hints = vec![
1605                        Hint::info(
1606                            source_engine,
1607                            match_value.clone(),
1608                            format!("The expression to match on is of type \"{match_type}\".")
1609                        ),
1610                    ];
1611
1612                    for (i, alternative) in missing_in_alternatives.iter().enumerate() {
1613                        hints.push(
1614                            Hint::info(
1615                                source_engine,
1616                                alternative.clone(),
1617                                format!("\"{variable}\" is {}missing in this alternative.", if i != 0 { "also " } else { "" }),
1618                            )
1619                        )
1620                    }
1621
1622                    hints
1623                },
1624                help: vec![
1625                    format!("Consider removing the variable \"{variable}\" altogether, or adding it to all alternatives."),
1626                ],
1627            },
1628            MatchStructPatternMissingFields { missing_fields, missing_fields_are_public, struct_name, struct_decl_span, total_number_of_fields, span } => Diagnostic {
1629                reason: Some(Reason::new(code(1), "Struct pattern has missing fields".to_string())),
1630                issue: Issue::error(
1631                    source_engine,
1632                    span.clone(),
1633                    format!("Struct pattern is missing the {}field{} {}.",
1634                        if *missing_fields_are_public { "public " } else { "" },
1635                        plural_s(missing_fields.len()),
1636                        sequence_to_str(missing_fields, Enclosing::DoubleQuote, 2)
1637                    )
1638                ),
1639                hints: vec![
1640                    Hint::help(
1641                        source_engine,
1642                        span.clone(),
1643                        "Struct pattern must either contain or ignore each struct field.".to_string()
1644                    ),
1645                    Hint::info(
1646                        source_engine,
1647                        struct_decl_span.clone(),
1648                        format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1649                            number_to_str(*total_number_of_fields),
1650                            plural_s(*total_number_of_fields),
1651                        )
1652                    ),
1653                ],
1654                help: vec![
1655                    // Consider ignoring the field "x_1" by using the `_` pattern: `x_1: _`.
1656                    //  or
1657                    // Consider ignoring individual fields by using the `_` pattern. E.g, `x_1: _`.
1658                    format!("Consider ignoring {} field{} {}by using the `_` pattern{} `{}: _`.",
1659                        singular_plural(missing_fields.len(), "the", "individual"),
1660                        plural_s(missing_fields.len()),
1661                        singular_plural(missing_fields.len(), &format!("\"{}\" ", missing_fields[0]), ""),
1662                        singular_plural(missing_fields.len(), ":", ". E.g.,"),
1663                        missing_fields[0]
1664                    ),
1665                    "Alternatively, consider ignoring all the missing fields by ending the struct pattern with `..`.".to_string(),
1666                ],
1667            },
1668            MatchStructPatternMustIgnorePrivateFields { private_fields, struct_name, struct_decl_span, all_fields_are_private, span } => Diagnostic {
1669                reason: Some(Reason::new(code(1), "Struct pattern must ignore inaccessible private fields".to_string())),
1670                issue: Issue::error(
1671                    source_engine,
1672                    span.clone(),
1673                    format!("Struct pattern must ignore inaccessible private field{} {}.",
1674                        plural_s(private_fields.len()),
1675                        sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1676                    )
1677                ),
1678                hints: vec![
1679                    Hint::help(
1680                        source_engine,
1681                        span.clone(),
1682                        format!("To ignore the private field{}, end the struct pattern with `..`.",
1683                            plural_s(private_fields.len()),
1684                        )
1685                    ),
1686                    Hint::info(
1687                        source_engine,
1688                        struct_decl_span.clone(),
1689                        format!("Struct \"{struct_name}\" is declared here, and has {}.",
1690                            if *all_fields_are_private {
1691                                "all private fields".to_string()
1692                            } else {
1693                                format!("private field{} {}",
1694                                    plural_s(private_fields.len()),
1695                                    sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1696                                )
1697                            }
1698                        )
1699                    ),
1700                ],
1701                help: vec![],
1702            },
1703            TraitNotImportedAtFunctionApplication { trait_name, function_name, function_call_site_span, trait_constraint_span, trait_candidates } => {
1704                // Make candidates order deterministic.
1705                let mut trait_candidates = trait_candidates.clone();
1706                trait_candidates.sort();
1707                let trait_candidates = &trait_candidates; // Remove mutability.
1708
1709                Diagnostic {
1710                    reason: Some(Reason::new(code(1), "Trait is not imported".to_string())),
1711                    issue: Issue::error(
1712                        source_engine,
1713                        function_call_site_span.clone(),
1714                        format!(
1715                            "Trait \"{trait_name}\" is not imported {}when calling \"{function_name}\".",
1716                            get_file_name(source_engine, function_call_site_span.source_id())
1717                                .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1718                        )
1719                    ),
1720                    hints: {
1721                        let mut hints = vec![
1722                            Hint::help(
1723                                source_engine,
1724                                function_call_site_span.clone(),
1725                                format!("This import is needed because \"{function_name}\" requires \"{trait_name}\" in one of its trait constraints.")
1726                            ),
1727                            Hint::info(
1728                                source_engine,
1729                                trait_constraint_span.clone(),
1730                                format!("In the definition of \"{function_name}\", \"{trait_name}\" is used in this trait constraint.")
1731                            ),
1732                        ];
1733
1734                        match trait_candidates.len() {
1735                            // If no candidates are found, that means that an alias was used in the trait constraint definition.
1736                            // The way how constraint checking works now, the trait will not be found when we try to check if
1737                            // the trait constraints are satisfied for type, and we will never end up in this case here.
1738                            // So we will simply ignore it.
1739                            0 => (),
1740                            // The most common case. Exactly one known trait with the given name.
1741                            1 => hints.push(Hint::help(
1742                                    source_engine,
1743                                    function_call_site_span.clone(),
1744                                    format!(
1745                                        "Import the \"{trait_name}\" trait {}by using: `use {};`.",
1746                                        get_file_name(source_engine, function_call_site_span.source_id())
1747                                            .map_or("".to_string(), |file_name| format!("into \"{file_name}\" ")),
1748                                        trait_candidates[0]
1749                                    )
1750                                )),
1751                            // Unlikely (for now) case of having several traits with the same name.
1752                            _ => hints.push(Hint::help(
1753                                    source_engine,
1754                                    function_call_site_span.clone(),
1755                                    format!(
1756                                        "To import the proper \"{trait_name}\" {}follow the detailed instructions given below.",
1757                                        get_file_name(source_engine, function_call_site_span.source_id())
1758                                            .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1759                                    )
1760                                )),
1761                        }
1762
1763                        hints
1764                    },
1765                    help: {
1766                        let mut help = vec![];
1767
1768                        if trait_candidates.len() > 1 {
1769                            help.push(format!("There are these {} traits with the name \"{trait_name}\" available in the modules:", number_to_str(trait_candidates.len())));
1770                            for trait_candidate in trait_candidates.iter() {
1771                                help.push(format!("{}- {trait_candidate}", Indent::Single));
1772                            }
1773                            help.push("To import the proper one follow these steps:".to_string());
1774                            help.push(format!(
1775                                "{}1. Look at the definition of the \"{function_name}\"{}.",
1776                                    Indent::Single,
1777                                    get_file_name(source_engine, trait_constraint_span.source_id())
1778                                        .map_or("".to_string(), |file_name| format!(" in the \"{file_name}\""))
1779                            ));
1780                            help.push(format!(
1781                                "{}2. Detect which exact \"{trait_name}\" is used in the trait constraint in the \"{function_name}\".",
1782                                Indent::Single
1783                            ));
1784                            help.push(format!(
1785                                "{}3. Import that \"{trait_name}\"{}.",
1786                                Indent::Single,
1787                                get_file_name(source_engine, function_call_site_span.source_id())
1788                                    .map_or("".to_string(), |file_name| format!(" into \"{file_name}\""))
1789                            ));
1790                            help.push(format!("{} E.g., assuming it is the first one on the list, use: `use {};`", Indent::Double, trait_candidates[0]));
1791                        }
1792
1793                        help
1794                    },
1795                }
1796            },
1797            // TODO-IG: Extend error messages to pointers, once typed pointers are defined and can be dereferenced.
1798            ExpressionCannotBeDereferenced { expression_type, span } => Diagnostic {
1799                reason: Some(Reason::new(code(1), "Expression cannot be dereferenced".to_string())),
1800                issue: Issue::error(
1801                    source_engine,
1802                    span.clone(),
1803                    format!("This expression cannot be dereferenced, because it is of type \"{expression_type}\", which is not a reference type.")
1804                ),
1805                hints: vec![
1806                    Hint::help(
1807                        source_engine,
1808                        span.clone(),
1809                        "In Sway, only references can be dereferenced.".to_string()
1810                    ),
1811                    Hint::help(
1812                        source_engine,
1813                        span.clone(),
1814                        "Are you missing the reference operator `&` somewhere in the code?".to_string()
1815                    ),
1816                ],
1817                help: vec![],
1818            },
1819            StructInstantiationMissingFields { field_names, struct_name, span, struct_decl_span, total_number_of_fields } => Diagnostic {
1820                reason: Some(Reason::new(code(1), "Struct instantiation has missing fields".to_string())),
1821                issue: Issue::error(
1822                    source_engine,
1823                    span.clone(),
1824                    format!("Instantiation of the struct \"{struct_name}\" is missing the field{} {}.",
1825                            plural_s(field_names.len()),
1826                            sequence_to_str(field_names, Enclosing::DoubleQuote, 2)
1827                        )
1828                ),
1829                hints: vec![
1830                    Hint::help(
1831                        source_engine,
1832                        span.clone(),
1833                        "Struct instantiation must initialize all the fields of the struct.".to_string()
1834                    ),
1835                    Hint::info(
1836                        source_engine,
1837                        struct_decl_span.clone(),
1838                        format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1839                            number_to_str(*total_number_of_fields),
1840                            plural_s(*total_number_of_fields),
1841                        )
1842                    ),
1843                ],
1844                help: vec![],
1845            },
1846            StructCannotBeInstantiated { struct_name, span, struct_decl_span, private_fields, constructors, all_fields_are_private, is_in_storage_declaration, struct_can_be_changed } => Diagnostic {
1847                reason: Some(Reason::new(code(1), "Struct cannot be instantiated due to inaccessible private fields".to_string())),
1848                issue: Issue::error(
1849                    source_engine,
1850                    span.clone(),
1851                    format!("\"{struct_name}\" cannot be {}instantiated in this {}, due to {}inaccessible private field{}.",
1852                        if *is_in_storage_declaration { "" } else { "directly " },
1853                        if *is_in_storage_declaration { "storage declaration" } else { "module" },
1854                        singular_plural(private_fields.len(), "an ", ""),
1855                        plural_s(private_fields.len())
1856                    )
1857                ),
1858                hints: vec![
1859                    Hint::help(
1860                        source_engine,
1861                        span.clone(),
1862                        format!("Inaccessible field{} {} {}.",
1863                            plural_s(private_fields.len()),
1864                            is_are(private_fields.len()),
1865                            sequence_to_str(private_fields, Enclosing::DoubleQuote, 5)
1866                        )
1867                    ),
1868                    Hint::help(
1869                        source_engine,
1870                        span.clone(),
1871                        if *is_in_storage_declaration {
1872                            "Structs with private fields can be instantiated in storage declarations only if they are declared in the same module as the storage.".to_string()
1873                        } else {
1874                            "Structs with private fields can be instantiated only within the module in which they are declared.".to_string()
1875                        }
1876                    ),
1877                    if *is_in_storage_declaration {
1878                        Hint::help(
1879                            source_engine,
1880                            span.clone(),
1881                            "They can still be initialized in storage declarations if they have public constructors that evaluate to a constant.".to_string()
1882                        )
1883                    } else {
1884                        Hint::none()
1885                    },
1886                    if *is_in_storage_declaration {
1887                        Hint::help(
1888                            source_engine,
1889                            span.clone(),
1890                            "They can always be stored in storage by using the `read` and `write` functions provided in the `std::storage::storage_api`.".to_string()
1891                        )
1892                    } else {
1893                        Hint::none()
1894                    },
1895                    if !*is_in_storage_declaration && !constructors.is_empty() {
1896                        Hint::help(
1897                            source_engine,
1898                            span.clone(),
1899                            format!("\"{struct_name}\" can be instantiated via public constructors suggested below.")
1900                        )
1901                    } else {
1902                        Hint::none()
1903                    },
1904                    Hint::info(
1905                        source_engine,
1906                        struct_decl_span.clone(),
1907                        format!("Struct \"{struct_name}\" is declared here, and has {}.",
1908                            if *all_fields_are_private {
1909                                "all private fields".to_string()
1910                            } else {
1911                                format!("private field{} {}",
1912                                    plural_s(private_fields.len()),
1913                                    sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1914                                )
1915                            }
1916                        )
1917                    ),
1918                ],
1919                help: {
1920                    let mut help = vec![];
1921
1922                    if *is_in_storage_declaration {
1923                        help.push(format!("Consider initializing \"{struct_name}\" by finding an available constructor that evaluates to a constant{}.",
1924                            if *struct_can_be_changed {
1925                                ", or implement a new one"
1926                            } else {
1927                                ""
1928                            }
1929                        ));
1930
1931                        if !constructors.is_empty() {
1932                            help.push("Check these already available constructors. They might evaluate to a constant:".to_string());
1933                            // We always expect a very few candidates here. So let's list all of them by using `usize::MAX`.
1934                            for constructor in sequence_to_list(constructors, Indent::Single, usize::MAX) {
1935                                help.push(constructor);
1936                            }
1937                        };
1938
1939                        help.push(Diagnostic::help_empty_line());
1940
1941                        help.push(format!("Or you can always store instances of \"{struct_name}\" in the contract storage, by using the `std::storage::storage_api`:"));
1942                        help.push(format!("{}use std::storage::storage_api::{{read, write}};", Indent::Single));
1943                        help.push(format!("{}write(STORAGE_KEY, 0, my_{});", Indent::Single, to_snake_case(struct_name.as_str())));
1944                        help.push(format!("{}let my_{}_option = read::<{struct_name}>(STORAGE_KEY, 0);", Indent::Single, to_snake_case(struct_name.as_str())));
1945                    }
1946                    else if !constructors.is_empty() {
1947                        help.push(format!("Consider instantiating \"{struct_name}\" by using one of the available constructors{}:",
1948                            if *struct_can_be_changed {
1949                                ", or implement a new one"
1950                            } else {
1951                                ""
1952                            }
1953                        ));
1954                        for constructor in sequence_to_list(constructors, Indent::Single, 5) {
1955                            help.push(constructor);
1956                        }
1957                    }
1958
1959                    if *struct_can_be_changed {
1960                        if *is_in_storage_declaration || !constructors.is_empty() {
1961                            help.push(Diagnostic::help_empty_line());
1962                        }
1963
1964                        if !*is_in_storage_declaration && constructors.is_empty() {
1965                            help.push(format!("Consider implementing a public constructor for \"{struct_name}\"."));
1966                        };
1967
1968                        help.push(
1969                            // Alternatively, consider declaring the field "f" as public in "Struct": `pub f: ...,`.
1970                            //  or
1971                            // Alternatively, consider declaring the fields "f" and "g" as public in "Struct": `pub <field>: ...,`.
1972                            //  or
1973                            // Alternatively, consider declaring all fields as public in "Struct": `pub <field>: ...,`.
1974                            format!("Alternatively, consider declaring {} as public in \"{struct_name}\": `pub {}: ...,`.",
1975                                if *all_fields_are_private {
1976                                    "all fields".to_string()
1977                                } else {
1978                                    format!("{} {}",
1979                                        singular_plural(private_fields.len(), "the field", "the fields"),
1980                                        sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1981                                    )
1982                                },
1983                                if *all_fields_are_private {
1984                                    "<field>".to_string()
1985                                } else {
1986                                    match &private_fields[..] {
1987                                        [field] => format!("{field}"),
1988                                        _ => "<field>".to_string(),
1989                                    }
1990                                },
1991                            )
1992                        )
1993                    };
1994
1995                    help
1996                }
1997            },
1998            StructFieldIsPrivate { field_name, struct_name, field_decl_span, struct_can_be_changed, usage_context } => Diagnostic {
1999                reason: Some(Reason::new(code(1), "Private struct field is inaccessible".to_string())),
2000                issue: Issue::error(
2001                    source_engine,
2002                    field_name.span(),
2003                    format!("Private field \"{field_name}\" {}is inaccessible in this module.",
2004                        match usage_context {
2005                            StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => "".to_string(),
2006                            StorageAccess | StructFieldAccess => format!("of the struct \"{struct_name}\" "),
2007                        }
2008                    )
2009                ),
2010                hints: vec![
2011                    Hint::help(
2012                        source_engine,
2013                        field_name.span(),
2014                        format!("Private fields can only be {} within the module in which their struct is declared.",
2015                            match usage_context {
2016                                StructInstantiation { .. } | StorageDeclaration { .. } => "initialized",
2017                                StorageAccess | StructFieldAccess => "accessed",
2018                                PatternMatching { .. } => "matched",
2019                            }
2020                        )
2021                    ),
2022                    if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2023                        Hint::help(
2024                            source_engine,
2025                            field_name.span(),
2026                            "Otherwise, they must be ignored by ending the struct pattern with `..`.".to_string()
2027                        )
2028                    } else {
2029                        Hint::none()
2030                    },
2031                    Hint::info(
2032                        source_engine,
2033                        field_decl_span.clone(),
2034                        format!("Field \"{field_name}\" {}is declared here as private.",
2035                            match usage_context {
2036                                StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => format!("of the struct \"{struct_name}\" "),
2037                                StorageAccess | StructFieldAccess => "".to_string(),
2038                            }
2039                        )
2040                    ),
2041                ],
2042                help: vec![
2043                    if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2044                        format!("Consider removing the field \"{field_name}\" from the struct pattern, and ending the pattern with `..`.")
2045                    } else {
2046                        Diagnostic::help_none()
2047                    },
2048                    if *struct_can_be_changed {
2049                        match usage_context {
2050                            StorageAccess | StructFieldAccess | PatternMatching { .. } => {
2051                                format!("{} declaring the field \"{field_name}\" as public in \"{struct_name}\": `pub {field_name}: ...,`.",
2052                                    if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2053                                        "Alternatively, consider"
2054                                    } else {
2055                                        "Consider"
2056                                    }
2057                                )
2058                            },
2059                            // For all other usages, detailed instructions are already given in specific messages.
2060                            _ => Diagnostic::help_none(),
2061                        }
2062                    } else {
2063                        Diagnostic::help_none()
2064                    },
2065                ],
2066            },
2067            StructFieldDoesNotExist { field_name, available_fields, is_public_struct_access, struct_name, struct_decl_span, struct_is_empty, usage_context } => Diagnostic {
2068                reason: Some(Reason::new(code(1), "Struct field does not exist".to_string())),
2069                issue: Issue::error(
2070                    source_engine,
2071                    field_name.span(),
2072                    format!("Field \"{field_name}\" does not exist in the struct \"{struct_name}\".")
2073                ),
2074                hints: {
2075                    let public = if *is_public_struct_access { "public " } else { "" };
2076
2077                    let (hint, show_struct_decl) = if *struct_is_empty {
2078                        (Some(format!("\"{struct_name}\" is an empty struct. It doesn't have any fields.")), false)
2079                    }
2080                    // If the struct anyhow cannot be instantiated (in the struct instantiation or storage declaration),
2081                    // we don't show any additional hints.
2082                    // Showing any available fields would be inconsistent and misleading, because they anyhow cannot be used.
2083                    // Besides, "Struct cannot be instantiated" error will provide all the explanations and suggestions.
2084                    else if (matches!(usage_context, StorageAccess) && *is_public_struct_access && available_fields.is_empty())
2085                            ||
2086                            (matches!(usage_context, StructInstantiation { struct_can_be_instantiated: false } | StorageDeclaration { struct_can_be_instantiated: false })) {
2087                        // If the struct anyhow cannot be instantiated in the storage, don't show any additional hint
2088                        // if there is an attempt to access a non existing field of such non-instantiable struct.
2089                        //   or
2090                        // Likewise, if we are in the struct instantiation or storage declaration and the struct
2091                        // cannot be instantiated.
2092                        (None, false)
2093                    } else if !available_fields.is_empty() {
2094                        // In all other cases, show the available fields.
2095                        const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2096                        match &available_fields[..] {
2097                            [field] => (Some(format!("Only available {public}field is \"{field}\".")), false),
2098                            _ => (Some(format!("Available {public}fields are {}.", sequence_to_str(available_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY))),
2099                                    available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2100                                ),
2101                        }
2102                    }
2103                    else {
2104                        (None, false)
2105                    };
2106
2107                    let mut hints = vec![];
2108
2109                    if let Some(hint) = hint {
2110                        hints.push(Hint::help(source_engine, field_name.span(), hint));
2111                    };
2112
2113                    if show_struct_decl {
2114                        hints.push(Hint::info(
2115                            source_engine,
2116                            struct_decl_span.clone(),
2117                            format!("Struct \"{struct_name}\" is declared here, and has {} {public}fields.",
2118                                number_to_str(available_fields.len())
2119                            )
2120                        ));
2121                    }
2122
2123                    hints
2124                },
2125                help: vec![],
2126            },
2127            StructFieldDuplicated { field_name, duplicate } => Diagnostic {
2128                reason: Some(Reason::new(code(1), "Struct field has multiple definitions".to_string())),
2129                issue: Issue::error(
2130                    source_engine,
2131                    field_name.span(),
2132                    format!("Field \"{field_name}\" has multiple definitions.")
2133                ),
2134                hints: {
2135                    vec![
2136                        Hint::info(
2137                            source_engine,
2138                            duplicate.span(),
2139                            "Field definition duplicated here.".into(),
2140                        )
2141                   ]
2142                },
2143                help: vec![],
2144            },
2145            NotIndexable { actually, span } => Diagnostic {
2146                reason: Some(Reason::new(code(1), "Type is not indexable".to_string())),
2147                issue: Issue::error(
2148                    source_engine,
2149                    span.clone(),
2150                    format!("This expression has type \"{actually}\", which is not an indexable type.")
2151                ),
2152                hints: vec![],
2153                help: vec![
2154                    "Index operator `[]` can be used only on indexable types.".to_string(),
2155                    "In Sway, indexable types are:".to_string(),
2156                    format!("{}- arrays. E.g., `[u64;3]`.", Indent::Single),
2157                    format!("{}- references, direct or indirect, to arrays. E.g., `&[u64;3]` or `&&&[u64;3]`.", Indent::Single),
2158                ],
2159            },
2160            FieldAccessOnNonStruct { actually, storage_variable, field_name, span } => Diagnostic {
2161                reason: Some(Reason::new(code(1), "Field access requires a struct".to_string())),
2162                issue: Issue::error(
2163                    source_engine,
2164                    span.clone(),
2165                    format!("{} has type \"{actually}\", which is not a struct{}.",
2166                        if let Some(storage_variable) = storage_variable {
2167                            format!("Storage variable \"{storage_variable}\"")
2168                        } else {
2169                            "This expression".to_string()
2170                        },
2171                        if storage_variable.is_some() {
2172                            ""
2173                        } else {
2174                            " or a reference to a struct"
2175                        }
2176                    )
2177                ),
2178                hints: vec![
2179                    Hint::info(
2180                        source_engine,
2181                        field_name.span(),
2182                        format!("Field access happens here, on \"{field_name}\".")
2183                    )
2184                ],
2185                help: if storage_variable.is_some() {
2186                    vec![
2187                        "Fields can only be accessed on storage variables that are structs.".to_string(),
2188                    ]
2189                } else {
2190                    vec![
2191                        "In Sway, fields can be accessed on:".to_string(),
2192                        format!("{}- structs. E.g., `my_struct.field`.", Indent::Single),
2193                        format!("{}- references, direct or indirect, to structs. E.g., `(&my_struct).field` or `(&&&my_struct).field`.", Indent::Single),
2194                    ]
2195                }
2196            },
2197            SymbolWithMultipleBindings { name, paths, span } => Diagnostic {
2198                reason: Some(Reason::new(code(1), "Multiple bindings exist for symbol in the scope".to_string())),
2199                issue: Issue::error(
2200                    source_engine,
2201                    span.clone(),
2202                    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)),
2203                ),
2204                hints: vec![],
2205                help: vec![format!("Consider using a fully qualified name, e.g., `{}::{}`.", paths[0], name)],
2206            },
2207            StorageFieldDoesNotExist { field_name, available_fields, storage_decl_span } => Diagnostic {
2208                reason: Some(Reason::new(code(1), "Storage field does not exist".to_string())),
2209                issue: Issue::error(
2210                    source_engine,
2211                    field_name.span(),
2212                    format!("Storage field \"{field_name}\" does not exist in the storage.")
2213                ),
2214                hints: {
2215                    let (hint, show_storage_decl) = if available_fields.is_empty() {
2216                        ("The storage is empty. It doesn't have any fields.".to_string(), false)
2217                    } else {
2218                        const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2219                        let display_fields = available_fields.iter().map(|(path, field_name)| {
2220                            let path = path.iter().map(ToString::to_string).collect::<Vec<_>>().join("::");
2221                            if path.is_empty() {
2222                                format!("storage.{field_name}")
2223                            } else {
2224                                format!("storage::{path}.{field_name}")
2225                            }
2226                        }).collect::<Vec<_>>();
2227                        match &display_fields[..] {
2228                            [field] => (format!("Only available storage field is \"{field}\"."), false),
2229                            _ => (format!("Available storage fields are {}.", sequence_to_str(&display_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY)),
2230                                    available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2231                                ),
2232                        }
2233                    };
2234
2235                    let mut hints = vec![];
2236
2237                    hints.push(Hint::help(source_engine, field_name.span(), hint));
2238
2239                    if show_storage_decl {
2240                        hints.push(Hint::info(
2241                            source_engine,
2242                            storage_decl_span.clone(),
2243                            format!("Storage is declared here, and has {} fields.",
2244                                number_to_str(available_fields.len())
2245                            )
2246                        ));
2247                    }
2248
2249                    hints
2250                },
2251                help: vec![],
2252            },
2253            TupleIndexOutOfBounds { index, count, tuple_type, span, prefix_span } => Diagnostic {
2254                reason: Some(Reason::new(code(1), "Tuple index is out of bounds".to_string())),
2255                issue: Issue::error(
2256                    source_engine,
2257                    span.clone(),
2258                    format!("Tuple index {index} is out of bounds. The tuple has only {count} element{}.", plural_s(*count))
2259                ),
2260                hints: vec![
2261                    Hint::info(
2262                        source_engine,
2263                        prefix_span.clone(),
2264                        format!("This expression has type \"{tuple_type}\".")
2265                    ),
2266                ],
2267                help: vec![],
2268            },
2269            TupleElementAccessOnNonTuple { actually, span, index, index_span } => Diagnostic {
2270                reason: Some(Reason::new(code(1), "Tuple element access requires a tuple".to_string())),
2271                issue: Issue::error(
2272                    source_engine,
2273                    span.clone(),
2274                    format!("This expression has type \"{actually}\", which is not a tuple or a reference to a tuple.")
2275                ),
2276                hints: vec![
2277                    Hint::info(
2278                        source_engine,
2279                        index_span.clone(),
2280                        format!("Tuple element access happens here, on the index {index}.")
2281                    )
2282                ],
2283                help: vec![
2284                    "In Sway, tuple elements can be accessed on:".to_string(),
2285                    format!("{}- tuples. E.g., `my_tuple.1`.", Indent::Single),
2286                    format!("{}- references, direct or indirect, to tuples. E.g., `(&my_tuple).1` or `(&&&my_tuple).1`.", Indent::Single),
2287                ],
2288            },
2289            RefMutCannotReferenceConstant { constant, span } => Diagnostic {
2290                reason: Some(Reason::new(code(1), "References to mutable values cannot reference constants".to_string())),
2291                issue: Issue::error(
2292                    source_engine,
2293                    span.clone(),
2294                    format!("\"{constant}\" is a constant. `&mut` cannot reference constants.")
2295                ),
2296                hints: vec![],
2297                help: vec![
2298                    "Consider:".to_string(),
2299                    format!("{}- taking a reference without `mut`: `&{constant}`.", Indent::Single),
2300                    format!("{}- referencing a mutable copy of the constant, by returning it from a block: `&mut {{ {constant} }}`.", Indent::Single)
2301                ],
2302            },
2303            RefMutCannotReferenceImmutableVariable { decl_name, span } => Diagnostic {
2304                reason: Some(Reason::new(code(1), "References to mutable values cannot reference immutable variables".to_string())),
2305                issue: Issue::error(
2306                    source_engine,
2307                    span.clone(),
2308                    format!("\"{decl_name}\" is an immutable variable. `&mut` cannot reference immutable variables.")
2309                ),
2310                hints: vec![
2311                    Hint::info(
2312                        source_engine,
2313                        decl_name.span(),
2314                        format!("Variable \"{decl_name}\" is declared here as immutable.")
2315                    ),
2316                ],
2317                help: vec![
2318                    "Consider:".to_string(),
2319                    // TODO-IG: Once desugaring information becomes available, do not show the first suggestion if declaring variable as mutable is not possible.
2320                    format!("{}- declaring \"{decl_name}\" as mutable.", Indent::Single),
2321                    format!("{}- taking a reference without `mut`: `&{decl_name}`.", Indent::Single),
2322                    format!("{}- referencing a mutable copy of \"{decl_name}\", by returning it from a block: `&mut {{ {decl_name} }}`.", Indent::Single)
2323                ],
2324            },
2325            ConflictingImplsForTraitAndType { trait_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => Diagnostic {
2326                reason: Some(Reason::new(code(1), "Trait is already implemented for type".to_string())),
2327                issue: Issue::error(
2328                    source_engine,
2329                    second_impl_span.clone(),
2330                    if type_implementing_for == type_implementing_for_unaliased {
2331                        format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\".")
2332                    } else {
2333                        format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").")
2334                    }
2335                ),
2336                hints: vec![
2337                    Hint::info(
2338                        source_engine,
2339                        existing_impl_span.clone(),
2340                        if type_implementing_for == type_implementing_for_unaliased {
2341                            format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\".",
2342                                    call_path_suffix_with_args(trait_name)
2343                            )
2344                        } else {
2345                            format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").",
2346                                    call_path_suffix_with_args(trait_name)
2347                            )
2348                        }
2349                    ),
2350                ],
2351                help: vec![
2352                    "In Sway, there can be at most one implementation of a trait for any given type.".to_string(),
2353                    "This property is called \"trait coherence\".".to_string(),
2354                ],
2355            },
2356            DuplicateDeclDefinedForType { decl_kind, decl_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => {
2357                let decl_kind_snake_case = sway_types::style::to_upper_camel_case(decl_kind);
2358                Diagnostic {
2359                    reason: Some(Reason::new(code(1), "Type contains duplicate declarations".to_string())),
2360                    issue: Issue::error(
2361                        source_engine,
2362                        second_impl_span.clone(),
2363                        if type_implementing_for == type_implementing_for_unaliased {
2364                            format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\".")
2365                        } else {
2366                            format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").")
2367                        }
2368                    ),
2369                    hints: vec![
2370                        Hint::info(
2371                            source_engine,
2372                            existing_impl_span.clone(),
2373                            format!("\"{decl_name}\" previously defined here.")
2374                        )
2375                    ],
2376                    help: vec![
2377                        "A type may not contain two or more declarations of the same name".to_string(),
2378                    ],
2379                }
2380            },
2381            MarkerTraitExplicitlyImplemented { marker_trait_full_name, span} => Diagnostic {
2382                reason: Some(Reason::new(code(1), "Marker traits cannot be explicitly implemented".to_string())),
2383                issue: Issue::error(
2384                    source_engine,
2385                    span.clone(),
2386                    format!("Trait \"{marker_trait_full_name}\" is a marker trait and cannot be explicitly implemented.")
2387                ),
2388                hints: vec![],
2389                help: match marker_trait_name(marker_trait_full_name) {
2390                    "Error" => vec![
2391                        "\"Error\" marker trait is automatically implemented by the compiler for string slices".to_string(),
2392                        "and enums annotated with the `#[error_type]` attribute.".to_string(),
2393                    ],
2394                    "Enum" => vec![
2395                        "\"Enum\" marker trait is automatically implemented by the compiler for all enum types.".to_string(),
2396                    ],
2397                    _ => vec![],
2398                }
2399            },
2400            AssignmentToNonMutableVariable { lhs_span, decl_name } => Diagnostic {
2401                reason: Some(Reason::new(code(1), "Immutable variables cannot be assigned to".to_string())),
2402                issue: Issue::error(
2403                    source_engine,
2404                    lhs_span.clone(),
2405                    // "x" cannot be assigned to, because it is an immutable variable.
2406                    //  or
2407                    // This expression cannot be assigned to, because "x" is an immutable variable.
2408                    format!("{} cannot be assigned to, because {} is an immutable variable.",
2409                        if decl_name.as_str() == lhs_span.as_str() { // We have just a single variable in the expression.
2410                            format!("\"{decl_name}\"")
2411                        } else {
2412                            "This expression".to_string()
2413                        },
2414                        if decl_name.as_str() == lhs_span.as_str() {
2415                            "it".to_string()
2416                        } else {
2417                            format!("\"{decl_name}\"")
2418                        }
2419                    )
2420                ),
2421                hints: vec![
2422                    Hint::info(
2423                        source_engine,
2424                        decl_name.span(),
2425                        format!("Variable \"{decl_name}\" is declared here as immutable.")
2426                    ),
2427                ],
2428                help: vec![
2429                    // TODO-IG: Once desugaring information becomes available, do not show this suggestion if declaring variable as mutable is not possible.
2430                    format!("Consider declaring \"{decl_name}\" as mutable."),
2431                ],
2432            },
2433            AssignmentToConstantOrConfigurable { lhs_span, is_configurable, decl_name } => Diagnostic {
2434                reason: Some(Reason::new(code(1), format!("{} cannot be assigned to",
2435                    if *is_configurable {
2436                        "Configurables"
2437                    } else {
2438                        "Constants"
2439                    }
2440                ))),
2441                issue: Issue::error(
2442                    source_engine,
2443                    lhs_span.clone(),
2444                    // "x" cannot be assigned to, because it is a constant/configurable.
2445                    //  or
2446                    // This expression cannot be assigned to, because "x" is a constant/configurable.
2447                    format!("{} cannot be assigned to, because {} is a {}.",
2448                        if decl_name.as_str() == lhs_span.as_str() { // We have just the constant in the expression.
2449                            format!("\"{decl_name}\"")
2450                        } else {
2451                            "This expression".to_string()
2452                        },
2453                        if decl_name.as_str() == lhs_span.as_str() {
2454                            "it".to_string()
2455                        } else {
2456                            format!("\"{decl_name}\"")
2457                        },
2458                        if *is_configurable {
2459                            "configurable"
2460                        } else {
2461                            "constant"
2462                        }
2463                    )
2464                ),
2465                hints: vec![
2466                    Hint::info(
2467                        source_engine,
2468                        decl_name.span(),
2469                        format!("{} \"{decl_name}\" is declared here.",
2470                            if *is_configurable {
2471                                "Configurable"
2472                            } else {
2473                                "Constant"
2474                            }
2475                        )
2476                    ),
2477                ],
2478                help: vec![],
2479            },
2480            DeclAssignmentTargetCannotBeAssignedTo { decl_name, decl_friendly_type_name, lhs_span } => Diagnostic {
2481                reason: Some(Reason::new(code(1), "Assignment target cannot be assigned to".to_string())),
2482                issue: Issue::error(
2483                    source_engine,
2484                    lhs_span.clone(),
2485                    // "x" cannot be assigned to, because it is a trait/function/ etc and not a mutable variable.
2486                    //  or
2487                    // This cannot be assigned to, because "x" is a trait/function/ etc and not a mutable variable.
2488                    format!("{} cannot be assigned to, because {} is {}{decl_friendly_type_name} and not a mutable variable.",
2489                        match decl_name {
2490                            Some(decl_name) if decl_name.as_str() == lhs_span.as_str() => // We have just the decl name in the expression.
2491                                format!("\"{decl_name}\""),
2492                            _ => "This".to_string(),
2493                        },
2494                        match decl_name {
2495                            Some(decl_name) if decl_name.as_str() == lhs_span.as_str() =>
2496                                "it".to_string(),
2497                            Some(decl_name) => format!("\"{}\"", decl_name.as_str()),
2498                            _ => "it".to_string(),
2499                        },
2500                        a_or_an(decl_friendly_type_name)
2501                    )
2502                ),
2503                hints: vec![
2504                    match decl_name {
2505                        Some(decl_name) => Hint::info(
2506                            source_engine,
2507                            decl_name.span(),
2508                            format!("{} \"{decl_name}\" is declared here.", ascii_sentence_case(&decl_friendly_type_name.to_string()))
2509                        ),
2510                        _ => Hint::none(),
2511                    }
2512                ],
2513                help: vec![],
2514            },
2515            AssignmentViaNonMutableReference { decl_reference_name, decl_reference_rhs, decl_reference_type, span } => Diagnostic {
2516                reason: Some(Reason::new(code(1), "Reference is not a reference to a mutable value (`&mut`)".to_string())),
2517                issue: Issue::error(
2518                    source_engine,
2519                    span.clone(),
2520                    // This reference expression is not a reference to a mutable value (`&mut`).
2521                    //  or
2522                    // Reference "ref_xyz" is not a reference to a mutable value (`&mut`).
2523                    format!("{} is not a reference to a mutable value (`&mut`).",
2524                        match decl_reference_name {
2525                            Some(decl_reference_name) => format!("Reference \"{decl_reference_name}\""),
2526                            _ => "This reference expression".to_string(),
2527                        }
2528                    )
2529                ),
2530                hints: vec![
2531                    match decl_reference_name {
2532                        Some(decl_reference_name) => Hint::info(
2533                            source_engine,
2534                            decl_reference_name.span(),
2535                            format!("Reference \"{decl_reference_name}\" is declared here as a reference to immutable value.")
2536                        ),
2537                        _ => Hint::none(),
2538                    },
2539                    match decl_reference_rhs {
2540                        Some(decl_reference_rhs) => Hint::info(
2541                            source_engine,
2542                            decl_reference_rhs.clone(),
2543                            format!("This expression has type \"{decl_reference_type}\" instead of \"&mut {}\".",
2544                                &decl_reference_type[1..]
2545                            )
2546                        ),
2547                        _ => Hint::info(
2548                            source_engine,
2549                            span.clone(),
2550                            format!("It has type \"{decl_reference_type}\" instead of \"&mut {}\".",
2551                                &decl_reference_type[1..]
2552                            )
2553                        ),
2554                    },
2555                    match decl_reference_rhs {
2556                        Some(decl_reference_rhs) if decl_reference_rhs.as_str().starts_with('&') => Hint::help(
2557                            source_engine,
2558                            decl_reference_rhs.clone(),
2559                            format!("Consider taking here a reference to a mutable value: `&mut {}`.",
2560                                first_line(decl_reference_rhs.as_str()[1..].trim(), true)
2561                            )
2562                        ),
2563                        _ => Hint::none(),
2564                    },
2565                ],
2566                help: vec![
2567                    format!("{} dereferenced in assignment targets must {} references to mutable values (`&mut`).",
2568                        if decl_reference_name.is_some() {
2569                            "References"
2570                        } else {
2571                            "Reference expressions"
2572                        },
2573                        if decl_reference_name.is_some() {
2574                            "be"
2575                        } else {
2576                            "result in"
2577                        }
2578                    ),
2579                ],
2580            },
2581            Unimplemented { feature, help, span } => Diagnostic {
2582                reason: Some(Reason::new(code(1), "Used feature is currently not implemented".to_string())),
2583                issue: Issue::error(
2584                    source_engine,
2585                    span.clone(),
2586                    format!("{feature} is currently not implemented.")
2587                ),
2588                hints: vec![],
2589                help: help.clone(),
2590            },
2591            MatchedValueIsNotValid { supported_types_message, span } => Diagnostic {
2592                reason: Some(Reason::new(code(1), "Matched value is not valid".to_string())),
2593                issue: Issue::error(
2594                    source_engine,
2595                    span.clone(),
2596                    "This cannot be matched.".to_string()
2597                ),
2598                hints: vec![],
2599                help: {
2600                    let mut help = vec![];
2601
2602                    help.push("Matched value must be an expression whose result is of one of the types supported in pattern matching.".to_string());
2603                    help.push(Diagnostic::help_empty_line());
2604                    for msg in supported_types_message {
2605                        help.push(msg.to_string());
2606                    }
2607
2608                    help
2609                }
2610            },
2611            TypeIsNotValidAsImplementingFor { invalid_type, trait_name, span } => Diagnostic {
2612                reason: Some(Reason::new(code(1), "Self type of an impl block is not valid".to_string())),
2613                issue: Issue::error(
2614                    source_engine,
2615                    span.clone(),
2616                    format!("{invalid_type} is not a valid type in the self type of {} impl block.",
2617                        match trait_name {
2618                            Some(_) => "a trait",
2619                            None => "an",
2620                        }
2621                    )
2622                ),
2623                hints: vec![
2624                    if matches!(invalid_type, InvalidImplementingForType::SelfType) {
2625                        Hint::help(
2626                            source_engine,
2627                            span.clone(),
2628                            format!("Replace {invalid_type} with the actual type that you want to implement for.")
2629                        )
2630                    } else {
2631                        Hint::none()
2632                    }
2633                ],
2634                help: {
2635                    if matches!(invalid_type, InvalidImplementingForType::Placeholder) {
2636                        vec![
2637                            format!("Are you trying to implement {} for any type?",
2638                                match trait_name {
2639                                    Some(trait_name) => format!("trait \"{trait_name}\""),
2640                                    None => "functionality".to_string(),
2641                                }
2642                            ),
2643                            Diagnostic::help_empty_line(),
2644                            "If so, use generic type parameters instead.".to_string(),
2645                            "E.g., instead of:".to_string(),
2646                            // The trait `trait_name` could represent an arbitrary complex trait.
2647                            // E.g., `with generic arguments, etc. So we don't want to deal
2648                            // with the complexity of representing it properly
2649                            // but rather use a simplified but clearly instructive
2650                            // sample trait name here, `SomeTrait`.
2651                            // impl _
2652                            //   or
2653                            // impl SomeTrait for _
2654                            format!("{}impl {}_",
2655                                Indent::Single,
2656                                match trait_name {
2657                                    Some(_) => "SomeTrait for ",
2658                                    None => "",
2659                                }
2660                            ),
2661                            "use:".to_string(),
2662                            format!("{}impl<T> {}T",
2663                                Indent::Single,
2664                                match trait_name {
2665                                    Some(_) => "SomeTrait for ",
2666                                    None => "",
2667                                }
2668                            ),
2669                        ]
2670                    } else {
2671                        vec![]
2672                    }
2673                }
2674            },
2675            ModulePathIsNotAnExpression { module_path, span } => Diagnostic {
2676                reason: Some(Reason::new(code(1), "Module path is not an expression".to_string())),
2677                issue: Issue::error(
2678                    source_engine,
2679                    span.clone(),
2680                    "This is a module path, and not an expression.".to_string()
2681                ),
2682                hints: vec![
2683                    Hint::help(
2684                        source_engine,
2685                        span.clone(),
2686                        "An expression is expected at this location, but a module path is found.".to_string()
2687                    ),
2688                ],
2689                help: vec![
2690                    "In expressions, module paths can only be used to fully qualify names with a path.".to_string(),
2691                    format!("E.g., `{module_path}::SOME_CONSTANT` or `{module_path}::some_function()`."),
2692                ]
2693            },
2694            Parse { error } => {
2695                match &error.kind {
2696                    ParseErrorKind::UnassignableExpression { erroneous_expression_kind, erroneous_expression_span } => Diagnostic {
2697                        reason: Some(Reason::new(code(1), "Expression cannot be assigned to".to_string())),
2698                        // A bit of a special handling for parentheses, because they are the only
2699                        // expression kind whose friendly name is in plural. Having it in singular
2700                        // or without this simple special handling gives very odd sounding sentences.
2701                        // Therefore, just a bit of a special handling.
2702                        issue: Issue::error(
2703                            source_engine,
2704                            error.span.clone(),
2705                            format!("This expression cannot be assigned to, because it {} {}{}.",
2706                                if &error.span == erroneous_expression_span { // If the whole expression is erroneous.
2707                                    "is"
2708                                } else {
2709                                    "contains"
2710                                },
2711                                if *erroneous_expression_kind == "parentheses" {
2712                                    ""
2713                                } else {
2714                                    a_or_an(erroneous_expression_kind)
2715                                },
2716                                erroneous_expression_kind
2717                            )
2718                        ),
2719                        hints: vec![
2720                            if &error.span != erroneous_expression_span {
2721                                Hint::info(
2722                                    source_engine,
2723                                    erroneous_expression_span.clone(),
2724                                    format!("{} the contained {erroneous_expression_kind}.",
2725                                        if *erroneous_expression_kind == "parentheses" {
2726                                            "These are"
2727                                        } else {
2728                                            "This is"
2729                                        }
2730                                    )
2731                                )
2732                            } else {
2733                                Hint::none()
2734                            },
2735                        ],
2736                        help: vec![
2737                            format!("{} cannot be {}an assignment target.",
2738                                ascii_sentence_case(&erroneous_expression_kind.to_string()),
2739                                if &error.span == erroneous_expression_span {
2740                                    ""
2741                                } else {
2742                                    "a part of "
2743                                }
2744                            ),
2745                            Diagnostic::help_empty_line(),
2746                            "In Sway, assignment targets must be one of the following:".to_string(),
2747                            format!("{}- Expressions starting with a mutable variable, optionally having", Indent::Single),
2748                            format!("{}  array or tuple element accesses, struct field accesses,", Indent::Single),
2749                            format!("{}  or arbitrary combinations of those.", Indent::Single),
2750                            format!("{}  E.g., `mut_var` or `mut_struct.field` or `mut_array[x + y].field.1`.", Indent::Single),
2751                            Diagnostic::help_empty_line(),
2752                            format!("{}- Dereferencing of an arbitrary expression that results", Indent::Single),
2753                            format!("{}  in a reference to a mutable value.", Indent::Single),
2754                            format!("{}  E.g., `*ref_to_mutable_value` or `*max_mut(&mut x, &mut y)`.", Indent::Single),
2755                        ]
2756                    },
2757                    ParseErrorKind::UnrecognizedOpCode { known_op_codes } => Diagnostic {
2758                        reason: Some(Reason::new(code(1), "Assembly instruction is unknown".to_string())),
2759                        issue: Issue::error(
2760                            source_engine,
2761                            error.span.clone(),
2762                            format!("\"{}\" is not a known assembly instruction.",
2763                                error.span.as_str()
2764                            )
2765                        ),
2766                        hints: {
2767                            let suggestions = &did_you_mean(error.span.as_str(), known_op_codes.iter(), 2);
2768                            if suggestions.is_empty() {
2769                                vec![]
2770                            } else {
2771                                vec![
2772                                    Hint::help(
2773                                        source_engine,
2774                                        error.span.clone(),
2775                                        format!("Did you mean {}?", sequence_to_str_or(suggestions, Enclosing::DoubleQuote, 2))
2776                                    ),
2777                                ]
2778                            }
2779                        },
2780                        help: vec![]
2781                    },
2782                    _ => Diagnostic {
2783                                // TODO: Temporary we use self here to achieve backward compatibility.
2784                                //       In general, self must not be used and will not be used once we
2785                                //       switch to our own #[error] macro. All the values for the formatting
2786                                //       of a diagnostic must come from the enum variant parameters.
2787                                issue: Issue::error(source_engine, self.span(), format!("{}", self)),
2788                                ..Default::default()
2789                        },
2790                }
2791            },
2792            ConfigurableMissingAbiDecodeInPlace { span } => Diagnostic {
2793                reason: Some(Reason::new(code(1), "Configurables need a function named \"abi_decode_in_place\" to be in scope".to_string())),
2794                issue: Issue::error(
2795                    source_engine,
2796                    span.clone(),
2797                    String::new()
2798                ),
2799                hints: vec![],
2800                help: vec![
2801                    "The function \"abi_decode_in_place\" is usually defined in the standard library module \"std::codec\".".into(),
2802                    "Verify that you are using a version of the \"std\" standard library that contains this function.".into(),
2803                ],
2804            },
2805            StorageAccessMismatched { span, is_pure, suggested_attributes, storage_access_violations } => Diagnostic {
2806                // Pure function cannot access storage
2807                //   or
2808                // Storage read-only function cannot write to storage
2809                reason: Some(Reason::new(code(1), format!("{} function cannot {} storage",
2810                    if *is_pure {
2811                        "Pure"
2812                    } else {
2813                        "Storage read-only"
2814                    },
2815                    if *is_pure {
2816                        "access"
2817                    } else {
2818                        "write to"
2819                    }
2820                ))),
2821                issue: Issue::error(
2822                    source_engine,
2823                    span.clone(),
2824                    format!("Function \"{}\" is {} and cannot {} storage.",
2825                        span.as_str(),
2826                        if *is_pure {
2827                            "pure"
2828                        } else {
2829                            "declared as `#[storage(read)]`"
2830                        },
2831                        if *is_pure {
2832                            "access"
2833                        } else {
2834                            "write to"
2835                        },
2836                    )
2837                ),
2838                hints: storage_access_violations
2839                    .iter()
2840                    .map(|(span, storage_access)| Hint::info(
2841                        source_engine,
2842                        span.clone(),
2843                        format!("{storage_access}")
2844                    ))
2845                    .collect(),
2846                help: vec![
2847                    format!("Consider declaring the function \"{}\" as `#[{STORAGE_PURITY_ATTRIBUTE_NAME}({suggested_attributes})]`,",
2848                        span.as_str()
2849                    ),
2850                    format!("or removing the {} from the function body.",
2851                        if *is_pure {
2852                            "storage access code".to_string()
2853                        } else {
2854                            format!("storage write{}", plural_s(storage_access_violations.len()))
2855                        }
2856                    ),
2857                ],
2858            },
2859            MultipleImplsSatisfyingTraitForType { span, type_annotation , trait_names, trait_types_and_names: trait_types_and_spans } => Diagnostic {
2860                reason: Some(Reason::new(code(1), format!("Multiple impls satisfying {} for {}", trait_names.join("+"), type_annotation))),
2861                issue: Issue::error(
2862                    source_engine,
2863                    span.clone(),
2864                    String::new()
2865                ),
2866                hints: vec![],
2867                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))| 
2868                    format!("#{} {} for {}", e, name, type_id.clone())
2869                ).collect::<Vec<_>>().join("\n"))],
2870            },
2871            MultipleContractsMethodsWithTheSameName { spans } => Diagnostic {
2872                reason: Some(Reason::new(code(1), "Multiple contracts methods with the same name.".into())),
2873                issue: Issue::error(
2874                    source_engine,
2875                    spans[0].clone(),
2876                    "This is the first method".into()
2877                ),
2878                hints: spans.iter().skip(1).map(|span| {
2879                    Hint::error(source_engine, span.clone(), "This is the duplicated method.".into())
2880                }).collect(),
2881                help: vec!["Contract methods names must be unique, even when implementing multiple ABIs.".into()],
2882            },
2883            FunctionSelectorClash { method_name, span, other_method_name, other_span } => Diagnostic {
2884		reason: Some(Reason::new(code(1), format!("Methods {method_name} and {other_method_name} have clashing function selectors."))),
2885		issue: Issue::error(
2886		    source_engine,
2887		    span.clone(),
2888		    String::new()
2889		),
2890		hints: vec![Hint::error(source_engine, other_span.clone(), format!("The declaration of {other_method_name} is here"))],
2891		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")]
2892	    },
2893            _ => Diagnostic {
2894                    // TODO: Temporary we use self here to achieve backward compatibility.
2895                    //       In general, self must not be used and will not be used once we
2896                    //       switch to our own #[error] macro. All the values for the formatting
2897                    //       of a diagnostic must come from the enum variant parameters.
2898                    issue: Issue::error(source_engine, self.span(), format!("{}", self)),
2899                    ..Default::default()
2900            }
2901        }
2902    }
2903}
2904
2905#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
2906pub enum TypeNotAllowedReason {
2907    #[error(
2908        "Returning a type containing `raw_slice` from `main()` is not allowed. \
2909            Consider converting it into a flat `raw_slice` first."
2910    )]
2911    NestedSliceReturnNotAllowedInMain,
2912
2913    #[error("The type \"{ty}\" is not allowed in storage.")]
2914    TypeNotAllowedInContractStorage { ty: String },
2915
2916    #[error("`str` or a type containing `str` on `main()` arguments is not allowed.")]
2917    StringSliceInMainParameters,
2918
2919    #[error("Returning `str` or a type containing `str` from `main()` is not allowed.")]
2920    StringSliceInMainReturn,
2921
2922    #[error("`str` or a type containing `str` on `configurables` is not allowed.")]
2923    StringSliceInConfigurables,
2924
2925    #[error("`str` or a type containing `str` on `const` is not allowed.")]
2926    StringSliceInConst,
2927
2928    #[error("slices or types containing slices on `const` are not allowed.")]
2929    SliceInConst,
2930
2931    #[error("references, pointers, slices, string slices or types containing any of these are not allowed.")]
2932    NotAllowedInTransmute,
2933}
2934
2935#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2936pub enum StructFieldUsageContext {
2937    StructInstantiation { struct_can_be_instantiated: bool },
2938    StorageDeclaration { struct_can_be_instantiated: bool },
2939    StorageAccess,
2940    PatternMatching { has_rest_pattern: bool },
2941    StructFieldAccess,
2942    // TODO: Distinguish between struct field access and destructing
2943    //       once https://github.com/FuelLabs/sway/issues/5478 is implemented
2944    //       and provide specific suggestions for these two cases.
2945    //       (Destructing desugars to plain struct field access.)
2946}
2947
2948#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2949pub enum InvalidImplementingForType {
2950    SelfType,
2951    Placeholder,
2952    Other,
2953}
2954
2955impl fmt::Display for InvalidImplementingForType {
2956    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2957        match self {
2958            Self::SelfType => f.write_str("\"Self\""),
2959            Self::Placeholder => f.write_str("Placeholder `_`"),
2960            Self::Other => f.write_str("This"),
2961        }
2962    }
2963}
2964
2965/// Defines what shadows a constant or a configurable.
2966#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2967pub enum ShadowingSource {
2968    /// A constant or a configurable is shadowed by a constant.
2969    Const,
2970    /// A constant or a configurable is shadowed by a local variable declared with the `let` keyword.
2971    LetVar,
2972    /// A constant or a configurable is shadowed by a variable declared in pattern matching,
2973    /// being a struct field. E.g., `S { some_field }`.
2974    PatternMatchingStructFieldVar,
2975}
2976
2977impl fmt::Display for ShadowingSource {
2978    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2979        match self {
2980            Self::Const => f.write_str("Constant"),
2981            Self::LetVar => f.write_str("Variable"),
2982            Self::PatternMatchingStructFieldVar => f.write_str("Pattern variable"),
2983        }
2984    }
2985}
2986
2987/// Defines how a storage gets accessed within a function body.
2988/// E.g., calling `__state_clear` intrinsic or using `scwq` ASM instruction
2989/// represent a [StorageAccess::Clear] access.
2990#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2991pub enum StorageAccess {
2992    Clear,
2993    ReadWord,
2994    ReadSlots,
2995    WriteWord,
2996    WriteSlots,
2997    /// Storage access happens via call to an impure function.
2998    /// The parameters are the call path span and if the called function
2999    /// reads from and writes to the storage: (call_path, reads, writes).
3000    ImpureFunctionCall(Span, bool, bool),
3001}
3002
3003impl StorageAccess {
3004    pub fn is_write(&self) -> bool {
3005        matches!(
3006            self,
3007            Self::Clear | Self::WriteWord | Self::WriteSlots | Self::ImpureFunctionCall(_, _, true)
3008        )
3009    }
3010}
3011
3012impl fmt::Display for StorageAccess {
3013    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3014        match self {
3015            Self::Clear => f.write_str("Clearing the storage happens here."),
3016            Self::ReadWord => f.write_str("Reading a word from the storage happens here."),
3017            Self::ReadSlots => f.write_str("Reading storage slots happens here."),
3018            Self::WriteWord => f.write_str("Writing a word to the storage happens here."),
3019            Self::WriteSlots => f.write_str("Writing to storage slots happens here."),
3020            Self::ImpureFunctionCall(call_path, reads, writes) => f.write_fmt(format_args!(
3021                "Function \"{}\" {} the storage.",
3022                call_path_suffix_with_args(&call_path.as_str().to_string()),
3023                match (reads, writes) {
3024                    (true, true) => "reads from and writes to",
3025                    (true, false) => "reads from",
3026                    (false, true) => "writes to",
3027                    (false, false) => unreachable!(
3028                        "Function \"{}\" is impure, so it must read from or write to the storage.",
3029                        call_path.as_str()
3030                    ),
3031                }
3032            )),
3033        }
3034    }
3035}
3036
3037/// Extracts only the suffix part of the `marker_trait_full_name`, without the arguments.
3038/// E.g.:
3039/// - `std::marker::Error` => `Error`
3040/// - `std::marker::SomeMarkerTrait::<T>` => `SomeMarkerTrait`
3041/// - `std::marker::SomeMarkerTrait<T>` => `SomeMarkerTrait`
3042///
3043/// Panics if the `marker_trait_full_name` does not start with "std::marker::".
3044fn marker_trait_name(marker_trait_full_name: &str) -> &str {
3045    const MARKER_TRAITS_MODULE: &str = "std::marker::";
3046    assert!(
3047        marker_trait_full_name.starts_with(MARKER_TRAITS_MODULE),
3048        "`marker_trait_full_name` must start with \"std::marker::\", but it was \"{}\"",
3049        marker_trait_full_name
3050    );
3051
3052    let lower_boundary = MARKER_TRAITS_MODULE.len();
3053    let name_part = &marker_trait_full_name[lower_boundary..];
3054
3055    let upper_boundary = marker_trait_full_name.len() - lower_boundary;
3056    let only_name_len = std::cmp::min(
3057        name_part.find(':').unwrap_or(upper_boundary),
3058        name_part.find('<').unwrap_or(upper_boundary),
3059    );
3060    let upper_boundary = lower_boundary + only_name_len;
3061
3062    &marker_trait_full_name[lower_boundary..upper_boundary]
3063}