Skip to main content

sway_error/
error.rs

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