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("Expected string literal")]
935 ExpectedStringLiteral { span: Span },
936 #[error("\"break\" used outside of a loop")]
937 BreakOutsideLoop { span: Span },
938 #[error("\"continue\" used outside of a loop")]
939 ContinueOutsideLoop { span: Span },
940 #[error("Contract ID value is not a literal.")]
943 ContractIdValueNotALiteral { span: Span },
944
945 #[error("{reason}")]
946 TypeNotAllowed {
947 reason: TypeNotAllowedReason,
948 span: Span,
949 },
950 #[error("ref mut parameter not allowed for main()")]
951 RefMutableNotAllowedInMain { param_name: Ident, span: Span },
952 #[error(
953 "Register \"{name}\" is initialized and later reassigned which is not allowed. \
954 Consider assigning to a different register inside the ASM block."
955 )]
956 InitializedRegisterReassignment { name: String, span: Span },
957 #[error("Control flow VM instructions are not allowed in assembly blocks.")]
958 DisallowedControlFlowInstruction { name: String, span: Span },
959 #[error("Calling private library method {name} is not allowed.")]
960 CallingPrivateLibraryMethod { name: String, span: Span },
961 #[error("Using intrinsic \"{intrinsic}\" in a predicate is not allowed.")]
962 DisallowedIntrinsicInPredicate { intrinsic: String, span: Span },
963 #[error("Possibly non-zero amount of coins transferred to non-payable contract method \"{fn_name}\".")]
964 CoinsPassedToNonPayableMethod { fn_name: Ident, span: Span },
965 #[error(
966 "Payable attribute mismatch. The \"{fn_name}\" method implementation \
967 {} in its signature in {interface_name}.",
968 if *missing_impl_attribute {
969 "is missing #[payable] attribute specified"
970 } else {
971 "has extra #[payable] attribute not mentioned"
972 }
973 )]
974 TraitImplPayabilityMismatch {
975 fn_name: Ident,
976 interface_name: InterfaceName,
977 missing_impl_attribute: bool,
978 span: Span,
979 },
980 #[error("Configurable constants are not allowed in libraries.")]
981 ConfigurableInLibrary { span: Span },
982 #[error("Multiple applicable items in scope. {}", {
983 let mut candidates = "".to_string();
984 let mut as_traits = as_traits.clone();
985 as_traits.sort_by_key(|a| a.0.to_lowercase());
987 for (index, as_trait) in as_traits.iter().enumerate() {
988 candidates = format!("{candidates}\n Disambiguate the associated {item_kind} for candidate #{index}\n <{} as {}>::{item_name}", as_trait.1, as_trait.0);
989 }
990 candidates
991 })]
992 MultipleApplicableItemsInScope {
993 span: Span,
994 item_name: String,
995 item_kind: String,
996 as_traits: Vec<(String, String)>,
997 },
998 #[error("Provided generic type is not of type str.")]
999 NonStrGenericType { span: Span },
1000 #[error("A contract method cannot call methods belonging to the same ABI")]
1001 ContractCallsItsOwnMethod { span: Span },
1002 #[error("ABI cannot define a method of the same name as its super-ABI \"{superabi}\"")]
1003 AbiShadowsSuperAbiMethod { span: Span, superabi: Ident },
1004 #[error("ABI cannot inherit samely named method (\"{method_name}\") from several super-ABIs: \"{superabi1}\" and \"{superabi2}\"")]
1005 ConflictingSuperAbiMethods {
1006 span: Span,
1007 method_name: String,
1008 superabi1: String,
1009 superabi2: String,
1010 },
1011 #[error("Associated types not supported in ABI.")]
1012 AssociatedTypeNotSupportedInAbi { span: Span },
1013 #[error("Cannot call ABI supertrait's method as a contract method: \"{fn_name}\"")]
1014 AbiSupertraitMethodCallAsContractCall { fn_name: Ident, span: Span },
1015 #[error(
1016 "Methods {method_name} and {other_method_name} name have clashing function selectors."
1017 )]
1018 FunctionSelectorClash {
1019 method_name: Ident,
1020 span: Span,
1021 other_method_name: Ident,
1022 other_span: Span,
1023 },
1024 #[error("{invalid_type} is not a valid type in the self type of an impl block.")]
1025 TypeIsNotValidAsImplementingFor {
1026 invalid_type: InvalidImplementingForType,
1027 trait_name: Option<String>,
1029 span: Span,
1030 },
1031 #[error("Uninitialized register is being read before being written")]
1032 UninitRegisterInAsmBlockBeingRead { span: Span },
1033 #[error("Expression of type \"{expression_type}\" cannot be dereferenced.")]
1034 ExpressionCannotBeDereferenced { expression_type: String, span: Span },
1035 #[error("Fallback functions can only exist in contracts")]
1036 FallbackFnsAreContractOnly { span: Span },
1037 #[error("Fallback functions cannot have parameters")]
1038 FallbackFnsCannotHaveParameters { span: Span },
1039 #[error("Could not generate the entry method. See errors above for more details.")]
1040 CouldNotGenerateEntry { span: Span },
1041 #[error("Missing `std` in dependencies.")]
1042 CouldNotGenerateEntryMissingStd { span: Span },
1043 #[error("Type \"{ty}\" does not implement AbiEncode or AbiDecode.")]
1044 CouldNotGenerateEntryMissingImpl { ty: String, span: Span },
1045 #[error("Only bool, u8, u16, u32, u64, u256, b256, string arrays and string slices can be used here.")]
1046 EncodingUnsupportedType { span: Span },
1047 #[error("Configurables need a function named \"abi_decode_in_place\" to be in scope.")]
1048 ConfigurableMissingAbiDecodeInPlace { span: Span },
1049 #[error("Invalid name found for renamed ABI type.\n")]
1050 ABIInvalidName { span: Span, name: String },
1051 #[error("Duplicated name found for renamed ABI type.\n")]
1052 ABIDuplicateName {
1053 span: Span,
1054 other_span: Span,
1055 is_attribute: bool,
1056 },
1057 #[error("Collision detected between two different types.\n Shared hash:{hash}\n First type:{first_type}\n Second type:{second_type}")]
1058 ABIHashCollision {
1059 span: Span,
1060 hash: String,
1061 first_type: String,
1062 second_type: String,
1063 },
1064 #[error("Type must be known at this point")]
1065 TypeMustBeKnownAtThisPoint { span: Span, internal: String },
1066 #[error("Multiple impls satisfying trait for type.")]
1067 MultipleImplsSatisfyingTraitForType {
1068 span: Span,
1069 type_annotation: String,
1070 trait_names: Vec<String>,
1071 trait_types_and_names: Vec<(String, String)>,
1072 },
1073 #[error("Multiple contracts methods with the same name.")]
1074 MultipleContractsMethodsWithTheSameName { spans: Vec<Span> },
1075 #[error("Error type enum \"{enum_name}\" has non-error variant{} {}. All variants must be marked as `#[error]`.",
1076 plural_s(non_error_variants.len()),
1077 sequence_to_str(non_error_variants, Enclosing::DoubleQuote, 2)
1078 )]
1079 ErrorTypeEnumHasNonErrorVariants {
1080 enum_name: IdentUnique,
1081 non_error_variants: Vec<IdentUnique>,
1082 },
1083 #[error("Enum variant \"{enum_variant_name}\" is marked as `#[error]`, but \"{enum_name}\" is not an `#[error_type]` enum.")]
1084 ErrorAttributeInNonErrorEnum {
1085 enum_name: IdentUnique,
1086 enum_variant_name: IdentUnique,
1087 },
1088 #[error("This expression has type \"{argument_type}\", which does not implement \"std::marker::Error\". Panic expression arguments must implement \"Error\".")]
1089 PanicExpressionArgumentIsNotError { argument_type: String, span: Span },
1090 #[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.",
1091 ord_num_suffix(*current as usize)
1092 )]
1093 MaxNumOfPanicExpressionsReached {
1094 current: u64,
1095 max_num: u64,
1096 span: Span,
1097 },
1098 #[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`.",
1099 ord_num_suffix(*current as usize)
1100 )]
1101 MaxNumOfPanickingCallsReached {
1102 current: u64,
1103 max_num: u64,
1104 span: Span,
1105 },
1106 #[error("Coherence violation: only traits defined in this crate can be implemented for external types.")]
1107 IncoherentImplDueToOrphanRule {
1108 trait_name: String,
1109 type_name: String,
1110 span: Span,
1111 },
1112}
1113
1114impl std::convert::From<TypeError> for CompileError {
1115 fn from(other: TypeError) -> CompileError {
1116 CompileError::TypeError(other)
1117 }
1118}
1119
1120impl Spanned for CompileError {
1121 fn span(&self) -> Span {
1122 use CompileError::*;
1123 match self {
1124 ConstGenericNotSupportedHere { span } => span.clone(),
1125 LengthExpressionNotSupported { span } => span.clone(),
1126 FeatureIsDisabled { span, .. } => span.clone(),
1127 ModuleDepGraphEvaluationError { .. } => Span::dummy(),
1128 ModuleDepGraphCyclicReference { .. } => Span::dummy(),
1129 UnknownVariable { span, .. } => span.clone(),
1130 NotAVariable { span, .. } => span.clone(),
1131 Unimplemented { span, .. } => span.clone(),
1132 TypeError(err) => err.span(),
1133 ParseError { span, .. } => span.clone(),
1134 Internal(_, span) => span.clone(),
1135 InternalOwned(_, span) => span.clone(),
1136 NoPredicateMainFunction(span) => span.clone(),
1137 PredicateMainDoesNotReturnBool(span) => span.clone(),
1138 NoScriptMainFunction(span) => span.clone(),
1139 MultipleDefinitionsOfFunction { span, .. } => span.clone(),
1140 MultipleDefinitionsOfName { span, .. } => span.clone(),
1141 MultipleDefinitionsOfConstant { new: span, .. } => span.clone(),
1142 MultipleDefinitionsOfType { span, .. } => span.clone(),
1143 MultipleDefinitionsOfMatchArmVariable { duplicate, .. } => duplicate.clone(),
1144 MultipleDefinitionsOfFallbackFunction { span, .. } => span.clone(),
1145 AssignmentToNonMutableVariable { lhs_span, .. } => lhs_span.clone(),
1146 AssignmentToConstantOrConfigurable { lhs_span, .. } => lhs_span.clone(),
1147 DeclAssignmentTargetCannotBeAssignedTo { lhs_span, .. } => lhs_span.clone(),
1148 AssignmentViaNonMutableReference { span, .. } => span.clone(),
1149 MutableParameterNotSupported { span, .. } => span.clone(),
1150 ImmutableArgumentToMutableParameter { span } => span.clone(),
1151 RefMutableNotAllowedInContractAbi { span, .. } => span.clone(),
1152 RefMutCannotReferenceConstant { span, .. } => span.clone(),
1153 RefMutCannotReferenceImmutableVariable { span, .. } => span.clone(),
1154 MethodRequiresMutableSelf { span, .. } => span.clone(),
1155 AssociatedFunctionCalledAsMethod { span, .. } => span.clone(),
1156 TypeParameterNotInTypeScope { span, .. } => span.clone(),
1157 MismatchedTypeInInterfaceSurface { span, .. } => span.clone(),
1158 UnknownTrait { span, .. } => span.clone(),
1159 FunctionNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1160 ConstantNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1161 TypeNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1162 MissingInterfaceSurfaceConstants { span, .. } => span.clone(),
1163 MissingInterfaceSurfaceTypes { span, .. } => span.clone(),
1164 MissingInterfaceSurfaceMethods { span, .. } => span.clone(),
1165 IncorrectNumberOfTypeArguments { span, .. } => span.clone(),
1166 DoesNotTakeTypeArguments { span, .. } => span.clone(),
1167 DoesNotTakeTypeArgumentsAsPrefix { span, .. } => span.clone(),
1168 TypeArgumentsNotAllowed { span } => span.clone(),
1169 NeedsTypeArguments { span, .. } => span.clone(),
1170 StructInstantiationMissingFieldForErrorRecovery { span, .. } => span.clone(),
1171 StructInstantiationMissingFields { span, .. } => span.clone(),
1172 StructCannotBeInstantiated { span, .. } => span.clone(),
1173 StructFieldIsPrivate { field_name, .. } => field_name.span(),
1174 StructFieldDoesNotExist { field_name, .. } => field_name.span(),
1175 StructFieldDuplicated { field_name, .. } => field_name.span(),
1176 MethodNotFound { called_method, .. } => called_method.span(),
1177 ModuleNotFound { span, .. } => span.clone(),
1178 TupleElementAccessOnNonTuple { span, .. } => span.clone(),
1179 NotAStruct { span, .. } => span.clone(),
1180 NotIndexable { span, .. } => span.clone(),
1181 FieldAccessOnNonStruct { span, .. } => span.clone(),
1182 SymbolNotFound { span, .. } => span.clone(),
1183 SymbolWithMultipleBindings { span, .. } => span.clone(),
1184 ImportPrivateSymbol { span, .. } => span.clone(),
1185 ImportPrivateModule { span, .. } => span.clone(),
1186 NoElseBranch { span, .. } => span.clone(),
1187 NotAType { span, .. } => span.clone(),
1188 MissingEnumInstantiator { span, .. } => span.clone(),
1189 PathDoesNotReturn { span, .. } => span.clone(),
1190 UnknownRegister { span, .. } => span.clone(),
1191 MissingImmediate { span, .. } => span.clone(),
1192 InvalidImmediateValue { span, .. } => span.clone(),
1193 UnknownEnumVariant { span, .. } => span.clone(),
1194 UnrecognizedOp { span, .. } => span.clone(),
1195 UnableToInferGeneric { span, .. } => span.clone(),
1196 UnconstrainedGenericParameter { span, .. } => span.clone(),
1197 TraitConstraintNotSatisfied { span, .. } => span.clone(),
1198 TraitConstraintMissing { span, .. } => span.clone(),
1199 Immediate06TooLarge { span, .. } => span.clone(),
1200 Immediate12TooLarge { span, .. } => span.clone(),
1201 Immediate18TooLarge { span, .. } => span.clone(),
1202 Immediate24TooLarge { span, .. } => span.clone(),
1203 IncorrectNumberOfAsmRegisters { span, .. } => span.clone(),
1204 UnnecessaryImmediate { span, .. } => span.clone(),
1205 AmbiguousPath { span } => span.clone(),
1206 ModulePathIsNotAnExpression { span, .. } => span.clone(),
1207 UnknownType { span, .. } => span.clone(),
1208 UnknownTypeName { span, .. } => span.clone(),
1209 FileCouldNotBeRead { span, .. } => span.clone(),
1210 ImportMustBeLibrary { span, .. } => span.clone(),
1211 MoreThanOneEnumInstantiator { span, .. } => span.clone(),
1212 UnnecessaryEnumInstantiator { span, .. } => span.clone(),
1213 UnitVariantWithParenthesesEnumInstantiator { span, .. } => span.clone(),
1214 TraitNotFound { span, .. } => span.clone(),
1215 TraitNotImportedAtFunctionApplication {
1216 function_call_site_span,
1217 ..
1218 } => function_call_site_span.clone(),
1219 InvalidExpressionOnLhs { span, .. } => span.clone(),
1220 TooManyArgumentsForFunction { span, .. } => span.clone(),
1221 TooFewArgumentsForFunction { span, .. } => span.clone(),
1222 MissingParenthesesForFunction { span, .. } => span.clone(),
1223 InvalidAbiType { span, .. } => span.clone(),
1224 NotAnAbi { span, .. } => span.clone(),
1225 ImplAbiForNonContract { span, .. } => span.clone(),
1226 ConflictingImplsForTraitAndType {
1227 second_impl_span, ..
1228 } => second_impl_span.clone(),
1229 MarkerTraitExplicitlyImplemented { span, .. } => span.clone(),
1230 DuplicateDeclDefinedForType {
1231 second_impl_span, ..
1232 } => second_impl_span.clone(),
1233 IncorrectNumberOfInterfaceSurfaceFunctionParameters { span, .. } => span.clone(),
1234 ArgumentParameterTypeMismatch { span, .. } => span.clone(),
1235 RecursiveCall { span, .. } => span.clone(),
1236 RecursiveCallChain { span, .. } => span.clone(),
1237 RecursiveType { span, .. } => span.clone(),
1238 RecursiveTypeChain { span, .. } => span.clone(),
1239 GMFromExternalContext { span, .. } => span.clone(),
1240 MintFromExternalContext { span, .. } => span.clone(),
1241 BurnFromExternalContext { span, .. } => span.clone(),
1242 ContractStorageFromExternalContext { span, .. } => span.clone(),
1243 InvalidOpcodeFromPredicate { span, .. } => span.clone(),
1244 ArrayOutOfBounds { span, .. } => span.clone(),
1245 ConstantRequiresExpression { span, .. } => span.clone(),
1246 ConstantsCannotBeShadowed { name, .. } => name.span(),
1247 ConfigurablesCannotBeShadowed { name, .. } => name.span(),
1248 ConfigurablesCannotBeMatchedAgainst { name, .. } => name.span(),
1249 ConstantShadowsVariable { name, .. } => name.span(),
1250 ConstantDuplicatesConstantOrConfigurable { name, .. } => name.span(),
1251 ShadowsOtherSymbol { name } => name.span(),
1252 GenericShadowsGeneric { name } => name.span(),
1253 MatchExpressionNonExhaustive { span, .. } => span.clone(),
1254 MatchStructPatternMissingFields { span, .. } => span.clone(),
1255 MatchStructPatternMustIgnorePrivateFields { span, .. } => span.clone(),
1256 MatchArmVariableNotDefinedInAllAlternatives { variable, .. } => variable.span(),
1257 MatchArmVariableMismatchedType { variable, .. } => variable.span(),
1258 MatchedValueIsNotValid { span, .. } => span.clone(),
1259 NotAnEnum { span, .. } => span.clone(),
1260 TraitDeclPureImplImpure { span, .. } => span.clone(),
1261 TraitImplPurityMismatch { span, .. } => span.clone(),
1262 DeclIsNotAnEnum { span, .. } => span.clone(),
1263 DeclIsNotAStruct { span, .. } => span.clone(),
1264 DeclIsNotAFunction { span, .. } => span.clone(),
1265 DeclIsNotAVariable { span, .. } => span.clone(),
1266 DeclIsNotAnAbi { span, .. } => span.clone(),
1267 DeclIsNotATrait { span, .. } => span.clone(),
1268 DeclIsNotAnImplTrait { span, .. } => span.clone(),
1269 DeclIsNotATraitFn { span, .. } => span.clone(),
1270 DeclIsNotStorage { span, .. } => span.clone(),
1271 DeclIsNotAConstant { span, .. } => span.clone(),
1272 DeclIsNotATypeAlias { span, .. } => span.clone(),
1273 ImpureInNonContract { span, .. } => span.clone(),
1274 StorageAccessMismatched { span, .. } => span.clone(),
1275 ParameterRefMutabilityMismatch { span, .. } => span.clone(),
1276 IntegerTooLarge { span, .. } => span.clone(),
1277 IntegerTooSmall { span, .. } => span.clone(),
1278 IntegerContainsInvalidDigit { span, .. } => span.clone(),
1279 AbiAsSupertrait { span, .. } => span.clone(),
1280 SupertraitImplRequired { span, .. } => span.clone(),
1281 ContractCallParamRepeated { span, .. } => span.clone(),
1282 UnrecognizedContractParam { span, .. } => span.clone(),
1283 CallParamForNonContractCallMethod { span, .. } => span.clone(),
1284 StorageFieldDoesNotExist { field_name, .. } => field_name.span(),
1285 InvalidStorageOnlyTypeDecl { span, .. } => span.clone(),
1286 NoDeclaredStorage { span, .. } => span.clone(),
1287 MultipleStorageDeclarations { span, .. } => span.clone(),
1288 UnexpectedDeclaration { span, .. } => span.clone(),
1289 ContractAddressMustBeKnown { span, .. } => span.clone(),
1290 ConvertParseTree { error } => error.span(),
1291 Lex { error } => error.span(),
1292 Parse { error } => error.span.clone(),
1293 EnumNotFound { span, .. } => span.clone(),
1294 TupleIndexOutOfBounds { span, .. } => span.clone(),
1295 NonConstantDeclValue { span, .. } => span.clone(),
1296 StorageDeclarationInNonContract { span, .. } => span.clone(),
1297 IntrinsicUnsupportedArgType { span, .. } => span.clone(),
1298 IntrinsicIncorrectNumArgs { span, .. } => span.clone(),
1299 IntrinsicIncorrectNumTArgs { span, .. } => span.clone(),
1300 BreakOutsideLoop { span } => span.clone(),
1301 ContinueOutsideLoop { span } => span.clone(),
1302 ContractIdValueNotALiteral { span } => span.clone(),
1303 RefMutableNotAllowedInMain { span, .. } => span.clone(),
1304 InitializedRegisterReassignment { span, .. } => span.clone(),
1305 DisallowedControlFlowInstruction { span, .. } => span.clone(),
1306 CallingPrivateLibraryMethod { span, .. } => span.clone(),
1307 DisallowedIntrinsicInPredicate { span, .. } => span.clone(),
1308 CoinsPassedToNonPayableMethod { span, .. } => span.clone(),
1309 TraitImplPayabilityMismatch { span, .. } => span.clone(),
1310 ConfigurableInLibrary { span } => span.clone(),
1311 MultipleApplicableItemsInScope { span, .. } => span.clone(),
1312 NonStrGenericType { span } => span.clone(),
1313 CannotBeEvaluatedToConst { span } => span.clone(),
1314 ContractCallsItsOwnMethod { span } => span.clone(),
1315 AbiShadowsSuperAbiMethod { span, .. } => span.clone(),
1316 ConflictingSuperAbiMethods { span, .. } => span.clone(),
1317 AssociatedTypeNotSupportedInAbi { span, .. } => span.clone(),
1318 AbiSupertraitMethodCallAsContractCall { span, .. } => span.clone(),
1319 FunctionSelectorClash { span, .. } => span.clone(),
1320 TypeNotAllowed { span, .. } => span.clone(),
1321 ExpectedStringLiteral { span } => span.clone(),
1322 TypeIsNotValidAsImplementingFor { span, .. } => span.clone(),
1323 UninitRegisterInAsmBlockBeingRead { span } => span.clone(),
1324 ExpressionCannotBeDereferenced { span, .. } => span.clone(),
1325 FallbackFnsAreContractOnly { span } => span.clone(),
1326 FallbackFnsCannotHaveParameters { span } => span.clone(),
1327 CouldNotGenerateEntry { span } => span.clone(),
1328 CouldNotGenerateEntryMissingStd { span } => span.clone(),
1329 CouldNotGenerateEntryMissingImpl { span, .. } => span.clone(),
1330 CannotBeEvaluatedToConfigurableSizeUnknown { span } => span.clone(),
1331 EncodingUnsupportedType { span } => span.clone(),
1332 ConfigurableMissingAbiDecodeInPlace { span } => span.clone(),
1333 ABIInvalidName { span, .. } => span.clone(),
1334 ABIDuplicateName { span, .. } => span.clone(),
1335 ABIHashCollision { span, .. } => span.clone(),
1336 InvalidRangeEndGreaterThanStart { span, .. } => span.clone(),
1337 TypeMustBeKnownAtThisPoint { span, .. } => span.clone(),
1338 MultipleImplsSatisfyingTraitForType { span, .. } => span.clone(),
1339 MultipleContractsMethodsWithTheSameName { spans } => spans[0].clone(),
1340 ErrorTypeEnumHasNonErrorVariants { enum_name, .. } => enum_name.span(),
1341 ErrorAttributeInNonErrorEnum {
1342 enum_variant_name, ..
1343 } => enum_variant_name.span(),
1344 PanicExpressionArgumentIsNotError { span, .. } => span.clone(),
1345 MaxNumOfPanicExpressionsReached { span, .. } => span.clone(),
1346 MaxNumOfPanickingCallsReached { span, .. } => span.clone(),
1347 IncoherentImplDueToOrphanRule { span, .. } => span.clone(),
1348 }
1349 }
1350}
1351
1352impl ToDiagnostic for CompileError {
1364 fn to_diagnostic(&self, source_engine: &SourceEngine) -> Diagnostic {
1365 let code = Code::semantic_analysis;
1366 use CompileError::*;
1367 match self {
1368 ConstantsCannotBeShadowed { shadowing_source, name, constant_span, constant_decl_span, is_alias } => Diagnostic {
1369 reason: Some(Reason::new(code(1), "Constants cannot be shadowed".to_string())),
1370 issue: Issue::error(
1371 source_engine,
1372 name.span(),
1373 format!(
1374 "{shadowing_source} \"{name}\" shadows {}constant of the same name.",
1380 if constant_decl_span.clone() != Span::dummy() { "imported " } else { "" }
1381 )
1382 ),
1383 hints: vec![
1384 Hint::info(
1385 source_engine,
1386 constant_span.clone(),
1387 format!(
1388 "Shadowed constant \"{name}\" {} here{}.",
1394 if constant_decl_span.clone() != Span::dummy() { "gets imported" } else { "is declared" },
1395 if *is_alias { " as alias" } else { "" }
1396 )
1397 ),
1398 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1399 Hint::help(
1400 source_engine,
1401 name.span(),
1402 format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1403 )
1404 } else {
1405 Hint::none()
1406 },
1407 Hint::info( source_engine,
1409 constant_decl_span.clone(),
1410 format!("This is the original declaration of the imported constant \"{name}\".")
1411 ),
1412 ],
1413 help: vec![
1414 "Unlike variables, constants cannot be shadowed by other constants or variables.".to_string(),
1415 match (shadowing_source, *constant_decl_span != Span::dummy()) {
1416 (LetVar | PatternMatchingStructFieldVar, false) => format!("Consider renaming either the {} \"{name}\" or the constant \"{name}\".",
1417 format!("{shadowing_source}").to_lowercase(),
1418 ),
1419 (Const, false) => "Consider renaming one of the constants.".to_string(),
1420 (shadowing_source, true) => format!(
1421 "Consider renaming the {} \"{name}\" or using {} for the imported constant.",
1422 format!("{shadowing_source}").to_lowercase(),
1423 if *is_alias { "a different alias" } else { "an alias" }
1424 ),
1425 },
1426 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1427 format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1428 } else {
1429 Diagnostic::help_none()
1430 }
1431 ],
1432 },
1433 ConfigurablesCannotBeShadowed { shadowing_source, name, configurable_span } => Diagnostic {
1434 reason: Some(Reason::new(code(1), "Configurables cannot be shadowed".to_string())),
1435 issue: Issue::error(
1436 source_engine,
1437 name.span(),
1438 format!("{shadowing_source} \"{name}\" shadows configurable of the same name.")
1439 ),
1440 hints: vec![
1441 Hint::info(
1442 source_engine,
1443 configurable_span.clone(),
1444 format!("Shadowed configurable \"{name}\" is declared here.")
1445 ),
1446 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1447 Hint::help(
1448 source_engine,
1449 name.span(),
1450 format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1451 )
1452 } else {
1453 Hint::none()
1454 },
1455 ],
1456 help: vec![
1457 "Unlike variables, configurables cannot be shadowed by constants or variables.".to_string(),
1458 format!(
1459 "Consider renaming either the {} \"{name}\" or the configurable \"{name}\".",
1460 format!("{shadowing_source}").to_lowercase()
1461 ),
1462 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1463 format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1464 } else {
1465 Diagnostic::help_none()
1466 }
1467 ],
1468 },
1469 ConfigurablesCannotBeMatchedAgainst { name, configurable_span } => Diagnostic {
1470 reason: Some(Reason::new(code(1), "Configurables cannot be matched against".to_string())),
1471 issue: Issue::error(
1472 source_engine,
1473 name.span(),
1474 format!("\"{name}\" is a configurable and configurables cannot be matched against.")
1475 ),
1476 hints: {
1477 let mut hints = vec![
1478 Hint::info(
1479 source_engine,
1480 configurable_span.clone(),
1481 format!("Configurable \"{name}\" is declared here.")
1482 ),
1483 ];
1484
1485 hints.append(&mut Hint::multi_help(source_engine, &name.span(), vec![
1486 format!("Are you trying to define a pattern variable named \"{name}\"?"),
1487 format!("In that case, use some other name for the pattern variable,"),
1488 format!("or consider renaming the configurable \"{name}\"."),
1489 ]));
1490
1491 hints
1492 },
1493 help: vec![
1494 "Unlike constants, configurables cannot be matched against in pattern matching.".to_string(),
1495 "That's not possible, because patterns to match against must be compile-time constants.".to_string(),
1496 "Configurables are run-time constants. Their values are defined during the deployment.".to_string(),
1497 Diagnostic::help_empty_line(),
1498 "To test against a configurable, consider:".to_string(),
1499 format!("{}- replacing the `match` expression with `if-else`s altogether.", Indent::Single),
1500 format!("{}- matching against a variable and comparing that variable afterwards with the configurable.", Indent::Single),
1501 format!("{} E.g., instead of:", Indent::Single),
1502 Diagnostic::help_empty_line(),
1503 format!("{} SomeStruct {{ x: A_CONFIGURABLE, y: 42 }} => {{", Indent::Double),
1504 format!("{} do_something();", Indent::Double),
1505 format!("{} }}", Indent::Double),
1506 Diagnostic::help_empty_line(),
1507 format!("{} to have:", Indent::Single),
1508 Diagnostic::help_empty_line(),
1509 format!("{} SomeStruct {{ x, y: 42 }} => {{", Indent::Double),
1510 format!("{} if x == A_CONFIGURABLE {{", Indent::Double),
1511 format!("{} do_something();", Indent::Double),
1512 format!("{} }}", Indent::Double),
1513 format!("{} }}", Indent::Double),
1514 ],
1515 },
1516 ConstantShadowsVariable { name , variable_span } => Diagnostic {
1517 reason: Some(Reason::new(code(1), "Constants cannot shadow variables".to_string())),
1518 issue: Issue::error(
1519 source_engine,
1520 name.span(),
1521 format!("Constant \"{name}\" shadows variable of the same name.")
1522 ),
1523 hints: vec![
1524 Hint::info(
1525 source_engine,
1526 variable_span.clone(),
1527 format!("This is the shadowed variable \"{name}\".")
1528 ),
1529 ],
1530 help: vec![
1531 format!("Variables can shadow other variables, but constants cannot."),
1532 format!("Consider renaming either the variable or the constant."),
1533 ],
1534 },
1535 ConstantDuplicatesConstantOrConfigurable { existing_constant_or_configurable, new_constant_or_configurable, name, existing_span } => Diagnostic {
1536 reason: Some(Reason::new(code(1), match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1537 ("Constant", "Constant") => "Constant of the same name already exists".to_string(),
1538 ("Constant", "Configurable") => "Constant of the same name as configurable already exists".to_string(),
1539 ("Configurable", "Constant") => "Configurable of the same name as constant already exists".to_string(),
1540 _ => unreachable!("We can have only the listed combinations. Configurable duplicating configurable is not a valid combination.")
1541 })),
1542 issue: Issue::error(
1543 source_engine,
1544 name.span(),
1545 format!("{new_constant_or_configurable} \"{name}\" has the same name as an already declared {}.",
1546 existing_constant_or_configurable.to_lowercase()
1547 )
1548 ),
1549 hints: vec![
1550 Hint::info(
1551 source_engine,
1552 existing_span.clone(),
1553 format!("{existing_constant_or_configurable} \"{name}\" is {}declared here.",
1554 if existing_constant_or_configurable == new_constant_or_configurable {
1556 "already "
1557 } else {
1558 ""
1559 }
1560 )
1561 ),
1562 ],
1563 help: vec![
1564 match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1565 ("Constant", "Constant") => "Consider renaming one of the constants, or in case of imported constants, using an alias.".to_string(),
1566 _ => "Consider renaming either the configurable or the constant, or in case of an imported constant, using an alias.".to_string(),
1567 },
1568 ],
1569 },
1570 MultipleDefinitionsOfMatchArmVariable { match_value, match_type, first_definition, first_definition_is_struct_field, duplicate, duplicate_is_struct_field } => Diagnostic {
1571 reason: Some(Reason::new(code(1), "Match pattern variable is already defined".to_string())),
1572 issue: Issue::error(
1573 source_engine,
1574 duplicate.clone(),
1575 format!("Variable \"{}\" is already defined in this match arm.", first_definition.as_str())
1576 ),
1577 hints: vec![
1578 Hint::help(
1579 source_engine,
1580 if *duplicate_is_struct_field {
1581 duplicate.clone()
1582 }
1583 else {
1584 Span::dummy()
1585 },
1586 format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str())
1587 ),
1588 Hint::info(
1589 source_engine,
1590 first_definition.clone(),
1591 format!(
1592 "This {}is the first definition of the variable \"{}\".",
1593 if *first_definition_is_struct_field {
1594 format!("struct field \"{}\" ", first_definition.as_str())
1595 }
1596 else {
1597 "".to_string()
1598 },
1599 first_definition.as_str(),
1600 )
1601 ),
1602 Hint::help(
1603 source_engine,
1604 if *first_definition_is_struct_field && !*duplicate_is_struct_field {
1605 first_definition.clone()
1606 }
1607 else {
1608 Span::dummy()
1609 },
1610 format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str()),
1611 ),
1612 Hint::info(
1613 source_engine,
1614 match_value.clone(),
1615 format!("The expression to match on is of type \"{match_type}\".")
1616 ),
1617 ],
1618 help: vec![
1619 format!("Variables used in match arm patterns must be unique within a pattern, except in alternatives."),
1620 match (*first_definition_is_struct_field, *duplicate_is_struct_field) {
1621 (true, true) => format!("Consider declaring a variable with different name for either of the fields. E.g., `{0}: var_{0}`.", first_definition.as_str()),
1622 (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()),
1623 (false, false) => "Consider renaming either of the variables.".to_string(),
1624 },
1625 ],
1626 },
1627 MatchArmVariableMismatchedType { match_value, match_type, variable, first_definition, expected, received } => Diagnostic {
1628 reason: Some(Reason::new(code(1), "Match pattern variable has mismatched type".to_string())),
1629 issue: Issue::error(
1630 source_engine,
1631 variable.span(),
1632 format!("Variable \"{variable}\" is expected to be of type \"{expected}\", but is \"{received}\".")
1633 ),
1634 hints: vec![
1635 Hint::info(
1636 source_engine,
1637 first_definition.clone(),
1638 format!("\"{variable}\" is first defined here with the type \"{}\".",
1639 short_name(expected),
1640 )
1641 ),
1642 Hint::info(
1643 source_engine,
1644 match_value.clone(),
1645 format!("The expression to match on is of type \"{match_type}\".")
1646 ),
1647 ],
1648 help: vec![
1649 format!("In the same match arm, a variable must have the same type in all alternatives."),
1650 ],
1651 },
1652 MatchArmVariableNotDefinedInAllAlternatives { match_value, match_type, variable, missing_in_alternatives} => Diagnostic {
1653 reason: Some(Reason::new(code(1), "Match pattern variable is not defined in all alternatives".to_string())),
1654 issue: Issue::error(
1655 source_engine,
1656 variable.span(),
1657 format!("Variable \"{variable}\" is not defined in all alternatives.")
1658 ),
1659 hints: {
1660 let mut hints = vec![
1661 Hint::info(
1662 source_engine,
1663 match_value.clone(),
1664 format!("The expression to match on is of type \"{match_type}\".")
1665 ),
1666 ];
1667
1668 for (i, alternative) in missing_in_alternatives.iter().enumerate() {
1669 hints.push(
1670 Hint::info(
1671 source_engine,
1672 alternative.clone(),
1673 format!("\"{variable}\" is {}missing in this alternative.", if i != 0 { "also " } else { "" }),
1674 )
1675 )
1676 }
1677
1678 hints
1679 },
1680 help: vec![
1681 format!("Consider removing the variable \"{variable}\" altogether, or adding it to all alternatives."),
1682 ],
1683 },
1684 MatchStructPatternMissingFields { missing_fields, missing_fields_are_public, struct_name, struct_decl_span, total_number_of_fields, span } => Diagnostic {
1685 reason: Some(Reason::new(code(1), "Struct pattern has missing fields".to_string())),
1686 issue: Issue::error(
1687 source_engine,
1688 span.clone(),
1689 format!("Struct pattern is missing the {}field{} {}.",
1690 if *missing_fields_are_public { "public " } else { "" },
1691 plural_s(missing_fields.len()),
1692 sequence_to_str(missing_fields, Enclosing::DoubleQuote, 2)
1693 )
1694 ),
1695 hints: vec![
1696 Hint::help(
1697 source_engine,
1698 span.clone(),
1699 "Struct pattern must either contain or ignore each struct field.".to_string()
1700 ),
1701 Hint::info(
1702 source_engine,
1703 struct_decl_span.clone(),
1704 format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1705 num_to_str(*total_number_of_fields),
1706 plural_s(*total_number_of_fields),
1707 )
1708 ),
1709 ],
1710 help: vec![
1711 format!("Consider ignoring {} field{} {}by using the `_` pattern{} `{}: _`.",
1715 singular_plural(missing_fields.len(), "the", "individual"),
1716 plural_s(missing_fields.len()),
1717 singular_plural(missing_fields.len(), &format!("\"{}\" ", missing_fields[0]), ""),
1718 singular_plural(missing_fields.len(), ":", ". E.g.,"),
1719 missing_fields[0]
1720 ),
1721 "Alternatively, consider ignoring all the missing fields by ending the struct pattern with `..`.".to_string(),
1722 ],
1723 },
1724 MatchStructPatternMustIgnorePrivateFields { private_fields, struct_name, struct_decl_span, all_fields_are_private, span } => Diagnostic {
1725 reason: Some(Reason::new(code(1), "Struct pattern must ignore inaccessible private fields".to_string())),
1726 issue: Issue::error(
1727 source_engine,
1728 span.clone(),
1729 format!("Struct pattern must ignore inaccessible private field{} {}.",
1730 plural_s(private_fields.len()),
1731 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1732 )
1733 ),
1734 hints: vec![
1735 Hint::help(
1736 source_engine,
1737 span.clone(),
1738 format!("To ignore the private field{}, end the struct pattern with `..`.",
1739 plural_s(private_fields.len()),
1740 )
1741 ),
1742 Hint::info(
1743 source_engine,
1744 struct_decl_span.clone(),
1745 format!("Struct \"{struct_name}\" is declared here, and has {}.",
1746 if *all_fields_are_private {
1747 "all private fields".to_string()
1748 } else {
1749 format!("private field{} {}",
1750 plural_s(private_fields.len()),
1751 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1752 )
1753 }
1754 )
1755 ),
1756 ],
1757 help: vec![],
1758 },
1759 TraitNotImportedAtFunctionApplication { trait_name, function_name, function_call_site_span, trait_constraint_span, trait_candidates } => {
1760 let mut trait_candidates = trait_candidates.clone();
1762 trait_candidates.sort();
1763 let trait_candidates = &trait_candidates; Diagnostic {
1766 reason: Some(Reason::new(code(1), "Trait is not imported".to_string())),
1767 issue: Issue::error(
1768 source_engine,
1769 function_call_site_span.clone(),
1770 format!(
1771 "Trait \"{trait_name}\" is not imported {}when calling \"{function_name}\".",
1772 get_file_name(source_engine, function_call_site_span.source_id())
1773 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1774 )
1775 ),
1776 hints: {
1777 let mut hints = vec![
1778 Hint::help(
1779 source_engine,
1780 function_call_site_span.clone(),
1781 format!("This import is needed because \"{function_name}\" requires \"{trait_name}\" in one of its trait constraints.")
1782 ),
1783 Hint::info(
1784 source_engine,
1785 trait_constraint_span.clone(),
1786 format!("In the definition of \"{function_name}\", \"{trait_name}\" is used in this trait constraint.")
1787 ),
1788 ];
1789
1790 match trait_candidates.len() {
1791 0 => (),
1796 1 => hints.push(Hint::help(
1798 source_engine,
1799 function_call_site_span.clone(),
1800 format!(
1801 "Import the \"{trait_name}\" trait {}by using: `use {};`.",
1802 get_file_name(source_engine, function_call_site_span.source_id())
1803 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" ")),
1804 trait_candidates[0]
1805 )
1806 )),
1807 _ => hints.push(Hint::help(
1809 source_engine,
1810 function_call_site_span.clone(),
1811 format!(
1812 "To import the proper \"{trait_name}\" {}follow the detailed instructions given below.",
1813 get_file_name(source_engine, function_call_site_span.source_id())
1814 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1815 )
1816 )),
1817 }
1818
1819 hints
1820 },
1821 help: {
1822 let mut help = vec![];
1823
1824 if trait_candidates.len() > 1 {
1825 help.push(format!("There are these {} traits with the name \"{trait_name}\" available in the modules:", num_to_str(trait_candidates.len())));
1826 for trait_candidate in trait_candidates.iter() {
1827 help.push(format!("{}- {trait_candidate}", Indent::Single));
1828 }
1829 help.push("To import the proper one follow these steps:".to_string());
1830 help.push(format!(
1831 "{}1. Look at the definition of the \"{function_name}\"{}.",
1832 Indent::Single,
1833 get_file_name(source_engine, trait_constraint_span.source_id())
1834 .map_or("".to_string(), |file_name| format!(" in the \"{file_name}\""))
1835 ));
1836 help.push(format!(
1837 "{}2. Detect which exact \"{trait_name}\" is used in the trait constraint in the \"{function_name}\".",
1838 Indent::Single
1839 ));
1840 help.push(format!(
1841 "{}3. Import that \"{trait_name}\"{}.",
1842 Indent::Single,
1843 get_file_name(source_engine, function_call_site_span.source_id())
1844 .map_or("".to_string(), |file_name| format!(" into \"{file_name}\""))
1845 ));
1846 help.push(format!("{} E.g., assuming it is the first one on the list, use: `use {};`", Indent::Double, trait_candidates[0]));
1847 }
1848
1849 help
1850 },
1851 }
1852 },
1853 ExpressionCannotBeDereferenced { expression_type, span } => Diagnostic {
1855 reason: Some(Reason::new(code(1), "Expression cannot be dereferenced".to_string())),
1856 issue: Issue::error(
1857 source_engine,
1858 span.clone(),
1859 format!("This expression cannot be dereferenced, because it is of type \"{expression_type}\", which is not a reference type.")
1860 ),
1861 hints: vec![
1862 Hint::help(
1863 source_engine,
1864 span.clone(),
1865 "In Sway, only references can be dereferenced.".to_string()
1866 ),
1867 Hint::help(
1868 source_engine,
1869 span.clone(),
1870 "Are you missing the reference operator `&` somewhere in the code?".to_string()
1871 ),
1872 ],
1873 help: vec![],
1874 },
1875 StructInstantiationMissingFields { field_names, struct_name, span, struct_decl_span, total_number_of_fields } => Diagnostic {
1876 reason: Some(Reason::new(code(1), "Struct instantiation has missing fields".to_string())),
1877 issue: Issue::error(
1878 source_engine,
1879 span.clone(),
1880 format!("Instantiation of the struct \"{struct_name}\" is missing the field{} {}.",
1881 plural_s(field_names.len()),
1882 sequence_to_str(field_names, Enclosing::DoubleQuote, 2)
1883 )
1884 ),
1885 hints: vec![
1886 Hint::help(
1887 source_engine,
1888 span.clone(),
1889 "Struct instantiation must initialize all the fields of the struct.".to_string()
1890 ),
1891 Hint::info(
1892 source_engine,
1893 struct_decl_span.clone(),
1894 format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1895 num_to_str(*total_number_of_fields),
1896 plural_s(*total_number_of_fields),
1897 )
1898 ),
1899 ],
1900 help: vec![],
1901 },
1902 StructCannotBeInstantiated { struct_name, span, struct_decl_span, private_fields, constructors, all_fields_are_private, is_in_storage_declaration, struct_can_be_changed } => Diagnostic {
1903 reason: Some(Reason::new(code(1), "Struct cannot be instantiated due to inaccessible private fields".to_string())),
1904 issue: Issue::error(
1905 source_engine,
1906 span.clone(),
1907 format!("\"{struct_name}\" cannot be {}instantiated in this {}, due to {}inaccessible private field{}.",
1908 if *is_in_storage_declaration { "" } else { "directly " },
1909 if *is_in_storage_declaration { "storage declaration" } else { "module" },
1910 singular_plural(private_fields.len(), "an ", ""),
1911 plural_s(private_fields.len())
1912 )
1913 ),
1914 hints: vec![
1915 Hint::help(
1916 source_engine,
1917 span.clone(),
1918 format!("Inaccessible field{} {} {}.",
1919 plural_s(private_fields.len()),
1920 is_are(private_fields.len()),
1921 sequence_to_str(private_fields, Enclosing::DoubleQuote, 5)
1922 )
1923 ),
1924 Hint::help(
1925 source_engine,
1926 span.clone(),
1927 if *is_in_storage_declaration {
1928 "Structs with private fields can be instantiated in storage declarations only if they are declared in the same module as the storage.".to_string()
1929 } else {
1930 "Structs with private fields can be instantiated only within the module in which they are declared.".to_string()
1931 }
1932 ),
1933 if *is_in_storage_declaration {
1934 Hint::help(
1935 source_engine,
1936 span.clone(),
1937 "They can still be initialized in storage declarations if they have public constructors that evaluate to a constant.".to_string()
1938 )
1939 } else {
1940 Hint::none()
1941 },
1942 if *is_in_storage_declaration {
1943 Hint::help(
1944 source_engine,
1945 span.clone(),
1946 "They can always be stored in storage by using the `read` and `write` functions provided in the `std::storage::storage_api`.".to_string()
1947 )
1948 } else {
1949 Hint::none()
1950 },
1951 if !*is_in_storage_declaration && !constructors.is_empty() {
1952 Hint::help(
1953 source_engine,
1954 span.clone(),
1955 format!("\"{struct_name}\" can be instantiated via public constructors suggested below.")
1956 )
1957 } else {
1958 Hint::none()
1959 },
1960 Hint::info(
1961 source_engine,
1962 struct_decl_span.clone(),
1963 format!("Struct \"{struct_name}\" is declared here, and has {}.",
1964 if *all_fields_are_private {
1965 "all private fields".to_string()
1966 } else {
1967 format!("private field{} {}",
1968 plural_s(private_fields.len()),
1969 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1970 )
1971 }
1972 )
1973 ),
1974 ],
1975 help: {
1976 let mut help = vec![];
1977
1978 if *is_in_storage_declaration {
1979 help.push(format!("Consider initializing \"{struct_name}\" by finding an available constructor that evaluates to a constant{}.",
1980 if *struct_can_be_changed {
1981 ", or implement a new one"
1982 } else {
1983 ""
1984 }
1985 ));
1986
1987 if !constructors.is_empty() {
1988 help.push("Check these already available constructors. They might evaluate to a constant:".to_string());
1989 for constructor in sequence_to_list(constructors, Indent::Single, usize::MAX) {
1991 help.push(constructor);
1992 }
1993 };
1994
1995 help.push(Diagnostic::help_empty_line());
1996
1997 help.push(format!("Or you can always store instances of \"{struct_name}\" in the contract storage, by using the `std::storage::storage_api`:"));
1998 help.push(format!("{}use std::storage::storage_api::{{read, write}};", Indent::Single));
1999 help.push(format!("{}write(STORAGE_KEY, 0, my_{});", Indent::Single, to_snake_case(struct_name.as_str())));
2000 help.push(format!("{}let my_{}_option = read::<{struct_name}>(STORAGE_KEY, 0);", Indent::Single, to_snake_case(struct_name.as_str())));
2001 }
2002 else if !constructors.is_empty() {
2003 help.push(format!("Consider instantiating \"{struct_name}\" by using one of the available constructors{}:",
2004 if *struct_can_be_changed {
2005 ", or implement a new one"
2006 } else {
2007 ""
2008 }
2009 ));
2010 for constructor in sequence_to_list(constructors, Indent::Single, 5) {
2011 help.push(constructor);
2012 }
2013 }
2014
2015 if *struct_can_be_changed {
2016 if *is_in_storage_declaration || !constructors.is_empty() {
2017 help.push(Diagnostic::help_empty_line());
2018 }
2019
2020 if !*is_in_storage_declaration && constructors.is_empty() {
2021 help.push(format!("Consider implementing a public constructor for \"{struct_name}\"."));
2022 };
2023
2024 help.push(
2025 format!("Alternatively, consider declaring {} as public in \"{struct_name}\": `pub {}: ...,`.",
2031 if *all_fields_are_private {
2032 "all fields".to_string()
2033 } else {
2034 format!("{} {}",
2035 singular_plural(private_fields.len(), "the field", "the fields"),
2036 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
2037 )
2038 },
2039 if *all_fields_are_private {
2040 "<field>".to_string()
2041 } else {
2042 match &private_fields[..] {
2043 [field] => format!("{field}"),
2044 _ => "<field>".to_string(),
2045 }
2046 },
2047 )
2048 )
2049 };
2050
2051 help
2052 }
2053 },
2054 StructFieldIsPrivate { field_name, struct_name, field_decl_span, struct_can_be_changed, usage_context } => Diagnostic {
2055 reason: Some(Reason::new(code(1), "Private struct field is inaccessible".to_string())),
2056 issue: Issue::error(
2057 source_engine,
2058 field_name.span(),
2059 format!("Private field \"{field_name}\" {}is inaccessible in this module.",
2060 match usage_context {
2061 StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => "".to_string(),
2062 StorageAccess | StructFieldAccess => format!("of the struct \"{struct_name}\" "),
2063 }
2064 )
2065 ),
2066 hints: vec![
2067 Hint::help(
2068 source_engine,
2069 field_name.span(),
2070 format!("Private fields can only be {} within the module in which their struct is declared.",
2071 match usage_context {
2072 StructInstantiation { .. } | StorageDeclaration { .. } => "initialized",
2073 StorageAccess | StructFieldAccess => "accessed",
2074 PatternMatching { .. } => "matched",
2075 }
2076 )
2077 ),
2078 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2079 Hint::help(
2080 source_engine,
2081 field_name.span(),
2082 "Otherwise, they must be ignored by ending the struct pattern with `..`.".to_string()
2083 )
2084 } else {
2085 Hint::none()
2086 },
2087 Hint::info(
2088 source_engine,
2089 field_decl_span.clone(),
2090 format!("Field \"{field_name}\" {}is declared here as private.",
2091 match usage_context {
2092 StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => format!("of the struct \"{struct_name}\" "),
2093 StorageAccess | StructFieldAccess => "".to_string(),
2094 }
2095 )
2096 ),
2097 ],
2098 help: vec![
2099 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2100 format!("Consider removing the field \"{field_name}\" from the struct pattern, and ending the pattern with `..`.")
2101 } else {
2102 Diagnostic::help_none()
2103 },
2104 if *struct_can_be_changed {
2105 match usage_context {
2106 StorageAccess | StructFieldAccess | PatternMatching { .. } => {
2107 format!("{} declaring the field \"{field_name}\" as public in \"{struct_name}\": `pub {field_name}: ...,`.",
2108 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2109 "Alternatively, consider"
2110 } else {
2111 "Consider"
2112 }
2113 )
2114 },
2115 _ => Diagnostic::help_none(),
2117 }
2118 } else {
2119 Diagnostic::help_none()
2120 },
2121 ],
2122 },
2123 StructFieldDoesNotExist { field_name, available_fields, is_public_struct_access, struct_name, struct_decl_span, struct_is_empty, usage_context } => Diagnostic {
2124 reason: Some(Reason::new(code(1), "Struct field does not exist".to_string())),
2125 issue: Issue::error(
2126 source_engine,
2127 field_name.span(),
2128 format!("Field \"{field_name}\" does not exist in the struct \"{struct_name}\".")
2129 ),
2130 hints: {
2131 let public = if *is_public_struct_access { "public " } else { "" };
2132
2133 let (hint, show_struct_decl) = if *struct_is_empty {
2134 (Some(format!("\"{struct_name}\" is an empty struct. It doesn't have any fields.")), false)
2135 }
2136 else if (matches!(usage_context, StorageAccess) && *is_public_struct_access && available_fields.is_empty())
2141 ||
2142 (matches!(usage_context, StructInstantiation { struct_can_be_instantiated: false } | StorageDeclaration { struct_can_be_instantiated: false })) {
2143 (None, false)
2149 } else if !available_fields.is_empty() {
2150 const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2152 match &available_fields[..] {
2153 [field] => (Some(format!("Only available {public}field is \"{field}\".")), false),
2154 _ => (Some(format!("Available {public}fields are {}.", sequence_to_str(available_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY))),
2155 available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2156 ),
2157 }
2158 }
2159 else {
2160 (None, false)
2161 };
2162
2163 let mut hints = vec![];
2164
2165 if let Some(hint) = hint {
2166 hints.push(Hint::help(source_engine, field_name.span(), hint));
2167 };
2168
2169 if show_struct_decl {
2170 hints.push(Hint::info(
2171 source_engine,
2172 struct_decl_span.clone(),
2173 format!("Struct \"{struct_name}\" is declared here, and has {} {public}fields.",
2174 num_to_str(available_fields.len())
2175 )
2176 ));
2177 }
2178
2179 hints
2180 },
2181 help: vec![],
2182 },
2183 StructFieldDuplicated { field_name, duplicate } => Diagnostic {
2184 reason: Some(Reason::new(code(1), "Struct field has multiple definitions".to_string())),
2185 issue: Issue::error(
2186 source_engine,
2187 field_name.span(),
2188 format!("Field \"{field_name}\" has multiple definitions.")
2189 ),
2190 hints: {
2191 vec![
2192 Hint::info(
2193 source_engine,
2194 duplicate.span(),
2195 "Field definition duplicated here.".into(),
2196 )
2197 ]
2198 },
2199 help: vec![],
2200 },
2201 NotIndexable { actually, span } => Diagnostic {
2202 reason: Some(Reason::new(code(1), "Type is not indexable".to_string())),
2203 issue: Issue::error(
2204 source_engine,
2205 span.clone(),
2206 format!("This expression has type \"{actually}\", which is not an indexable type.")
2207 ),
2208 hints: vec![],
2209 help: vec![
2210 "Index operator `[]` can be used only on indexable types.".to_string(),
2211 "In Sway, indexable types are:".to_string(),
2212 format!("{}- arrays. E.g., `[u64;3]`.", Indent::Single),
2213 format!("{}- references, direct or indirect, to arrays. E.g., `&[u64;3]` or `&&&[u64;3]`.", Indent::Single),
2214 ],
2215 },
2216 FieldAccessOnNonStruct { actually, storage_variable, field_name, span } => Diagnostic {
2217 reason: Some(Reason::new(code(1), "Field access requires a struct".to_string())),
2218 issue: Issue::error(
2219 source_engine,
2220 span.clone(),
2221 format!("{} has type \"{actually}\", which is not a struct{}.",
2222 if let Some(storage_variable) = storage_variable {
2223 format!("Storage variable \"{storage_variable}\"")
2224 } else {
2225 "This expression".to_string()
2226 },
2227 if storage_variable.is_some() {
2228 ""
2229 } else {
2230 " or a reference to a struct"
2231 }
2232 )
2233 ),
2234 hints: vec![
2235 Hint::info(
2236 source_engine,
2237 field_name.span(),
2238 format!("Field access happens here, on \"{field_name}\".")
2239 )
2240 ],
2241 help: if storage_variable.is_some() {
2242 vec![
2243 "Fields can only be accessed on storage variables that are structs.".to_string(),
2244 ]
2245 } else {
2246 vec![
2247 "In Sway, fields can be accessed on:".to_string(),
2248 format!("{}- structs. E.g., `my_struct.field`.", Indent::Single),
2249 format!("{}- references, direct or indirect, to structs. E.g., `(&my_struct).field` or `(&&&my_struct).field`.", Indent::Single),
2250 ]
2251 }
2252 },
2253 SymbolWithMultipleBindings { name, paths, span } => Diagnostic {
2254 reason: Some(Reason::new(code(1), "Multiple bindings exist for symbol in the scope".to_string())),
2255 issue: Issue::error(
2256 source_engine,
2257 span.clone(),
2258 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)),
2259 ),
2260 hints: vec![],
2261 help: vec![format!("Consider using a fully qualified name, e.g., `{}::{}`.", paths[0], name)],
2262 },
2263 StorageFieldDoesNotExist { field_name, available_fields, storage_decl_span } => Diagnostic {
2264 reason: Some(Reason::new(code(1), "Storage field does not exist".to_string())),
2265 issue: Issue::error(
2266 source_engine,
2267 field_name.span(),
2268 format!("Storage field \"{field_name}\" does not exist in the storage.")
2269 ),
2270 hints: {
2271 let (hint, show_storage_decl) = if available_fields.is_empty() {
2272 ("The storage is empty. It doesn't have any fields.".to_string(), false)
2273 } else {
2274 const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2275 let display_fields = available_fields.iter().map(|(path, field_name)| {
2276 let path = path.iter().map(ToString::to_string).collect::<Vec<_>>().join("::");
2277 if path.is_empty() {
2278 format!("storage.{field_name}")
2279 } else {
2280 format!("storage::{path}.{field_name}")
2281 }
2282 }).collect::<Vec<_>>();
2283 match &display_fields[..] {
2284 [field] => (format!("Only available storage field is \"{field}\"."), false),
2285 _ => (format!("Available storage fields are {}.", sequence_to_str(&display_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY)),
2286 available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2287 ),
2288 }
2289 };
2290
2291 let mut hints = vec![];
2292
2293 hints.push(Hint::help(source_engine, field_name.span(), hint));
2294
2295 if show_storage_decl {
2296 hints.push(Hint::info(
2297 source_engine,
2298 storage_decl_span.clone(),
2299 format!("Storage is declared here, and has {} fields.",
2300 num_to_str(available_fields.len())
2301 )
2302 ));
2303 }
2304
2305 hints
2306 },
2307 help: vec![],
2308 },
2309 TupleIndexOutOfBounds { index, count, tuple_type, span, prefix_span } => Diagnostic {
2310 reason: Some(Reason::new(code(1), "Tuple index is out of bounds".to_string())),
2311 issue: Issue::error(
2312 source_engine,
2313 span.clone(),
2314 format!("Tuple index {index} is out of bounds. The tuple has only {count} element{}.", plural_s(*count))
2315 ),
2316 hints: vec![
2317 Hint::info(
2318 source_engine,
2319 prefix_span.clone(),
2320 format!("This expression has type \"{tuple_type}\".")
2321 ),
2322 ],
2323 help: vec![],
2324 },
2325 TupleElementAccessOnNonTuple { actually, span, index, index_span } => Diagnostic {
2326 reason: Some(Reason::new(code(1), "Tuple element access requires a tuple".to_string())),
2327 issue: Issue::error(
2328 source_engine,
2329 span.clone(),
2330 format!("This expression has type \"{actually}\", which is not a tuple or a reference to a tuple.")
2331 ),
2332 hints: vec![
2333 Hint::info(
2334 source_engine,
2335 index_span.clone(),
2336 format!("Tuple element access happens here, on the index {index}.")
2337 )
2338 ],
2339 help: vec![
2340 "In Sway, tuple elements can be accessed on:".to_string(),
2341 format!("{}- tuples. E.g., `my_tuple.1`.", Indent::Single),
2342 format!("{}- references, direct or indirect, to tuples. E.g., `(&my_tuple).1` or `(&&&my_tuple).1`.", Indent::Single),
2343 ],
2344 },
2345 RefMutCannotReferenceConstant { constant, span } => Diagnostic {
2346 reason: Some(Reason::new(code(1), "References to mutable values cannot reference constants".to_string())),
2347 issue: Issue::error(
2348 source_engine,
2349 span.clone(),
2350 format!("\"{constant}\" is a constant. `&mut` cannot reference constants.")
2351 ),
2352 hints: vec![],
2353 help: vec![
2354 "Consider:".to_string(),
2355 format!("{}- taking a reference without `mut`: `&{constant}`.", Indent::Single),
2356 format!("{}- referencing a mutable copy of the constant, by returning it from a block: `&mut {{ {constant} }}`.", Indent::Single)
2357 ],
2358 },
2359 RefMutCannotReferenceImmutableVariable { decl_name, span } => Diagnostic {
2360 reason: Some(Reason::new(code(1), "References to mutable values cannot reference immutable variables".to_string())),
2361 issue: Issue::error(
2362 source_engine,
2363 span.clone(),
2364 format!("\"{decl_name}\" is an immutable variable. `&mut` cannot reference immutable variables.")
2365 ),
2366 hints: vec![
2367 Hint::info(
2368 source_engine,
2369 decl_name.span(),
2370 format!("Variable \"{decl_name}\" is declared here as immutable.")
2371 ),
2372 ],
2373 help: vec![
2374 "Consider:".to_string(),
2375 format!("{}- declaring \"{decl_name}\" as mutable.", Indent::Single),
2377 format!("{}- taking a reference without `mut`: `&{decl_name}`.", Indent::Single),
2378 format!("{}- referencing a mutable copy of \"{decl_name}\", by returning it from a block: `&mut {{ {decl_name} }}`.", Indent::Single)
2379 ],
2380 },
2381 ConflictingImplsForTraitAndType { trait_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => Diagnostic {
2382 reason: Some(Reason::new(code(1), "Trait is already implemented for type".to_string())),
2383 issue: Issue::error(
2384 source_engine,
2385 second_impl_span.clone(),
2386 format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\"."),
2387 ),
2388 hints: vec![
2389 if type_implementing_for != type_implementing_for_unaliased {
2390 Hint::help(
2391 source_engine,
2392 second_impl_span.clone(),
2393 format!("\"{}\" is an alias for \"{type_implementing_for_unaliased}\".",
2394 short_name(type_implementing_for),
2395 ))
2396 } else {
2397 Hint::none()
2398 },
2399 Hint::info(
2400 source_engine,
2401 existing_impl_span.clone(),
2402 format!("This is the already existing implementation of \"{}\" for \"{}\".",
2403 short_name(trait_name),
2404 short_name(type_implementing_for),
2405 ),
2406 ),
2407 ],
2408 help: vec![
2409 "In Sway, there can be at most one implementation of a trait for any given type.".to_string(),
2410 "This property is called \"trait coherence\".".to_string(),
2411 ],
2412 },
2413 DuplicateDeclDefinedForType { decl_kind, decl_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => {
2414 let decl_kind_snake_case = sway_types::style::to_upper_camel_case(decl_kind);
2415 Diagnostic {
2416 reason: Some(Reason::new(code(1), "Type contains duplicate declarations".to_string())),
2417 issue: Issue::error(
2418 source_engine,
2419 second_impl_span.clone(),
2420 if type_implementing_for == type_implementing_for_unaliased {
2421 format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\".")
2422 } else {
2423 format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").")
2424 }
2425 ),
2426 hints: vec![
2427 Hint::info(
2428 source_engine,
2429 existing_impl_span.clone(),
2430 format!("\"{decl_name}\" previously defined here.")
2431 )
2432 ],
2433 help: vec![
2434 "A type may not contain two or more declarations of the same name".to_string(),
2435 ],
2436 }
2437 },
2438 MarkerTraitExplicitlyImplemented { marker_trait_full_name, span} => Diagnostic {
2439 reason: Some(Reason::new(code(1), "Marker traits cannot be explicitly implemented".to_string())),
2440 issue: Issue::error(
2441 source_engine,
2442 span.clone(),
2443 format!("Trait \"{marker_trait_full_name}\" is a marker trait and cannot be explicitly implemented.")
2444 ),
2445 hints: vec![],
2446 help: match marker_trait_name(marker_trait_full_name) {
2447 "Error" => error_marker_trait_help_msg(),
2448 "Enum" => vec![
2449 "\"Enum\" marker trait is automatically implemented by the compiler for all enum types.".to_string(),
2450 ],
2451 _ => vec![],
2452 }
2453 },
2454 AssignmentToNonMutableVariable { lhs_span, decl_name } => Diagnostic {
2455 reason: Some(Reason::new(code(1), "Immutable variables cannot be assigned to".to_string())),
2456 issue: Issue::error(
2457 source_engine,
2458 lhs_span.clone(),
2459 format!("{} cannot be assigned to, because {} is an immutable variable.",
2463 if decl_name.as_str() == lhs_span.as_str() { format!("\"{decl_name}\"")
2465 } else {
2466 "This expression".to_string()
2467 },
2468 if decl_name.as_str() == lhs_span.as_str() {
2469 "it".to_string()
2470 } else {
2471 format!("\"{decl_name}\"")
2472 }
2473 )
2474 ),
2475 hints: vec![
2476 Hint::info(
2477 source_engine,
2478 decl_name.span(),
2479 format!("Variable \"{decl_name}\" is declared here as immutable.")
2480 ),
2481 ],
2482 help: vec![
2483 format!("Consider declaring \"{decl_name}\" as mutable."),
2485 ],
2486 },
2487 AssignmentToConstantOrConfigurable { lhs_span, is_configurable, decl_name } => Diagnostic {
2488 reason: Some(Reason::new(code(1), format!("{} cannot be assigned to",
2489 if *is_configurable {
2490 "Configurables"
2491 } else {
2492 "Constants"
2493 }
2494 ))),
2495 issue: Issue::error(
2496 source_engine,
2497 lhs_span.clone(),
2498 format!("{} cannot be assigned to, because {} is a {}.",
2502 if decl_name.as_str() == lhs_span.as_str() { format!("\"{decl_name}\"")
2504 } else {
2505 "This expression".to_string()
2506 },
2507 if decl_name.as_str() == lhs_span.as_str() {
2508 "it".to_string()
2509 } else {
2510 format!("\"{decl_name}\"")
2511 },
2512 if *is_configurable {
2513 "configurable"
2514 } else {
2515 "constant"
2516 }
2517 )
2518 ),
2519 hints: vec![
2520 Hint::info(
2521 source_engine,
2522 decl_name.span(),
2523 format!("{} \"{decl_name}\" is declared here.",
2524 if *is_configurable {
2525 "Configurable"
2526 } else {
2527 "Constant"
2528 }
2529 )
2530 ),
2531 ],
2532 help: vec![],
2533 },
2534 DeclAssignmentTargetCannotBeAssignedTo { decl_name, decl_friendly_type_name, lhs_span } => Diagnostic {
2535 reason: Some(Reason::new(code(1), "Assignment target cannot be assigned to".to_string())),
2536 issue: Issue::error(
2537 source_engine,
2538 lhs_span.clone(),
2539 format!("{} cannot be assigned to, because {} is {}{decl_friendly_type_name} and not a mutable variable.",
2543 match decl_name {
2544 Some(decl_name) if decl_name.as_str() == lhs_span.as_str() => format!("\"{decl_name}\""),
2546 _ => "This".to_string(),
2547 },
2548 match decl_name {
2549 Some(decl_name) if decl_name.as_str() == lhs_span.as_str() =>
2550 "it".to_string(),
2551 Some(decl_name) => format!("\"{}\"", decl_name.as_str()),
2552 _ => "it".to_string(),
2553 },
2554 a_or_an(decl_friendly_type_name)
2555 )
2556 ),
2557 hints: vec![
2558 match decl_name {
2559 Some(decl_name) => Hint::info(
2560 source_engine,
2561 decl_name.span(),
2562 format!("{} \"{decl_name}\" is declared here.", ascii_sentence_case(&decl_friendly_type_name.to_string()))
2563 ),
2564 _ => Hint::none(),
2565 }
2566 ],
2567 help: vec![],
2568 },
2569 AssignmentViaNonMutableReference { decl_reference_name, decl_reference_rhs, decl_reference_type, span } => Diagnostic {
2570 reason: Some(Reason::new(code(1), "Reference is not a reference to a mutable value (`&mut`)".to_string())),
2571 issue: Issue::error(
2572 source_engine,
2573 span.clone(),
2574 format!("{} is not a reference to a mutable value (`&mut`).",
2578 match decl_reference_name {
2579 Some(decl_reference_name) => format!("Reference \"{decl_reference_name}\""),
2580 _ => "This reference expression".to_string(),
2581 }
2582 )
2583 ),
2584 hints: vec![
2585 match decl_reference_name {
2586 Some(decl_reference_name) => Hint::info(
2587 source_engine,
2588 decl_reference_name.span(),
2589 format!("Reference \"{decl_reference_name}\" is declared here as a reference to immutable value.")
2590 ),
2591 _ => Hint::none(),
2592 },
2593 match decl_reference_rhs {
2594 Some(decl_reference_rhs) => Hint::info(
2595 source_engine,
2596 decl_reference_rhs.clone(),
2597 format!("This expression has type \"{decl_reference_type}\" instead of \"&mut {}\".",
2598 &decl_reference_type[1..]
2599 )
2600 ),
2601 _ => Hint::info(
2602 source_engine,
2603 span.clone(),
2604 format!("It has type \"{decl_reference_type}\" instead of \"&mut {}\".",
2605 &decl_reference_type[1..]
2606 )
2607 ),
2608 },
2609 match decl_reference_rhs {
2610 Some(decl_reference_rhs) if decl_reference_rhs.as_str().starts_with('&') => Hint::help(
2611 source_engine,
2612 decl_reference_rhs.clone(),
2613 format!("Consider taking here a reference to a mutable value: `&mut {}`.",
2614 first_line(decl_reference_rhs.as_str()[1..].trim(), true)
2615 )
2616 ),
2617 _ => Hint::none(),
2618 },
2619 ],
2620 help: vec![
2621 format!("{} dereferenced in assignment targets must {} references to mutable values (`&mut`).",
2622 if decl_reference_name.is_some() {
2623 "References"
2624 } else {
2625 "Reference expressions"
2626 },
2627 if decl_reference_name.is_some() {
2628 "be"
2629 } else {
2630 "result in"
2631 }
2632 ),
2633 ],
2634 },
2635 Unimplemented { feature, help, span } => Diagnostic {
2636 reason: Some(Reason::new(code(1), "Used feature is currently not implemented".to_string())),
2637 issue: Issue::error(
2638 source_engine,
2639 span.clone(),
2640 format!("{feature} is currently not implemented.")
2641 ),
2642 hints: vec![],
2643 help: help.clone(),
2644 },
2645 MatchedValueIsNotValid { supported_types_message, span } => Diagnostic {
2646 reason: Some(Reason::new(code(1), "Matched value is not valid".to_string())),
2647 issue: Issue::error(
2648 source_engine,
2649 span.clone(),
2650 "This cannot be matched.".to_string()
2651 ),
2652 hints: vec![],
2653 help: {
2654 let mut help = vec![];
2655
2656 help.push("Matched value must be an expression whose result is of one of the types supported in pattern matching.".to_string());
2657 help.push(Diagnostic::help_empty_line());
2658 for msg in supported_types_message {
2659 help.push(msg.to_string());
2660 }
2661
2662 help
2663 }
2664 },
2665 TypeIsNotValidAsImplementingFor { invalid_type, trait_name, span } => Diagnostic {
2666 reason: Some(Reason::new(code(1), "Self type of an impl block is not valid".to_string())),
2667 issue: Issue::error(
2668 source_engine,
2669 span.clone(),
2670 format!("{invalid_type} is not a valid type in the self type of {} impl block.",
2671 match trait_name {
2672 Some(_) => "a trait",
2673 None => "an",
2674 }
2675 )
2676 ),
2677 hints: vec![
2678 if matches!(invalid_type, InvalidImplementingForType::SelfType) {
2679 Hint::help(
2680 source_engine,
2681 span.clone(),
2682 format!("Replace {invalid_type} with the actual type that you want to implement for.")
2683 )
2684 } else {
2685 Hint::none()
2686 }
2687 ],
2688 help: {
2689 if matches!(invalid_type, InvalidImplementingForType::Placeholder) {
2690 vec![
2691 format!("Are you trying to implement {} for any type?",
2692 match trait_name {
2693 Some(trait_name) => format!("trait \"{trait_name}\""),
2694 None => "functionality".to_string(),
2695 }
2696 ),
2697 Diagnostic::help_empty_line(),
2698 "If so, use generic type parameters instead.".to_string(),
2699 "E.g., instead of:".to_string(),
2700 format!("{}impl {}_",
2709 Indent::Single,
2710 match trait_name {
2711 Some(_) => "SomeTrait for ",
2712 None => "",
2713 }
2714 ),
2715 "use:".to_string(),
2716 format!("{}impl<T> {}T",
2717 Indent::Single,
2718 match trait_name {
2719 Some(_) => "SomeTrait for ",
2720 None => "",
2721 }
2722 ),
2723 ]
2724 } else {
2725 vec![]
2726 }
2727 }
2728 },
2729 ModulePathIsNotAnExpression { module_path, span } => Diagnostic {
2730 reason: Some(Reason::new(code(1), "Module path is not an expression".to_string())),
2731 issue: Issue::error(
2732 source_engine,
2733 span.clone(),
2734 "This is a module path, and not an expression.".to_string()
2735 ),
2736 hints: vec![
2737 Hint::help(
2738 source_engine,
2739 span.clone(),
2740 "An expression is expected at this location, but a module path is found.".to_string()
2741 ),
2742 ],
2743 help: vec![
2744 "In expressions, module paths can only be used to fully qualify names with a path.".to_string(),
2745 format!("E.g., `{module_path}::SOME_CONSTANT` or `{module_path}::some_function()`."),
2746 ]
2747 },
2748 Parse { error } => {
2749 match &error.kind {
2750 ParseErrorKind::MissingColonInEnumTypeField { variant_name, tuple_contents } => Diagnostic {
2751 reason: Some(Reason::new(code(1), "Enum variant declaration is not valid".to_string())),
2752 issue: Issue::error(
2753 source_engine,
2754 error.span.clone(),
2755 format!("`{}` is not a valid enum variant declaration.", error.span.as_str()),
2756 ),
2757 hints: vec![
2758 if let Some(tuple_contents) = tuple_contents {
2759 Hint::help(
2760 source_engine,
2761 error.span.clone(),
2762 format!("Did you mean `{}: ({})`?", variant_name, tuple_contents.as_str())
2763 )
2764 } else {
2765 Hint::none()
2766 }
2767 ],
2768 help: vec![
2769 "In Sway, enum variants are in the form `Variant: ()`, `Variant: <type>`, or `Variant: (<type1>, ..., <typeN>)`.".to_string(),
2770 "E.g., `Foo: (), `Bar: u64`, or `Bar: (bool, u32)`.".to_string(),
2771 ],
2772 },
2773 ParseErrorKind::UnassignableExpression { erroneous_expression_kind, erroneous_expression_span } => Diagnostic {
2774 reason: Some(Reason::new(code(1), "Expression cannot be assigned to".to_string())),
2775 issue: Issue::error(
2780 source_engine,
2781 error.span.clone(),
2782 format!("This expression cannot be assigned to, because it {} {}{}.",
2783 if &error.span == erroneous_expression_span { "is"
2785 } else {
2786 "contains"
2787 },
2788 if *erroneous_expression_kind == "parentheses" {
2789 ""
2790 } else {
2791 a_or_an(erroneous_expression_kind)
2792 },
2793 erroneous_expression_kind
2794 )
2795 ),
2796 hints: vec![
2797 if &error.span != erroneous_expression_span {
2798 Hint::info(
2799 source_engine,
2800 erroneous_expression_span.clone(),
2801 format!("{} the contained {erroneous_expression_kind}.",
2802 if *erroneous_expression_kind == "parentheses" {
2803 "These are"
2804 } else {
2805 "This is"
2806 }
2807 )
2808 )
2809 } else {
2810 Hint::none()
2811 },
2812 ],
2813 help: vec![
2814 format!("{} cannot be {}an assignment target.",
2815 ascii_sentence_case(&erroneous_expression_kind.to_string()),
2816 if &error.span == erroneous_expression_span {
2817 ""
2818 } else {
2819 "a part of "
2820 }
2821 ),
2822 Diagnostic::help_empty_line(),
2823 "In Sway, assignment targets must be one of the following:".to_string(),
2824 format!("{}- Expressions starting with a mutable variable, optionally having", Indent::Single),
2825 format!("{} array or tuple element accesses, struct field accesses,", Indent::Single),
2826 format!("{} or arbitrary combinations of those.", Indent::Single),
2827 format!("{} E.g., `mut_var` or `mut_struct.field` or `mut_array[x + y].field.1`.", Indent::Single),
2828 Diagnostic::help_empty_line(),
2829 format!("{}- Dereferencing of an arbitrary expression that results", Indent::Single),
2830 format!("{} in a reference to a mutable value.", Indent::Single),
2831 format!("{} E.g., `*ref_to_mutable_value` or `*max_mut(&mut x, &mut y)`.", Indent::Single),
2832 ]
2833 },
2834 ParseErrorKind::UnrecognizedOpCode { known_op_codes } => Diagnostic {
2835 reason: Some(Reason::new(code(1), "Assembly instruction is unknown".to_string())),
2836 issue: Issue::error(
2837 source_engine,
2838 error.span.clone(),
2839 format!("\"{}\" is not a known assembly instruction.",
2840 error.span.as_str()
2841 )
2842 ),
2843 hints: vec![did_you_mean_help(source_engine, error.span.clone(), known_op_codes.iter(), 2, Enclosing::DoubleQuote)],
2844 help: vec![]
2845 },
2846 _ => Diagnostic {
2847 issue: Issue::error(source_engine, self.span(), format!("{self}")),
2851 ..Default::default()
2852 },
2853 }
2854 },
2855 ConvertParseTree { error } => {
2856 match error {
2857 ConvertParseTreeError::InvalidAttributeTarget { span, attribute, target_friendly_name, can_only_annotate_help } => Diagnostic {
2858 reason: Some(Reason::new(code(1), match get_attribute_type(attribute) {
2859 AttributeType::InnerDocComment => "Inner doc comment (`//!`) cannot document item",
2860 AttributeType::OuterDocComment => "Outer doc comment (`///`) cannot document item",
2861 AttributeType::Attribute => "Attribute cannot annotate item",
2862 }.to_string())),
2863 issue: Issue::error(
2864 source_engine,
2865 span.clone(),
2866 match get_attribute_type(attribute) {
2867 AttributeType::InnerDocComment => format!("Inner doc comment (`//!`) cannot document {}{target_friendly_name}.", a_or_an(&target_friendly_name)),
2868 AttributeType::OuterDocComment => format!("Outer doc comment (`///`) cannot document {}{target_friendly_name}.", a_or_an(&target_friendly_name)),
2869 AttributeType::Attribute => format!("\"{attribute}\" attribute cannot annotate {}{target_friendly_name}.", a_or_an(&target_friendly_name)),
2870 }.to_string()
2871 ),
2872 hints: vec![],
2873 help: can_only_annotate_help.iter().map(|help| help.to_string()).collect(),
2874 },
2875 ConvertParseTreeError::InvalidAttributeMultiplicity { last_occurrence, previous_occurrences } => Diagnostic {
2876 reason: Some(Reason::new(code(1), "Attribute can be applied only once".to_string())),
2877 issue: Issue::error(
2878 source_engine,
2879 last_occurrence.span(),
2880 format!("\"{last_occurrence}\" attribute can be applied only once, but is applied {} times.", num_to_str(previous_occurrences.len() + 1))
2881 ),
2882 hints: {
2883 let (first_occurrence, other_occurrences) = previous_occurrences.split_first().expect("there is at least one previous occurrence in `previous_occurrences`");
2884 let mut hints = vec![Hint::info(source_engine, first_occurrence.span(), "It is already applied here.".to_string())];
2885 other_occurrences.iter().for_each(|occurrence| hints.push(Hint::info(source_engine, occurrence.span(), "And here.".to_string())));
2886 hints
2887 },
2888 help: vec![],
2889 },
2890 ConvertParseTreeError::InvalidAttributeArgsMultiplicity { span, attribute, args_multiplicity, num_of_args } => Diagnostic {
2891 reason: Some(Reason::new(code(1), "Number of attribute arguments is invalid".to_string())),
2892 issue: Issue::error(
2893 source_engine,
2894 span.clone(),
2895 format!("\"{attribute}\" attribute must {}, but has {}.", get_expected_attributes_args_multiplicity_msg(args_multiplicity), num_to_str_or_none(*num_of_args))
2896 ),
2897 hints: vec![],
2898 help: vec![],
2899 },
2900 ConvertParseTreeError::InvalidAttributeArg { attribute, arg, expected_args } => Diagnostic {
2901 reason: Some(Reason::new(code(1), "Attribute argument is invalid".to_string())),
2902 issue: Issue::error(
2903 source_engine,
2904 arg.span(),
2905 format!("\"{arg}\" is an invalid argument for attribute \"{attribute}\".")
2906 ),
2907 hints: {
2908 let mut hints = vec![did_you_mean_help(source_engine, arg.span(), expected_args, 2, Enclosing::DoubleQuote)];
2909 if expected_args.len() == 1 {
2910 hints.push(Hint::help(source_engine, arg.span(), format!("The only valid argument is \"{}\".", expected_args[0])));
2911 } else if expected_args.len() <= 3 {
2912 hints.push(Hint::help(source_engine, arg.span(), format!("Valid arguments are {}.", sequence_to_str(expected_args, Enclosing::DoubleQuote, usize::MAX))));
2913 } else {
2914 hints.push(Hint::help(source_engine, arg.span(), "Valid arguments are:".to_string()));
2915 hints.append(&mut Hint::multi_help(source_engine, &arg.span(), sequence_to_list(expected_args, Indent::Single, usize::MAX)))
2916 }
2917 hints
2918 },
2919 help: vec![],
2920 },
2921 ConvertParseTreeError::InvalidAttributeArgExpectsValue { attribute, arg, value_span } => Diagnostic {
2922 reason: Some(Reason::new(code(1), format!("Attribute argument must {}have a value",
2923 match value_span {
2924 Some(_) => "not ",
2925 None => "",
2926 }
2927 ))),
2928 issue: Issue::error(
2929 source_engine,
2930 arg.span(),
2931 format!("\"{arg}\" argument of the attribute \"{attribute}\" must {}have a value.",
2932 match value_span {
2933 Some(_) => "not ",
2934 None => "",
2935 }
2936 )
2937 ),
2938 hints: vec![
2939 match &value_span {
2940 Some(value_span) => Hint::help(source_engine, value_span.clone(), format!("Remove the value: `= {}`.", value_span.as_str())),
2941 None => Hint::help(source_engine, arg.span(), format!("To set the value, use the `=` operator: `{arg} = <value>`.")),
2942 }
2943 ],
2944 help: vec![],
2945 },
2946 ConvertParseTreeError::InvalidAttributeArgValueType { span, arg, expected_type, received_type } => Diagnostic {
2947 reason: Some(Reason::new(code(1), "Attribute argument value has a wrong type".to_string())),
2948 issue: Issue::error(
2949 source_engine,
2950 span.clone(),
2951 format!("\"{arg}\" argument must have a value of type \"{expected_type}\".")
2952 ),
2953 hints: vec![
2954 Hint::help(
2955 source_engine,
2956 span.clone(),
2957 format!("This value has type \"{received_type}\"."),
2958 )
2959 ],
2960 help: vec![],
2961 },
2962 ConvertParseTreeError::InvalidAttributeArgValue { span, arg, expected_values } => Diagnostic {
2963 reason: Some(Reason::new(code(1), "Attribute argument value is invalid".to_string())),
2964 issue: Issue::error(
2965 source_engine,
2966 span.clone(),
2967 format!("\"{}\" is an invalid value for argument \"{arg}\".", span.as_str())
2968 ),
2969 hints: {
2970 let mut hints = vec![did_you_mean_help(source_engine, span.clone(), expected_values, 2, Enclosing::DoubleQuote)];
2971 if expected_values.len() == 1 {
2972 hints.push(Hint::help(source_engine, span.clone(), format!("The only valid argument value is \"{}\".", expected_values[0])));
2973 } else if expected_values.len() <= 3 {
2974 hints.push(Hint::help(source_engine, span.clone(), format!("Valid argument values are {}.", sequence_to_str(expected_values, Enclosing::DoubleQuote, usize::MAX))));
2975 } else {
2976 hints.push(Hint::help(source_engine, span.clone(), "Valid argument values are:".to_string()));
2977 hints.append(&mut Hint::multi_help(source_engine, span, sequence_to_list(expected_values, Indent::Single, usize::MAX)))
2978 }
2979 hints
2980 },
2981 help: vec![],
2982 },
2983 _ => Diagnostic {
2984 issue: Issue::error(source_engine, self.span(), format!("{self}")),
2988 ..Default::default()
2989 },
2990 }
2991 }
2992 ConfigurableMissingAbiDecodeInPlace { span } => Diagnostic {
2993 reason: Some(Reason::new(code(1), "Configurables need a function named \"abi_decode_in_place\" to be in scope".to_string())),
2994 issue: Issue::error(
2995 source_engine,
2996 span.clone(),
2997 String::new()
2998 ),
2999 hints: vec![],
3000 help: vec![
3001 "The function \"abi_decode_in_place\" is usually defined in the standard library module \"std::codec\".".into(),
3002 "Verify that you are using a version of the \"std\" standard library that contains this function.".into(),
3003 ],
3004 },
3005 StorageAccessMismatched { span, is_pure, suggested_attributes, storage_access_violations } => Diagnostic {
3006 reason: Some(Reason::new(code(1), format!("{} function cannot {} storage",
3010 if *is_pure {
3011 "Pure"
3012 } else {
3013 "Storage read-only"
3014 },
3015 if *is_pure {
3016 "access"
3017 } else {
3018 "write to"
3019 }
3020 ))),
3021 issue: Issue::error(
3022 source_engine,
3023 span.clone(),
3024 format!("Function \"{}\" is {} and cannot {} storage.",
3025 span.as_str(),
3026 if *is_pure {
3027 "pure"
3028 } else {
3029 "declared as `#[storage(read)]`"
3030 },
3031 if *is_pure {
3032 "access"
3033 } else {
3034 "write to"
3035 },
3036 )
3037 ),
3038 hints: storage_access_violations
3039 .iter()
3040 .map(|(span, storage_access)| Hint::info(
3041 source_engine,
3042 span.clone(),
3043 format!("{storage_access}")
3044 ))
3045 .collect(),
3046 help: vec![
3047 format!("Consider declaring the function \"{}\" as `#[storage({suggested_attributes})]`,",
3048 span.as_str()
3049 ),
3050 format!("or removing the {} from the function body.",
3051 if *is_pure {
3052 "storage access code".to_string()
3053 } else {
3054 format!("storage write{}", plural_s(storage_access_violations.len()))
3055 }
3056 ),
3057 ],
3058 },
3059 MultipleImplsSatisfyingTraitForType { span, type_annotation , trait_names, trait_types_and_names: trait_types_and_spans } => Diagnostic {
3060 reason: Some(Reason::new(code(1), format!("Multiple impls satisfying {} for {}", trait_names.join("+"), type_annotation))),
3061 issue: Issue::error(
3062 source_engine,
3063 span.clone(),
3064 String::new()
3065 ),
3066 hints: vec![],
3067 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))|
3068 format!("#{} {} for {}", e, name, type_id.clone())
3069 ).collect::<Vec<_>>().join("\n"))],
3070 },
3071 MultipleContractsMethodsWithTheSameName { spans } => Diagnostic {
3072 reason: Some(Reason::new(code(1), "Multiple contracts methods with the same name.".into())),
3073 issue: Issue::error(
3074 source_engine,
3075 spans[0].clone(),
3076 "This is the first method".into()
3077 ),
3078 hints: spans.iter().skip(1).map(|span| {
3079 Hint::error(source_engine, span.clone(), "This is the duplicated method.".into())
3080 }).collect(),
3081 help: vec!["Contract methods names must be unique, even when implementing multiple ABIs.".into()],
3082 },
3083 FunctionSelectorClash { method_name, span, other_method_name, other_span } => Diagnostic {
3084 reason: Some(Reason::new(code(1), format!("Methods {method_name} and {other_method_name} have clashing function selectors."))),
3085 issue: Issue::error(
3086 source_engine,
3087 span.clone(),
3088 String::new()
3089 ),
3090 hints: vec![Hint::error(source_engine, other_span.clone(), format!("The declaration of {other_method_name} is here"))],
3091 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")]
3092 },
3093 ErrorTypeEnumHasNonErrorVariants { enum_name, non_error_variants } => Diagnostic {
3094 reason: Some(Reason::new(code(1), "Error type enum cannot have non-error variants".to_string())),
3095 issue: Issue::error(
3096 source_engine,
3097 enum_name.span(),
3098 format!("Error type enum \"{enum_name}\" has non-error variant{} {}.",
3099 plural_s(non_error_variants.len()),
3100 sequence_to_str(non_error_variants, Enclosing::DoubleQuote, 2)
3101 )
3102 ),
3103 hints: non_error_variants.iter().map(|variant| Hint::underscored_info(source_engine, variant.span())).collect(),
3104 help: vec![
3105 "All error type enum's variants must be marked as errors.".to_string(),
3106 "To mark error variants as errors, annotate them with the `#[error]` attribute.".to_string(),
3107 ]
3108 },
3109 ErrorAttributeInNonErrorEnum { enum_name, enum_variant_name } => Diagnostic {
3110 reason: Some(Reason::new(code(1), "Error enum variants must be in error type enums".to_string())),
3111 issue: Issue::error(
3112 source_engine,
3113 enum_variant_name.span(),
3114 format!("Enum variant \"{enum_variant_name}\" is marked as `#[error]`, but its enum is not an error type enum.")
3115 ),
3116 hints: vec![
3117 Hint::help(
3118 source_engine,
3119 enum_name.span(),
3120 format!("Consider annotating \"{enum_name}\" enum with the `#[error_type]` attribute."),
3121 )
3122 ],
3123 help: vec![
3124 "Enum variants can be marked as `#[error]` only if their parent enum is annotated with the `#[error_type]` attribute.".to_string(),
3125 ]
3126 },
3127 PanicExpressionArgumentIsNotError { argument_type, span } => Diagnostic {
3128 reason: Some(Reason::new(code(1), "Panic expression arguments must implement \"Error\" marker trait".into())),
3129 issue: Issue::error(
3130 source_engine,
3131 span.clone(),
3132 format!("This expression has type \"{argument_type}\", which does not implement \"std::marker::Error\" trait."),
3133 ),
3134 hints: vec![],
3135 help: {
3136 let mut help = vec![
3137 "Panic expression accepts only arguments that implement \"std::marker::Error\" trait.".to_string(),
3138 Diagnostic::help_empty_line(),
3139 ];
3140 help.append(&mut error_marker_trait_help_msg());
3141 help
3142 },
3143 },
3144 MaxNumOfPanicExpressionsReached { current, max_num, span } => Diagnostic {
3145 reason: Some(Reason::new(code(1), format!("Project contains more than {max_num} `panic` expressions"))),
3146 issue: Issue::error(
3147 source_engine,
3148 span.clone(),
3149 format!("This is the {current}{} `panic` expression occurred during the compilation.",
3150 ord_num_suffix(*current as usize)
3151 ),
3152 ),
3153 hints: vec![],
3154 help: vec![
3155 format!("Sway projects can have up to {max_num} `panic` expressions."),
3156 "In practice, this limit should never be reached, even for large Sway programs.".to_string(),
3157 Diagnostic::help_empty_line(),
3158 "Consider refactoring your code to reduce the number of `panic` expressions.".to_string(),
3159 ],
3160 },
3161 MaxNumOfPanickingCallsReached { current, max_num, span } => Diagnostic {
3162 reason: Some(Reason::new(code(1), format!("Project contains more than {max_num} panicking calls"))),
3163 issue: Issue::error(
3164 source_engine,
3165 span.clone(),
3166 format!("This is the {current}{} panicking call occurred during the compilation.",
3167 ord_num_suffix(*current as usize)
3168 ),
3169 ),
3170 hints: vec![],
3171 help: vec![
3172 format!("Sway projects can have up to {max_num} panicking calls."),
3173 "In practice, this limit should never be reached, even for large Sway programs.".to_string(),
3174 Diagnostic::help_empty_line(),
3175 "Consider compiling the project with the `backtrace` build option".to_string(),
3176 "set to `only_always` or `none`.".to_string(),
3177 ],
3178 },
3179 IncoherentImplDueToOrphanRule { trait_name, type_name, span } => Diagnostic {
3180 reason: Some(Reason::new(
3181 code(1),
3182 "coherence violation: only traits defined in this module can be implemented for external types".into()
3183 )),
3184 issue: Issue::error(
3185 source_engine,
3186 span.clone(),
3187 format!(
3188 "cannot implement `{trait_name}` for `{type_name}`: both originate outside this module"
3189 ),
3190 ),
3191 hints: vec![],
3192 help: {
3193 let help = vec![
3194 "only traits defined in this module can be implemented for external types".to_string(),
3195 Diagnostic::help_empty_line(),
3196 format!(
3197 "move this impl into the module that defines `{type_name}`"
3198 ),
3199 format!(
3200 "or define and use a local trait instead of `{trait_name}` to avoid the orphan rule"
3201 ),
3202 ];
3203 help
3204 },
3205 },
3206 ABIDuplicateName { span, other_span: other, is_attribute } => Diagnostic {
3207 reason: Some(Reason::new(code(1), "Duplicated name found for renamed ABI type".into())),
3208 issue: Issue::error(
3209 source_engine,
3210 span.clone(),
3211 String::new()
3212 ),
3213 hints: vec![
3214 Hint::help(
3215 source_engine,
3216 other.clone(),
3217 format!("This is the existing {} with conflicting name.", if *is_attribute { "attribute" } else { "type" }),
3218 )
3219 ],
3220 help: vec![],
3221 },
3222 ABIInvalidName { span, name } => Diagnostic {
3223 reason: Some(Reason::new(code(1), "Invalid name found for renamed ABI type.".into())),
3224 issue: Issue::error(
3225 source_engine,
3226 span.clone(),
3227 String::new()
3228 ),
3229 hints: vec![],
3230 help: vec![format!("The name must be a valid Sway identifier{}.", if name.is_empty() { " and cannot be empty" } else { "" })],
3231 },
3232 MultipleDefinitionsOfConstant { name, old, new } => {
3233 Diagnostic {
3234 reason: Some(Reason::new(code(1), "Multiple definitions of constant".into())),
3235 issue: Issue::error(
3236 source_engine,
3237 new.clone(),
3238 format!("Constant \"{name}\" was already defined"),
3239 ),
3240 hints: vec![
3241 Hint::error(
3242 source_engine,
3243 old.clone(),
3244 "Its first definition is here.".into(),
3245 ),
3246 ],
3247 help: vec![],
3248 }
3249 }
3250 MethodNotFound { called_method, expected_signature, type_name, matching_methods } => {
3251 Diagnostic {
3252 reason: Some(Reason::new(code(1), "Associated function or method is not found".into())),
3253 issue: Issue::error(
3254 source_engine,
3255 called_method.span(),
3256 format!("\"{expected_signature}\" is not found for type \"{type_name}\"."),
3257 ),
3258 hints: if matching_methods.is_empty() {
3259 vec![]
3260 } else {
3261 Hint::multi_help(
3262 source_engine,
3263 &called_method.span(),
3264 std::iter::once(
3265 format!("{} \"{called_method}\" function{} {} implemented for the type:",
3266 singular_plural(matching_methods.len(), "Only this", "These"),
3267 plural_s(matching_methods.len()),
3268 is_are(matching_methods.len()),
3269 )
3270 )
3271 .chain(matching_methods
3272 .iter()
3273 .map(|m| format!("- {m}"))
3274 )
3275 .chain(std::iter::once(
3276 format!("Did you mean to call {}?",
3277 singular_plural(matching_methods.len(), "that function", "one of those functions"),
3278 )
3279 ))
3280 .collect()
3281 )
3282 },
3283 help: vec![],
3284 }
3285 }
3286 _ => Diagnostic {
3287 issue: Issue::error(source_engine, self.span(), format!("{self}")),
3291 ..Default::default()
3292 }
3293 }
3294 }
3295}
3296
3297#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
3298pub enum TypeNotAllowedReason {
3299 #[error(
3300 "Returning a type containing `raw_slice` from `main()` is not allowed. \
3301 Consider converting it into a flat `raw_slice` first."
3302 )]
3303 NestedSliceReturnNotAllowedInMain,
3304
3305 #[error("The type \"{ty}\" is not allowed in storage.")]
3306 TypeNotAllowedInContractStorage { ty: String },
3307
3308 #[error("`str` or a type containing `str` on `main()` arguments is not allowed.")]
3309 StringSliceInMainParameters,
3310
3311 #[error("Returning `str` or a type containing `str` from `main()` is not allowed.")]
3312 StringSliceInMainReturn,
3313
3314 #[error("`str` or a type containing `str` on `configurables` is not allowed.")]
3315 StringSliceInConfigurables,
3316
3317 #[error("`str` or a type containing `str` on `const` is not allowed.")]
3318 StringSliceInConst,
3319
3320 #[error("slices or types containing slices on `const` are not allowed.")]
3321 SliceInConst,
3322
3323 #[error("references, pointers, slices, string slices or types containing any of these are not allowed.")]
3324 NotAllowedInTransmute,
3325}
3326
3327#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3328pub enum StructFieldUsageContext {
3329 StructInstantiation { struct_can_be_instantiated: bool },
3330 StorageDeclaration { struct_can_be_instantiated: bool },
3331 StorageAccess,
3332 PatternMatching { has_rest_pattern: bool },
3333 StructFieldAccess,
3334 }
3339
3340#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3341pub enum InvalidImplementingForType {
3342 SelfType,
3343 Placeholder,
3344 Other,
3345}
3346
3347impl fmt::Display for InvalidImplementingForType {
3348 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3349 match self {
3350 Self::SelfType => f.write_str("\"Self\""),
3351 Self::Placeholder => f.write_str("Placeholder `_`"),
3352 Self::Other => f.write_str("This"),
3353 }
3354 }
3355}
3356
3357#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3359pub enum ShadowingSource {
3360 Const,
3362 LetVar,
3364 PatternMatchingStructFieldVar,
3367}
3368
3369impl fmt::Display for ShadowingSource {
3370 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3371 match self {
3372 Self::Const => f.write_str("Constant"),
3373 Self::LetVar => f.write_str("Variable"),
3374 Self::PatternMatchingStructFieldVar => f.write_str("Pattern variable"),
3375 }
3376 }
3377}
3378
3379#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3383pub enum StorageAccess {
3384 Clear,
3385 ReadWord,
3386 ReadSlots,
3387 WriteWord,
3388 WriteSlots,
3389 ImpureFunctionCall(Span, bool, bool),
3393}
3394
3395impl StorageAccess {
3396 pub fn is_write(&self) -> bool {
3397 matches!(
3398 self,
3399 Self::Clear | Self::WriteWord | Self::WriteSlots | Self::ImpureFunctionCall(_, _, true)
3400 )
3401 }
3402}
3403
3404impl fmt::Display for StorageAccess {
3405 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3406 match self {
3407 Self::Clear => f.write_str("Clearing the storage happens here."),
3408 Self::ReadWord => f.write_str("Reading a word from the storage happens here."),
3409 Self::ReadSlots => f.write_str("Reading storage slots happens here."),
3410 Self::WriteWord => f.write_str("Writing a word to the storage happens here."),
3411 Self::WriteSlots => f.write_str("Writing to storage slots happens here."),
3412 Self::ImpureFunctionCall(call_path, reads, writes) => f.write_fmt(format_args!(
3413 "Function \"{}\" {} the storage.",
3414 short_name(call_path.as_str()),
3415 match (reads, writes) {
3416 (true, true) => "reads from and writes to",
3417 (true, false) => "reads from",
3418 (false, true) => "writes to",
3419 (false, false) => unreachable!(
3420 "Function \"{}\" is impure, so it must read from or write to the storage.",
3421 call_path.as_str()
3422 ),
3423 }
3424 )),
3425 }
3426 }
3427}
3428
3429fn marker_trait_name(marker_trait_full_name: &str) -> &str {
3437 const MARKER_TRAITS_MODULE: &str = "std::marker::";
3438 assert!(
3439 marker_trait_full_name.starts_with(MARKER_TRAITS_MODULE),
3440 "`marker_trait_full_name` must start with \"std::marker::\", but it was \"{marker_trait_full_name}\""
3441 );
3442
3443 let lower_boundary = MARKER_TRAITS_MODULE.len();
3444 let name_part = &marker_trait_full_name[lower_boundary..];
3445
3446 let upper_boundary = marker_trait_full_name.len() - lower_boundary;
3447 let only_name_len = std::cmp::min(
3448 name_part.find(':').unwrap_or(upper_boundary),
3449 name_part.find('<').unwrap_or(upper_boundary),
3450 );
3451 let upper_boundary = lower_boundary + only_name_len;
3452
3453 &marker_trait_full_name[lower_boundary..upper_boundary]
3454}
3455
3456fn error_marker_trait_help_msg() -> Vec<String> {
3457 vec![
3458 "\"Error\" marker trait is automatically implemented by the compiler for the unit type `()`,".to_string(),
3459 "string slices, and enums annotated with the `#[error_type]` attribute.".to_string(),
3460 ]
3461}