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