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