1use crate::convert_parse_tree_error::ConvertParseTreeError;
2use crate::diagnostic::{Code, Diagnostic, Hint, Issue, Reason, ToDiagnostic};
3use crate::formatting::*;
4use crate::lex_error::LexError;
5use crate::parser_error::{ParseError, ParseErrorKind};
6use crate::type_error::TypeError;
7
8use core::fmt;
9use std::fmt::Formatter;
10use sway_types::constants::STORAGE_PURITY_ATTRIBUTE_NAME;
11use sway_types::style::to_snake_case;
12use sway_types::{BaseIdent, Ident, IdentUnique, SourceEngine, Span, Spanned};
13use thiserror::Error;
14
15use self::ShadowingSource::*;
16use self::StructFieldUsageContext::*;
17
18#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
19pub enum InterfaceName {
20 Abi(Ident),
21 Trait(Ident),
22}
23
24impl fmt::Display for InterfaceName {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 match self {
27 InterfaceName::Abi(name) => write!(f, "ABI \"{name}\""),
28 InterfaceName::Trait(name) => write!(f, "trait \"{name}\""),
29 }
30 }
31}
32
33#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
52pub enum CompileError {
53 #[error("\"const generics\" are not supported here.")]
54 ConstGenericNotSupportedHere { span: Span },
55 #[error("This expression is not supported as lengths.")]
56 LengthExpressionNotSupported { span: Span },
57 #[error(
58 "This needs \"{feature}\" to be enabled, but it is currently disabled. For more details go to {url}."
59 )]
60 FeatureIsDisabled {
61 feature: String,
62 url: String,
63 span: Span,
64 },
65 #[error(
66 "There was an error while evaluating the evaluation order for the module dependency graph."
67 )]
68 ModuleDepGraphEvaluationError {},
69 #[error("A cyclic reference was found between the modules: {}.",
70 modules.iter().map(|ident| ident.as_str().to_string())
71 .collect::<Vec<_>>()
72 .join(", "))]
73 ModuleDepGraphCyclicReference { modules: Vec<BaseIdent> },
74
75 #[error("Variable \"{var_name}\" does not exist in this scope.")]
76 UnknownVariable { var_name: Ident, span: Span },
77 #[error("Identifier \"{name}\" was used as a variable, but it is actually a {what_it_is}.")]
78 NotAVariable {
79 name: Ident,
80 what_it_is: &'static str,
81 span: Span,
82 },
83 #[error("{feature} is currently not implemented.")]
84 Unimplemented {
85 feature: String,
90 help: Vec<String>,
94 span: Span,
95 },
96 #[error("{0}")]
97 TypeError(TypeError),
98 #[error("Error parsing input: {err:?}")]
99 ParseError { span: Span, err: String },
100 #[error(
101 "Internal compiler error: {0}\nPlease file an issue on the repository and include the \
102 code that triggered this error."
103 )]
104 Internal(&'static str, Span),
105 #[error(
106 "Internal compiler error: {0}\nPlease file an issue on the repository and include the \
107 code that triggered this error."
108 )]
109 InternalOwned(String, Span),
110 #[error(
111 "Predicate declaration contains no main function. Predicates require a main function."
112 )]
113 NoPredicateMainFunction(Span),
114 #[error("A predicate's main function must return a boolean.")]
115 PredicateMainDoesNotReturnBool(Span),
116 #[error("Script declaration contains no main function. Scripts require a main function.")]
117 NoScriptMainFunction(Span),
118 #[error("Fallback function already defined in scope.")]
119 MultipleDefinitionsOfFallbackFunction { name: Ident, span: Span },
120 #[error("Function \"{name}\" was already defined in scope.")]
121 MultipleDefinitionsOfFunction { name: Ident, span: Span },
122 #[error("Name \"{name}\" is defined multiple times.")]
123 MultipleDefinitionsOfName { name: Ident, span: Span },
124 #[error("Constant \"{name}\" was already defined in scope.")]
125 MultipleDefinitionsOfConstant { name: Ident, span: Span },
126 #[error("Type \"{name}\" was already defined in scope.")]
127 MultipleDefinitionsOfType { name: Ident, span: Span },
128 #[error("Variable \"{}\" is already defined in match arm.", first_definition.as_str())]
129 MultipleDefinitionsOfMatchArmVariable {
130 match_value: Span,
131 match_type: String,
132 first_definition: Span,
133 first_definition_is_struct_field: bool,
134 duplicate: Span,
135 duplicate_is_struct_field: bool,
136 },
137 #[error(
138 "Assignment to an immutable variable. Variable \"{decl_name} is not declared as mutable."
139 )]
140 AssignmentToNonMutableVariable {
141 decl_name: Ident,
143 lhs_span: Span,
145 },
146 #[error(
147 "Assignment to a {}. {} cannot be assigned to.",
148 if *is_configurable {
149 "configurable"
150 } else {
151 "constant"
152 },
153 if *is_configurable {
154 "Configurables"
155 } else {
156 "Constants"
157 }
158 )]
159 AssignmentToConstantOrConfigurable {
160 decl_name: Ident,
162 is_configurable: bool,
163 lhs_span: Span,
165 },
166 #[error(
167 "This assignment target cannot be assigned to, because {} is {}{decl_friendly_type_name} and not a mutable variable.",
168 if let Some(decl_name) = decl_name {
169 format!("\"{decl_name}\"")
170 } else {
171 "this".to_string()
172 },
173 a_or_an(decl_friendly_type_name)
174 )]
175 DeclAssignmentTargetCannotBeAssignedTo {
176 decl_name: Option<Ident>,
178 decl_friendly_type_name: &'static str,
180 lhs_span: Span,
182 },
183 #[error("This reference is not a reference to a mutable value (`&mut`).")]
184 AssignmentViaNonMutableReference {
185 decl_reference_name: Option<Ident>,
190 decl_reference_rhs: Option<Span>,
193 decl_reference_type: String,
196 span: Span,
197 },
198 #[error(
199 "Cannot call method \"{method_name}\" on variable \"{variable_name}\" because \
200 \"{variable_name}\" is not declared as mutable."
201 )]
202 MethodRequiresMutableSelf {
203 method_name: Ident,
204 variable_name: Ident,
205 span: Span,
206 },
207 #[error(
208 "This parameter was declared as mutable, which is not supported yet, did you mean to use ref mut?"
209 )]
210 MutableParameterNotSupported { param_name: Ident, span: Span },
211 #[error("Cannot pass immutable argument to mutable parameter.")]
212 ImmutableArgumentToMutableParameter { span: Span },
213 #[error("ref mut or mut parameter is not allowed for contract ABI function.")]
214 RefMutableNotAllowedInContractAbi { param_name: Ident, span: Span },
215 #[error("Reference to a mutable value cannot reference a constant.")]
216 RefMutCannotReferenceConstant {
217 constant: String,
222 span: Span,
223 },
224 #[error("Reference to a mutable value cannot reference an immutable variable.")]
225 RefMutCannotReferenceImmutableVariable {
226 decl_name: Ident,
228 span: Span,
229 },
230 #[error(
231 "Cannot call associated function \"{fn_name}\" as a method. Use associated function \
232 syntax instead."
233 )]
234 AssociatedFunctionCalledAsMethod { fn_name: Ident, span: Span },
235 #[error(
236 "Generic type \"{name}\" is not in scope. Perhaps you meant to specify type parameters in \
237 the function signature? For example: \n`fn \
238 {fn_name}<{comma_separated_generic_params}>({args}) -> ... `"
239 )]
240 TypeParameterNotInTypeScope {
241 name: Ident,
242 span: Span,
243 comma_separated_generic_params: String,
244 fn_name: Ident,
245 args: String,
246 },
247 #[error(
248 "expected: {expected} \n\
249 found: {given} \n\
250 help: The definition of this {decl_type} must \
251 match the one in the {interface_name} declaration."
252 )]
253 MismatchedTypeInInterfaceSurface {
254 interface_name: InterfaceName,
255 span: Span,
256 decl_type: String,
257 given: String,
258 expected: String,
259 },
260 #[error("Trait \"{name}\" cannot be found in the current scope.")]
261 UnknownTrait { span: Span, name: Ident },
262 #[error("Function \"{name}\" is not a part of {interface_name}'s interface surface.")]
263 FunctionNotAPartOfInterfaceSurface {
264 name: Ident,
265 interface_name: InterfaceName,
266 span: Span,
267 },
268 #[error("Constant \"{name}\" is not a part of {interface_name}'s interface surface.")]
269 ConstantNotAPartOfInterfaceSurface {
270 name: Ident,
271 interface_name: InterfaceName,
272 span: Span,
273 },
274 #[error("Type \"{name}\" is not a part of {interface_name}'s interface surface.")]
275 TypeNotAPartOfInterfaceSurface {
276 name: Ident,
277 interface_name: InterfaceName,
278 span: Span,
279 },
280 #[error("Constants are missing from this trait implementation: {}",
281 missing_constants.iter().map(|ident| ident.as_str().to_string())
282 .collect::<Vec<_>>()
283 .join("\n"))]
284 MissingInterfaceSurfaceConstants {
285 missing_constants: Vec<BaseIdent>,
286 span: Span,
287 },
288 #[error("Associated types are missing from this trait implementation: {}",
289 missing_types.iter().map(|ident| ident.as_str().to_string())
290 .collect::<Vec<_>>()
291 .join("\n"))]
292 MissingInterfaceSurfaceTypes {
293 missing_types: Vec<BaseIdent>,
294 span: Span,
295 },
296 #[error("Functions are missing from this trait implementation: {}",
297 missing_functions.iter().map(|ident| ident.as_str().to_string())
298 .collect::<Vec<_>>()
299 .join("\n"))]
300 MissingInterfaceSurfaceMethods {
301 missing_functions: Vec<BaseIdent>,
302 span: Span,
303 },
304 #[error("Expected {} type {} for \"{name}\", but instead found {}.", expected, if *expected == 1usize { "argument" } else { "arguments" }, given)]
305 IncorrectNumberOfTypeArguments {
306 name: Ident,
307 given: usize,
308 expected: usize,
309 span: Span,
310 },
311 #[error("\"{name}\" does not take type arguments.")]
312 DoesNotTakeTypeArguments { name: Ident, span: Span },
313 #[error("\"{name}\" does not take type arguments as prefix.")]
314 DoesNotTakeTypeArgumentsAsPrefix { name: Ident, span: Span },
315 #[error("Type arguments are not allowed for this type.")]
316 TypeArgumentsNotAllowed { span: Span },
317 #[error("\"{name}\" needs type arguments.")]
318 NeedsTypeArguments { name: Ident, span: Span },
319 #[error(
320 "Enum with name \"{name}\" could not be found in this scope. Perhaps you need to import \
321 it?"
322 )]
323 EnumNotFound { name: Ident, span: Span },
324 #[error("Instantiation of the struct \"{struct_name}\" is missing field \"{field_name}\".")]
329 StructInstantiationMissingFieldForErrorRecovery {
330 field_name: Ident,
331 struct_name: Ident,
333 span: Span,
334 },
335 #[error("Instantiation of the struct \"{struct_name}\" is missing {} {}.",
336 if field_names.len() == 1 { "field" } else { "fields" },
337 field_names.iter().map(|name| format!("\"{name}\"")).collect::<Vec::<_>>().join(", "))]
338 StructInstantiationMissingFields {
339 field_names: Vec<Ident>,
340 struct_name: Ident,
342 span: Span,
343 struct_decl_span: Span,
344 total_number_of_fields: usize,
345 },
346 #[error("Struct \"{struct_name}\" cannot be instantiated here because it has private fields.")]
347 StructCannotBeInstantiated {
348 struct_name: Ident,
350 span: Span,
351 struct_decl_span: Span,
352 private_fields: Vec<Ident>,
353 constructors: Vec<String>,
357 all_fields_are_private: bool,
359 is_in_storage_declaration: bool,
360 struct_can_be_changed: bool,
361 },
362 #[error("Field \"{field_name}\" of the struct \"{struct_name}\" is private.")]
363 StructFieldIsPrivate {
364 field_name: IdentUnique,
365 struct_name: Ident,
367 field_decl_span: Span,
368 struct_can_be_changed: bool,
369 usage_context: StructFieldUsageContext,
370 },
371 #[error("Field \"{field_name}\" does not exist in struct \"{struct_name}\".")]
372 StructFieldDoesNotExist {
373 field_name: IdentUnique,
374 available_fields: Vec<Ident>,
376 is_public_struct_access: bool,
377 struct_name: Ident,
379 struct_decl_span: Span,
380 struct_is_empty: bool,
381 usage_context: StructFieldUsageContext,
382 },
383 #[error("Field \"{field_name}\" has multiple definitions.")]
384 StructFieldDuplicated { field_name: Ident, duplicate: Ident },
385 #[error("No method \"{method}\" found for type \"{type_name}\".{}",
386 if matching_method_strings.is_empty() {
387 "".to_string()
388 } else {
389 format!(" \nMatching method{}:\n{}", if matching_method_strings.len()> 1 {"s"} else {""},
390 matching_method_strings.iter().map(|m| format!(" {m}")).collect::<Vec<_>>().join("\n"))
391 }
392 )]
393 MethodNotFound {
394 method: String,
395 type_name: String,
396 matching_method_strings: Vec<String>,
397 span: Span,
398 },
399 #[error("Module \"{name}\" could not be found.")]
400 ModuleNotFound { span: Span, name: String },
401 #[error("This expression has type \"{actually}\", which is not a struct. Fields can only be accessed on structs.")]
402 FieldAccessOnNonStruct {
403 actually: String,
404 storage_variable: Option<String>,
407 field_name: IdentUnique,
409 span: Span,
410 },
411 #[error("This expression has type \"{actually}\", which is not a tuple. Elements can only be accessed on tuples.")]
412 TupleElementAccessOnNonTuple {
413 actually: String,
414 span: Span,
415 index: usize,
416 index_span: Span,
417 },
418 #[error("This expression has type \"{actually}\", which is not an indexable type.")]
419 NotIndexable { actually: String, span: Span },
420 #[error("\"{name}\" is a {actually}, not an enum.")]
421 NotAnEnum {
422 name: String,
423 span: Span,
424 actually: String,
425 },
426 #[error("This is a {actually}, not a struct.")]
427 NotAStruct { span: Span, actually: String },
428 #[error("This is a {actually}, not an enum.")]
429 DeclIsNotAnEnum { actually: String, span: Span },
430 #[error("This is a {actually}, not a struct.")]
431 DeclIsNotAStruct { actually: String, span: Span },
432 #[error("This is a {actually}, not a function.")]
433 DeclIsNotAFunction { actually: String, span: Span },
434 #[error("This is a {actually}, not a variable.")]
435 DeclIsNotAVariable { actually: String, span: Span },
436 #[error("This is a {actually}, not an ABI.")]
437 DeclIsNotAnAbi { actually: String, span: Span },
438 #[error("This is a {actually}, not a trait.")]
439 DeclIsNotATrait { actually: String, span: Span },
440 #[error("This is a {actually}, not an impl block.")]
441 DeclIsNotAnImplTrait { actually: String, span: Span },
442 #[error("This is a {actually}, not a trait function.")]
443 DeclIsNotATraitFn { actually: String, span: Span },
444 #[error("This is a {actually}, not storage.")]
445 DeclIsNotStorage { actually: String, span: Span },
446 #[error("This is a {actually}, not a constant")]
447 DeclIsNotAConstant { actually: String, span: Span },
448 #[error("This is a {actually}, not a type alias")]
449 DeclIsNotATypeAlias { actually: String, span: Span },
450 #[error("Could not find symbol \"{name}\" in this scope.")]
451 SymbolNotFound { name: Ident, span: Span },
452 #[error("Found multiple bindings for \"{name}\" in this scope.")]
453 SymbolWithMultipleBindings {
454 name: Ident,
455 paths: Vec<String>,
456 span: Span,
457 },
458 #[error("Symbol \"{name}\" is private.")]
459 ImportPrivateSymbol { name: Ident, span: Span },
460 #[error("Module \"{name}\" is private.")]
461 ImportPrivateModule { name: Ident, span: Span },
462 #[error(
463 "Because this if expression's value is used, an \"else\" branch is required and it must \
464 return type \"{r#type}\""
465 )]
466 NoElseBranch { span: Span, r#type: String },
467 #[error(
468 "Symbol \"{name}\" does not refer to a type, it refers to a {actually_is}. It cannot be \
469 used in this position."
470 )]
471 NotAType {
472 span: Span,
473 name: String,
474 actually_is: &'static str,
475 },
476 #[error(
477 "This enum variant requires an instantiation expression. Try initializing it with \
478 arguments in parentheses."
479 )]
480 MissingEnumInstantiator { span: Span },
481 #[error(
482 "This path must return a value of type \"{ty}\" from function \"{function_name}\", but it \
483 does not."
484 )]
485 PathDoesNotReturn {
486 span: Span,
487 ty: String,
488 function_name: Ident,
489 },
490 #[error(
491 "Expected Module level doc comment. All other attributes are unsupported at this level."
492 )]
493 ExpectedModuleDocComment { span: Span },
494 #[error(
495 "This register was not initialized in the initialization section of the ASM expression. \
496 Initialized registers are: {initialized_registers}"
497 )]
498 UnknownRegister {
499 span: Span,
500 initialized_registers: String,
501 },
502 #[error("This opcode takes an immediate value but none was provided.")]
503 MissingImmediate { span: Span },
504 #[error("This immediate value is invalid.")]
505 InvalidImmediateValue { span: Span },
506 #[error("Variant \"{variant_name}\" does not exist on enum \"{enum_name}\"")]
507 UnknownEnumVariant {
508 enum_name: Ident,
509 variant_name: Ident,
510 span: Span,
511 },
512 #[error("Unknown opcode: \"{op_name}\".")]
513 UnrecognizedOp { op_name: Ident, span: Span },
514 #[error("Cannot infer type for type parameter \"{ty}\". Insufficient type information provided. Try annotating its type.")]
515 UnableToInferGeneric { ty: String, span: Span },
516 #[error("The generic type parameter \"{ty}\" is unconstrained.")]
517 UnconstrainedGenericParameter { ty: String, span: Span },
518 #[error("Trait \"{trait_name}\" is not implemented for type \"{ty}\".")]
519 TraitConstraintNotSatisfied {
520 type_id: usize, ty: String,
522 trait_name: String,
523 span: Span,
524 },
525 #[error(
526 "Expects trait constraint \"{param}: {trait_name}\" which is missing from type parameter \"{param}\"."
527 )]
528 TraitConstraintMissing {
529 param: String,
530 trait_name: String,
531 span: Span,
532 },
533 #[error("The value \"{val}\" is too large to fit in this 6-bit immediate spot.")]
534 Immediate06TooLarge { val: u64, span: Span },
535 #[error("The value \"{val}\" is too large to fit in this 12-bit immediate spot.")]
536 Immediate12TooLarge { val: u64, span: Span },
537 #[error("The value \"{val}\" is too large to fit in this 18-bit immediate spot.")]
538 Immediate18TooLarge { val: u64, span: Span },
539 #[error("The value \"{val}\" is too large to fit in this 24-bit immediate spot.")]
540 Immediate24TooLarge { val: u64, span: Span },
541 #[error(
542 "This op expects {expected} register(s) as arguments, but you provided {received} register(s)."
543 )]
544 IncorrectNumberOfAsmRegisters {
545 span: Span,
546 expected: usize,
547 received: usize,
548 },
549 #[error("This op does not take an immediate value.")]
550 UnnecessaryImmediate { span: Span },
551 #[error("This reference is ambiguous, and could refer to a module, enum, or function of the same name. Try qualifying the name with a path.")]
552 AmbiguousPath { span: Span },
553 #[error("This is a module path, and not an expression.")]
554 ModulePathIsNotAnExpression { module_path: String, span: Span },
555 #[error("Unknown type name.")]
556 UnknownType { span: Span },
557 #[error("Unknown type name \"{name}\".")]
558 UnknownTypeName { name: String, span: Span },
559 #[error("The file {file_path} could not be read: {stringified_error}")]
560 FileCouldNotBeRead {
561 span: Span,
562 file_path: String,
563 stringified_error: String,
564 },
565 #[error("This imported file must be a library. It must start with \"library;\"")]
566 ImportMustBeLibrary { span: Span },
567 #[error("An enum instantiaton cannot contain more than one value. This should be a single value of type {ty}.")]
568 MoreThanOneEnumInstantiator { span: Span, ty: String },
569 #[error("This enum variant represents the unit type, so it should not be instantiated with any value.")]
570 UnnecessaryEnumInstantiator { span: Span },
571 #[error("The enum variant `{ty}` is of type `unit`, so its constructor does not take arguments or parentheses. Try removing the ().")]
572 UnitVariantWithParenthesesEnumInstantiator { span: Span, ty: String },
573 #[error("Cannot find trait \"{name}\" in this scope.")]
574 TraitNotFound { name: String, span: Span },
575 #[error("Trait \"{trait_name}\" is not imported when calling \"{function_name}\".\nThe import is needed because \"{function_name}\" uses \"{trait_name}\" in one of its trait constraints.")]
576 TraitNotImportedAtFunctionApplication {
577 trait_name: String,
578 function_name: String,
579 function_call_site_span: Span,
580 trait_constraint_span: Span,
581 trait_candidates: Vec<String>,
582 },
583 #[error("This expression is not valid on the left hand side of a reassignment.")]
584 InvalidExpressionOnLhs { span: Span },
585 #[error("This code cannot be evaluated to a constant")]
586 CannotBeEvaluatedToConst { span: Span },
587 #[error(
588 "This code cannot be evaluated to a configurable because its size is not always limited."
589 )]
590 CannotBeEvaluatedToConfigurableSizeUnknown { span: Span },
591 #[error("{} \"{method_name}\" expects {expected} {} but you provided {received}.",
592 if *dot_syntax_used { "Method" } else { "Function" },
593 if *expected == 1usize { "argument" } else {"arguments"},
594 )]
595 TooManyArgumentsForFunction {
596 span: Span,
597 method_name: Ident,
598 dot_syntax_used: bool,
599 expected: usize,
600 received: usize,
601 },
602 #[error("{} \"{method_name}\" expects {expected} {} but you provided {received}.",
603 if *dot_syntax_used { "Method" } else { "Function" },
604 if *expected == 1usize { "argument" } else {"arguments"},
605 )]
606 TooFewArgumentsForFunction {
607 span: Span,
608 method_name: Ident,
609 dot_syntax_used: bool,
610 expected: usize,
611 received: usize,
612 },
613 #[error("The function \"{method_name}\" was called without parentheses. Try adding ().")]
614 MissingParenthesesForFunction { span: Span, method_name: Ident },
615 #[error("This type is invalid in a function selector. A contract ABI function selector must be a known sized type, not generic.")]
616 InvalidAbiType { span: Span },
617 #[error("This is a {actually_is}, not an ABI. An ABI cast requires a valid ABI to cast the address to.")]
618 NotAnAbi {
619 span: Span,
620 actually_is: &'static str,
621 },
622 #[error("An ABI can only be implemented for the `Contract` type, so this implementation of an ABI for type \"{ty}\" is invalid.")]
623 ImplAbiForNonContract { span: Span, ty: String },
624 #[error("Conflicting implementations of trait \"{trait_name}\" for type \"{type_implementing_for}\".")]
625 ConflictingImplsForTraitAndType {
626 trait_name: String,
627 type_implementing_for: String,
628 type_implementing_for_unaliased: String,
629 existing_impl_span: Span,
630 second_impl_span: Span,
631 },
632 #[error(
633 "\"{marker_trait_full_name}\" is a marker trait and cannot be explicitly implemented."
634 )]
635 MarkerTraitExplicitlyImplemented {
636 marker_trait_full_name: String,
637 span: Span,
638 },
639 #[error("Duplicate definitions for the {decl_kind} \"{decl_name}\" for type \"{type_implementing_for}\".")]
640 DuplicateDeclDefinedForType {
641 decl_kind: String,
642 decl_name: String,
643 type_implementing_for: String,
644 type_implementing_for_unaliased: String,
645 existing_impl_span: Span,
646 second_impl_span: Span,
647 },
648 #[error("The function \"{fn_name}\" in {interface_name} is defined with {num_parameters} parameters, but the provided implementation has {provided_parameters} parameters.")]
649 IncorrectNumberOfInterfaceSurfaceFunctionParameters {
650 fn_name: Ident,
651 interface_name: InterfaceName,
652 num_parameters: usize,
653 provided_parameters: usize,
654 span: Span,
655 },
656 #[error("This parameter was declared as type {should_be}, but argument of type {provided} was provided.")]
657 ArgumentParameterTypeMismatch {
658 span: Span,
659 should_be: String,
660 provided: String,
661 },
662 #[error("Function {fn_name} is recursive, which is unsupported at this time.")]
663 RecursiveCall { fn_name: Ident, span: Span },
664 #[error(
665 "Function {fn_name} is recursive via {call_chain}, which is unsupported at this time."
666 )]
667 RecursiveCallChain {
668 fn_name: Ident,
669 call_chain: String, 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_PURITY_ATTRIBUTE_NAME}\" annotation must be \
819 removed, or the trait declaration must be changed to \
820 \"#[{STORAGE_PURITY_ATTRIBUTE_NAME}({attrs})]\"."
821 )]
822 TraitDeclPureImplImpure {
823 fn_name: Ident,
824 interface_name: InterfaceName,
825 attrs: String,
826 span: Span,
827 },
828 #[error(
829 "Storage attribute access mismatch. The function \"{fn_name}\" in \
830 {interface_name} requires the storage attribute(s) #[{STORAGE_PURITY_ATTRIBUTE_NAME}({attrs})]."
831 )]
832 TraitImplPurityMismatch {
833 fn_name: Ident,
834 interface_name: InterfaceName,
835 attrs: String,
836 span: Span,
837 },
838 #[error("Impure function inside of non-contract. Contract storage is only accessible from contracts.")]
839 ImpureInNonContract { span: Span },
840 #[error(
841 "This function performs storage access but does not have the required storage \
842 attribute(s). Try adding \"#[{STORAGE_PURITY_ATTRIBUTE_NAME}({suggested_attributes})]\" to the function \
843 declaration."
844 )]
845 StorageAccessMismatched {
846 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} arguments")]
923 IntrinsicIncorrectNumArgs {
924 name: String,
925 expected: u64,
926 span: Span,
927 },
928 #[error("Call to \"{name}\" expects {expected} type arguments")]
929 IntrinsicIncorrectNumTArgs {
930 name: String,
931 expected: u64,
932 span: Span,
933 },
934 #[error("Expected string literal")]
935 ExpectedStringLiteral { span: Span },
936 #[error("\"break\" used outside of a loop")]
937 BreakOutsideLoop { span: Span },
938 #[error("\"continue\" used outside of a loop")]
939 ContinueOutsideLoop { span: Span },
940 #[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("Collision detected between two different types.\n Shared hash:{hash}\n First type:{first_type}\n Second type:{second_type}")]
1050 ABIHashCollision {
1051 span: Span,
1052 hash: String,
1053 first_type: String,
1054 second_type: String,
1055 },
1056 #[error("Type must be known at this point")]
1057 TypeMustBeKnownAtThisPoint { span: Span, internal: String },
1058 #[error("Multiple impls satisfying trait for type.")]
1059 MultipleImplsSatisfyingTraitForType {
1060 span: Span,
1061 type_annotation: String,
1062 trait_names: Vec<String>,
1063 trait_types_and_names: Vec<(String, String)>,
1064 },
1065 #[error("Multiple contracts methods with the same name.")]
1066 MultipleContractsMethodsWithTheSameName { spans: Vec<Span> },
1067}
1068
1069impl std::convert::From<TypeError> for CompileError {
1070 fn from(other: TypeError) -> CompileError {
1071 CompileError::TypeError(other)
1072 }
1073}
1074
1075impl Spanned for CompileError {
1076 fn span(&self) -> Span {
1077 use CompileError::*;
1078 match self {
1079 ConstGenericNotSupportedHere { span } => span.clone(),
1080 LengthExpressionNotSupported { span } => span.clone(),
1081 FeatureIsDisabled { span, .. } => span.clone(),
1082 ModuleDepGraphEvaluationError { .. } => Span::dummy(),
1083 ModuleDepGraphCyclicReference { .. } => Span::dummy(),
1084 UnknownVariable { span, .. } => span.clone(),
1085 NotAVariable { span, .. } => span.clone(),
1086 Unimplemented { span, .. } => span.clone(),
1087 TypeError(err) => err.span(),
1088 ParseError { span, .. } => span.clone(),
1089 Internal(_, span) => span.clone(),
1090 InternalOwned(_, span) => span.clone(),
1091 NoPredicateMainFunction(span) => span.clone(),
1092 PredicateMainDoesNotReturnBool(span) => span.clone(),
1093 NoScriptMainFunction(span) => span.clone(),
1094 MultipleDefinitionsOfFunction { span, .. } => span.clone(),
1095 MultipleDefinitionsOfName { span, .. } => span.clone(),
1096 MultipleDefinitionsOfConstant { span, .. } => span.clone(),
1097 MultipleDefinitionsOfType { span, .. } => span.clone(),
1098 MultipleDefinitionsOfMatchArmVariable { duplicate, .. } => duplicate.clone(),
1099 MultipleDefinitionsOfFallbackFunction { span, .. } => span.clone(),
1100 AssignmentToNonMutableVariable { lhs_span, .. } => lhs_span.clone(),
1101 AssignmentToConstantOrConfigurable { lhs_span, .. } => lhs_span.clone(),
1102 DeclAssignmentTargetCannotBeAssignedTo { lhs_span, .. } => lhs_span.clone(),
1103 AssignmentViaNonMutableReference { span, .. } => span.clone(),
1104 MutableParameterNotSupported { span, .. } => span.clone(),
1105 ImmutableArgumentToMutableParameter { span } => span.clone(),
1106 RefMutableNotAllowedInContractAbi { span, .. } => span.clone(),
1107 RefMutCannotReferenceConstant { span, .. } => span.clone(),
1108 RefMutCannotReferenceImmutableVariable { span, .. } => span.clone(),
1109 MethodRequiresMutableSelf { span, .. } => span.clone(),
1110 AssociatedFunctionCalledAsMethod { span, .. } => span.clone(),
1111 TypeParameterNotInTypeScope { span, .. } => span.clone(),
1112 MismatchedTypeInInterfaceSurface { span, .. } => span.clone(),
1113 UnknownTrait { span, .. } => span.clone(),
1114 FunctionNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1115 ConstantNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1116 TypeNotAPartOfInterfaceSurface { span, .. } => span.clone(),
1117 MissingInterfaceSurfaceConstants { span, .. } => span.clone(),
1118 MissingInterfaceSurfaceTypes { span, .. } => span.clone(),
1119 MissingInterfaceSurfaceMethods { span, .. } => span.clone(),
1120 IncorrectNumberOfTypeArguments { span, .. } => span.clone(),
1121 DoesNotTakeTypeArguments { span, .. } => span.clone(),
1122 DoesNotTakeTypeArgumentsAsPrefix { span, .. } => span.clone(),
1123 TypeArgumentsNotAllowed { span } => span.clone(),
1124 NeedsTypeArguments { span, .. } => span.clone(),
1125 StructInstantiationMissingFieldForErrorRecovery { span, .. } => span.clone(),
1126 StructInstantiationMissingFields { span, .. } => span.clone(),
1127 StructCannotBeInstantiated { span, .. } => span.clone(),
1128 StructFieldIsPrivate { field_name, .. } => field_name.span(),
1129 StructFieldDoesNotExist { field_name, .. } => field_name.span(),
1130 StructFieldDuplicated { field_name, .. } => field_name.span(),
1131 MethodNotFound { span, .. } => span.clone(),
1132 ModuleNotFound { span, .. } => span.clone(),
1133 TupleElementAccessOnNonTuple { span, .. } => span.clone(),
1134 NotAStruct { span, .. } => span.clone(),
1135 NotIndexable { span, .. } => span.clone(),
1136 FieldAccessOnNonStruct { span, .. } => span.clone(),
1137 SymbolNotFound { span, .. } => span.clone(),
1138 SymbolWithMultipleBindings { span, .. } => span.clone(),
1139 ImportPrivateSymbol { span, .. } => span.clone(),
1140 ImportPrivateModule { span, .. } => span.clone(),
1141 NoElseBranch { span, .. } => span.clone(),
1142 NotAType { span, .. } => span.clone(),
1143 MissingEnumInstantiator { span, .. } => span.clone(),
1144 PathDoesNotReturn { span, .. } => span.clone(),
1145 ExpectedModuleDocComment { span } => span.clone(),
1146 UnknownRegister { span, .. } => span.clone(),
1147 MissingImmediate { span, .. } => span.clone(),
1148 InvalidImmediateValue { span, .. } => span.clone(),
1149 UnknownEnumVariant { span, .. } => span.clone(),
1150 UnrecognizedOp { span, .. } => span.clone(),
1151 UnableToInferGeneric { span, .. } => span.clone(),
1152 UnconstrainedGenericParameter { span, .. } => span.clone(),
1153 TraitConstraintNotSatisfied { span, .. } => span.clone(),
1154 TraitConstraintMissing { span, .. } => span.clone(),
1155 Immediate06TooLarge { span, .. } => span.clone(),
1156 Immediate12TooLarge { span, .. } => span.clone(),
1157 Immediate18TooLarge { span, .. } => span.clone(),
1158 Immediate24TooLarge { span, .. } => span.clone(),
1159 IncorrectNumberOfAsmRegisters { span, .. } => span.clone(),
1160 UnnecessaryImmediate { span, .. } => span.clone(),
1161 AmbiguousPath { span } => span.clone(),
1162 ModulePathIsNotAnExpression { span, .. } => span.clone(),
1163 UnknownType { span, .. } => span.clone(),
1164 UnknownTypeName { span, .. } => span.clone(),
1165 FileCouldNotBeRead { span, .. } => span.clone(),
1166 ImportMustBeLibrary { span, .. } => span.clone(),
1167 MoreThanOneEnumInstantiator { span, .. } => span.clone(),
1168 UnnecessaryEnumInstantiator { span, .. } => span.clone(),
1169 UnitVariantWithParenthesesEnumInstantiator { span, .. } => span.clone(),
1170 TraitNotFound { span, .. } => span.clone(),
1171 TraitNotImportedAtFunctionApplication {
1172 function_call_site_span,
1173 ..
1174 } => function_call_site_span.clone(),
1175 InvalidExpressionOnLhs { span, .. } => span.clone(),
1176 TooManyArgumentsForFunction { span, .. } => span.clone(),
1177 TooFewArgumentsForFunction { span, .. } => span.clone(),
1178 MissingParenthesesForFunction { span, .. } => span.clone(),
1179 InvalidAbiType { span, .. } => span.clone(),
1180 NotAnAbi { span, .. } => span.clone(),
1181 ImplAbiForNonContract { span, .. } => span.clone(),
1182 ConflictingImplsForTraitAndType {
1183 second_impl_span, ..
1184 } => second_impl_span.clone(),
1185 MarkerTraitExplicitlyImplemented { span, .. } => span.clone(),
1186 DuplicateDeclDefinedForType {
1187 second_impl_span, ..
1188 } => second_impl_span.clone(),
1189 IncorrectNumberOfInterfaceSurfaceFunctionParameters { span, .. } => span.clone(),
1190 ArgumentParameterTypeMismatch { span, .. } => span.clone(),
1191 RecursiveCall { span, .. } => span.clone(),
1192 RecursiveCallChain { span, .. } => span.clone(),
1193 RecursiveType { span, .. } => span.clone(),
1194 RecursiveTypeChain { span, .. } => span.clone(),
1195 GMFromExternalContext { span, .. } => span.clone(),
1196 MintFromExternalContext { span, .. } => span.clone(),
1197 BurnFromExternalContext { span, .. } => span.clone(),
1198 ContractStorageFromExternalContext { span, .. } => span.clone(),
1199 InvalidOpcodeFromPredicate { span, .. } => span.clone(),
1200 ArrayOutOfBounds { span, .. } => span.clone(),
1201 ConstantRequiresExpression { span, .. } => span.clone(),
1202 ConstantsCannotBeShadowed { name, .. } => name.span(),
1203 ConfigurablesCannotBeShadowed { name, .. } => name.span(),
1204 ConfigurablesCannotBeMatchedAgainst { name, .. } => name.span(),
1205 ConstantShadowsVariable { name, .. } => name.span(),
1206 ConstantDuplicatesConstantOrConfigurable { name, .. } => name.span(),
1207 ShadowsOtherSymbol { name } => name.span(),
1208 GenericShadowsGeneric { name } => name.span(),
1209 MatchExpressionNonExhaustive { span, .. } => span.clone(),
1210 MatchStructPatternMissingFields { span, .. } => span.clone(),
1211 MatchStructPatternMustIgnorePrivateFields { span, .. } => span.clone(),
1212 MatchArmVariableNotDefinedInAllAlternatives { variable, .. } => variable.span(),
1213 MatchArmVariableMismatchedType { variable, .. } => variable.span(),
1214 MatchedValueIsNotValid { span, .. } => span.clone(),
1215 NotAnEnum { span, .. } => span.clone(),
1216 TraitDeclPureImplImpure { span, .. } => span.clone(),
1217 TraitImplPurityMismatch { span, .. } => span.clone(),
1218 DeclIsNotAnEnum { span, .. } => span.clone(),
1219 DeclIsNotAStruct { span, .. } => span.clone(),
1220 DeclIsNotAFunction { span, .. } => span.clone(),
1221 DeclIsNotAVariable { span, .. } => span.clone(),
1222 DeclIsNotAnAbi { span, .. } => span.clone(),
1223 DeclIsNotATrait { span, .. } => span.clone(),
1224 DeclIsNotAnImplTrait { span, .. } => span.clone(),
1225 DeclIsNotATraitFn { span, .. } => span.clone(),
1226 DeclIsNotStorage { span, .. } => span.clone(),
1227 DeclIsNotAConstant { span, .. } => span.clone(),
1228 DeclIsNotATypeAlias { span, .. } => span.clone(),
1229 ImpureInNonContract { span, .. } => span.clone(),
1230 StorageAccessMismatched { span, .. } => span.clone(),
1231 ParameterRefMutabilityMismatch { span, .. } => span.clone(),
1232 IntegerTooLarge { span, .. } => span.clone(),
1233 IntegerTooSmall { span, .. } => span.clone(),
1234 IntegerContainsInvalidDigit { span, .. } => span.clone(),
1235 AbiAsSupertrait { span, .. } => span.clone(),
1236 SupertraitImplRequired { span, .. } => span.clone(),
1237 ContractCallParamRepeated { span, .. } => span.clone(),
1238 UnrecognizedContractParam { span, .. } => span.clone(),
1239 CallParamForNonContractCallMethod { span, .. } => span.clone(),
1240 StorageFieldDoesNotExist { field_name, .. } => field_name.span(),
1241 InvalidStorageOnlyTypeDecl { span, .. } => span.clone(),
1242 NoDeclaredStorage { span, .. } => span.clone(),
1243 MultipleStorageDeclarations { span, .. } => span.clone(),
1244 UnexpectedDeclaration { span, .. } => span.clone(),
1245 ContractAddressMustBeKnown { span, .. } => span.clone(),
1246 ConvertParseTree { error } => error.span(),
1247 Lex { error } => error.span(),
1248 Parse { error } => error.span.clone(),
1249 EnumNotFound { span, .. } => span.clone(),
1250 TupleIndexOutOfBounds { span, .. } => span.clone(),
1251 NonConstantDeclValue { span, .. } => span.clone(),
1252 StorageDeclarationInNonContract { span, .. } => span.clone(),
1253 IntrinsicUnsupportedArgType { span, .. } => span.clone(),
1254 IntrinsicIncorrectNumArgs { span, .. } => span.clone(),
1255 IntrinsicIncorrectNumTArgs { span, .. } => span.clone(),
1256 BreakOutsideLoop { span } => span.clone(),
1257 ContinueOutsideLoop { span } => span.clone(),
1258 ContractIdValueNotALiteral { span } => span.clone(),
1259 RefMutableNotAllowedInMain { span, .. } => span.clone(),
1260 InitializedRegisterReassignment { span, .. } => span.clone(),
1261 DisallowedControlFlowInstruction { span, .. } => span.clone(),
1262 CallingPrivateLibraryMethod { span, .. } => span.clone(),
1263 DisallowedIntrinsicInPredicate { span, .. } => span.clone(),
1264 CoinsPassedToNonPayableMethod { span, .. } => span.clone(),
1265 TraitImplPayabilityMismatch { span, .. } => span.clone(),
1266 ConfigurableInLibrary { span } => span.clone(),
1267 MultipleApplicableItemsInScope { span, .. } => span.clone(),
1268 NonStrGenericType { span } => span.clone(),
1269 CannotBeEvaluatedToConst { span } => span.clone(),
1270 ContractCallsItsOwnMethod { span } => span.clone(),
1271 AbiShadowsSuperAbiMethod { span, .. } => span.clone(),
1272 ConflictingSuperAbiMethods { span, .. } => span.clone(),
1273 AssociatedTypeNotSupportedInAbi { span, .. } => span.clone(),
1274 AbiSupertraitMethodCallAsContractCall { span, .. } => span.clone(),
1275 FunctionSelectorClash { span, .. } => span.clone(),
1276 TypeNotAllowed { span, .. } => span.clone(),
1277 ExpectedStringLiteral { span } => span.clone(),
1278 TypeIsNotValidAsImplementingFor { span, .. } => span.clone(),
1279 UninitRegisterInAsmBlockBeingRead { span } => span.clone(),
1280 ExpressionCannotBeDereferenced { span, .. } => span.clone(),
1281 FallbackFnsAreContractOnly { span } => span.clone(),
1282 FallbackFnsCannotHaveParameters { span } => span.clone(),
1283 CouldNotGenerateEntry { span } => span.clone(),
1284 CouldNotGenerateEntryMissingStd { span } => span.clone(),
1285 CouldNotGenerateEntryMissingImpl { span, .. } => span.clone(),
1286 CannotBeEvaluatedToConfigurableSizeUnknown { span } => span.clone(),
1287 EncodingUnsupportedType { span } => span.clone(),
1288 ConfigurableMissingAbiDecodeInPlace { span } => span.clone(),
1289 ABIHashCollision { span, .. } => span.clone(),
1290 InvalidRangeEndGreaterThanStart { span, .. } => span.clone(),
1291 TypeMustBeKnownAtThisPoint { span, .. } => span.clone(),
1292 MultipleImplsSatisfyingTraitForType { span, .. } => span.clone(),
1293 MultipleContractsMethodsWithTheSameName { spans } => spans[0].clone(),
1294 }
1295 }
1296}
1297
1298impl ToDiagnostic for CompileError {
1310 fn to_diagnostic(&self, source_engine: &SourceEngine) -> Diagnostic {
1311 let code = Code::semantic_analysis;
1312 use CompileError::*;
1313 match self {
1314 ConstantsCannotBeShadowed { shadowing_source, name, constant_span, constant_decl_span, is_alias } => Diagnostic {
1315 reason: Some(Reason::new(code(1), "Constants cannot be shadowed".to_string())),
1316 issue: Issue::error(
1317 source_engine,
1318 name.span(),
1319 format!(
1320 "{shadowing_source} \"{name}\" shadows {}constant of the same name.",
1326 if constant_decl_span.clone() != Span::dummy() { "imported " } else { "" }
1327 )
1328 ),
1329 hints: vec![
1330 Hint::info(
1331 source_engine,
1332 constant_span.clone(),
1333 format!(
1334 "Shadowed constant \"{name}\" {} here{}.",
1340 if constant_decl_span.clone() != Span::dummy() { "gets imported" } else { "is declared" },
1341 if *is_alias { " as alias" } else { "" }
1342 )
1343 ),
1344 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1345 Hint::help(
1346 source_engine,
1347 name.span(),
1348 format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1349 )
1350 } else {
1351 Hint::none()
1352 },
1353 Hint::info( source_engine,
1355 constant_decl_span.clone(),
1356 format!("This is the original declaration of the imported constant \"{name}\".")
1357 ),
1358 ],
1359 help: vec![
1360 "Unlike variables, constants cannot be shadowed by other constants or variables.".to_string(),
1361 match (shadowing_source, *constant_decl_span != Span::dummy()) {
1362 (LetVar | PatternMatchingStructFieldVar, false) => format!("Consider renaming either the {} \"{name}\" or the constant \"{name}\".",
1363 format!("{shadowing_source}").to_lowercase(),
1364 ),
1365 (Const, false) => "Consider renaming one of the constants.".to_string(),
1366 (shadowing_source, true) => format!(
1367 "Consider renaming the {} \"{name}\" or using {} for the imported constant.",
1368 format!("{shadowing_source}").to_lowercase(),
1369 if *is_alias { "a different alias" } else { "an alias" }
1370 ),
1371 },
1372 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1373 format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1374 } else {
1375 Diagnostic::help_none()
1376 }
1377 ],
1378 },
1379 ConfigurablesCannotBeShadowed { shadowing_source, name, configurable_span } => Diagnostic {
1380 reason: Some(Reason::new(code(1), "Configurables cannot be shadowed".to_string())),
1381 issue: Issue::error(
1382 source_engine,
1383 name.span(),
1384 format!("{shadowing_source} \"{name}\" shadows configurable of the same name.")
1385 ),
1386 hints: vec![
1387 Hint::info(
1388 source_engine,
1389 configurable_span.clone(),
1390 format!("Shadowed configurable \"{name}\" is declared here.")
1391 ),
1392 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1393 Hint::help(
1394 source_engine,
1395 name.span(),
1396 format!("\"{name}\" is a struct field that defines a pattern variable of the same name.")
1397 )
1398 } else {
1399 Hint::none()
1400 },
1401 ],
1402 help: vec![
1403 "Unlike variables, configurables cannot be shadowed by constants or variables.".to_string(),
1404 format!(
1405 "Consider renaming either the {} \"{name}\" or the configurable \"{name}\".",
1406 format!("{shadowing_source}").to_lowercase()
1407 ),
1408 if matches!(shadowing_source, PatternMatchingStructFieldVar) {
1409 format!("To rename the pattern variable use the `:`. E.g.: `{name}: some_other_name`.")
1410 } else {
1411 Diagnostic::help_none()
1412 }
1413 ],
1414 },
1415 ConfigurablesCannotBeMatchedAgainst { name, configurable_span } => Diagnostic {
1416 reason: Some(Reason::new(code(1), "Configurables cannot be matched against".to_string())),
1417 issue: Issue::error(
1418 source_engine,
1419 name.span(),
1420 format!("\"{name}\" is a configurable and configurables cannot be matched against.")
1421 ),
1422 hints: {
1423 let mut hints = vec![
1424 Hint::info(
1425 source_engine,
1426 configurable_span.clone(),
1427 format!("Configurable \"{name}\" is declared here.")
1428 ),
1429 ];
1430
1431 hints.append(&mut Hint::multi_help(source_engine, &name.span(), vec![
1432 format!("Are you trying to define a pattern variable named \"{name}\"?"),
1433 format!("In that case, use some other name for the pattern variable,"),
1434 format!("or consider renaming the configurable \"{name}\"."),
1435 ]));
1436
1437 hints
1438 },
1439 help: vec![
1440 "Unlike constants, configurables cannot be matched against in pattern matching.".to_string(),
1441 "That's not possible, because patterns to match against must be compile-time constants.".to_string(),
1442 "Configurables are run-time constants. Their values are defined during the deployment.".to_string(),
1443 Diagnostic::help_empty_line(),
1444 "To test against a configurable, consider:".to_string(),
1445 format!("{}- replacing the `match` expression with `if-else`s altogether.", Indent::Single),
1446 format!("{}- matching against a variable and comparing that variable afterwards with the configurable.", Indent::Single),
1447 format!("{} E.g., instead of:", Indent::Single),
1448 Diagnostic::help_empty_line(),
1449 format!("{} SomeStruct {{ x: A_CONFIGURABLE, y: 42 }} => {{", Indent::Double),
1450 format!("{} do_something();", Indent::Double),
1451 format!("{} }}", Indent::Double),
1452 Diagnostic::help_empty_line(),
1453 format!("{} to have:", Indent::Single),
1454 Diagnostic::help_empty_line(),
1455 format!("{} SomeStruct {{ x, y: 42 }} => {{", Indent::Double),
1456 format!("{} if x == A_CONFIGURABLE {{", Indent::Double),
1457 format!("{} do_something();", Indent::Double),
1458 format!("{} }}", Indent::Double),
1459 format!("{} }}", Indent::Double),
1460 ],
1461 },
1462 ConstantShadowsVariable { name , variable_span } => Diagnostic {
1463 reason: Some(Reason::new(code(1), "Constants cannot shadow variables".to_string())),
1464 issue: Issue::error(
1465 source_engine,
1466 name.span(),
1467 format!("Constant \"{name}\" shadows variable of the same name.")
1468 ),
1469 hints: vec![
1470 Hint::info(
1471 source_engine,
1472 variable_span.clone(),
1473 format!("This is the shadowed variable \"{name}\".")
1474 ),
1475 ],
1476 help: vec![
1477 format!("Variables can shadow other variables, but constants cannot."),
1478 format!("Consider renaming either the variable or the constant."),
1479 ],
1480 },
1481 ConstantDuplicatesConstantOrConfigurable { existing_constant_or_configurable, new_constant_or_configurable, name, existing_span } => Diagnostic {
1482 reason: Some(Reason::new(code(1), match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1483 ("Constant", "Constant") => "Constant of the same name already exists".to_string(),
1484 ("Constant", "Configurable") => "Constant of the same name as configurable already exists".to_string(),
1485 ("Configurable", "Constant") => "Configurable of the same name as constant already exists".to_string(),
1486 _ => unreachable!("We can have only the listed combinations. Configurable duplicating configurable is not a valid combination.")
1487 })),
1488 issue: Issue::error(
1489 source_engine,
1490 name.span(),
1491 format!("{new_constant_or_configurable} \"{name}\" has the same name as an already declared {}.",
1492 existing_constant_or_configurable.to_lowercase()
1493 )
1494 ),
1495 hints: vec![
1496 Hint::info(
1497 source_engine,
1498 existing_span.clone(),
1499 format!("{existing_constant_or_configurable} \"{name}\" is {}declared here.",
1500 if existing_constant_or_configurable == new_constant_or_configurable {
1502 "already "
1503 } else {
1504 ""
1505 }
1506 )
1507 ),
1508 ],
1509 help: vec![
1510 match (*existing_constant_or_configurable, *new_constant_or_configurable) {
1511 ("Constant", "Constant") => "Consider renaming one of the constants, or in case of imported constants, using an alias.".to_string(),
1512 _ => "Consider renaming either the configurable or the constant, or in case of an imported constant, using an alias.".to_string(),
1513 },
1514 ],
1515 },
1516 MultipleDefinitionsOfMatchArmVariable { match_value, match_type, first_definition, first_definition_is_struct_field, duplicate, duplicate_is_struct_field } => Diagnostic {
1517 reason: Some(Reason::new(code(1), "Match pattern variable is already defined".to_string())),
1518 issue: Issue::error(
1519 source_engine,
1520 duplicate.clone(),
1521 format!("Variable \"{}\" is already defined in this match arm.", first_definition.as_str())
1522 ),
1523 hints: vec![
1524 Hint::help(
1525 source_engine,
1526 if *duplicate_is_struct_field {
1527 duplicate.clone()
1528 }
1529 else {
1530 Span::dummy()
1531 },
1532 format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str())
1533 ),
1534 Hint::info(
1535 source_engine,
1536 first_definition.clone(),
1537 format!(
1538 "This {}is the first definition of the variable \"{}\".",
1539 if *first_definition_is_struct_field {
1540 format!("struct field \"{}\" ", first_definition.as_str())
1541 }
1542 else {
1543 "".to_string()
1544 },
1545 first_definition.as_str(),
1546 )
1547 ),
1548 Hint::help(
1549 source_engine,
1550 if *first_definition_is_struct_field && !*duplicate_is_struct_field {
1551 first_definition.clone()
1552 }
1553 else {
1554 Span::dummy()
1555 },
1556 format!("Struct field \"{0}\" is just a shorthand notation for `{0}: {0}`. It defines a variable \"{0}\".", first_definition.as_str()),
1557 ),
1558 Hint::info(
1559 source_engine,
1560 match_value.clone(),
1561 format!("The expression to match on is of type \"{match_type}\".")
1562 ),
1563 ],
1564 help: vec![
1565 format!("Variables used in match arm patterns must be unique within a pattern, except in alternatives."),
1566 match (*first_definition_is_struct_field, *duplicate_is_struct_field) {
1567 (true, true) => format!("Consider declaring a variable with different name for either of the fields. E.g., `{0}: var_{0}`.", first_definition.as_str()),
1568 (true, false) | (false, true) => format!("Consider declaring a variable for the field \"{0}\" (e.g., `{0}: var_{0}`), or renaming the variable \"{0}\".", first_definition.as_str()),
1569 (false, false) => "Consider renaming either of the variables.".to_string(),
1570 },
1571 ],
1572 },
1573 MatchArmVariableMismatchedType { match_value, match_type, variable, first_definition, expected, received } => Diagnostic {
1574 reason: Some(Reason::new(code(1), "Match pattern variable has mismatched type".to_string())),
1575 issue: Issue::error(
1576 source_engine,
1577 variable.span(),
1578 format!("Variable \"{variable}\" is expected to be of type \"{expected}\", but is \"{received}\".")
1579 ),
1580 hints: vec![
1581 Hint::info(
1582 source_engine,
1583 first_definition.clone(),
1584 format!("\"{variable}\" is first defined here with type \"{expected}\".")
1585 ),
1586 Hint::info(
1587 source_engine,
1588 match_value.clone(),
1589 format!("The expression to match on is of type \"{match_type}\".")
1590 ),
1591 ],
1592 help: vec![
1593 format!("In the same match arm, a variable must have the same type in all alternatives."),
1594 ],
1595 },
1596 MatchArmVariableNotDefinedInAllAlternatives { match_value, match_type, variable, missing_in_alternatives} => Diagnostic {
1597 reason: Some(Reason::new(code(1), "Match pattern variable is not defined in all alternatives".to_string())),
1598 issue: Issue::error(
1599 source_engine,
1600 variable.span(),
1601 format!("Variable \"{variable}\" is not defined in all alternatives.")
1602 ),
1603 hints: {
1604 let mut hints = vec![
1605 Hint::info(
1606 source_engine,
1607 match_value.clone(),
1608 format!("The expression to match on is of type \"{match_type}\".")
1609 ),
1610 ];
1611
1612 for (i, alternative) in missing_in_alternatives.iter().enumerate() {
1613 hints.push(
1614 Hint::info(
1615 source_engine,
1616 alternative.clone(),
1617 format!("\"{variable}\" is {}missing in this alternative.", if i != 0 { "also " } else { "" }),
1618 )
1619 )
1620 }
1621
1622 hints
1623 },
1624 help: vec![
1625 format!("Consider removing the variable \"{variable}\" altogether, or adding it to all alternatives."),
1626 ],
1627 },
1628 MatchStructPatternMissingFields { missing_fields, missing_fields_are_public, struct_name, struct_decl_span, total_number_of_fields, span } => Diagnostic {
1629 reason: Some(Reason::new(code(1), "Struct pattern has missing fields".to_string())),
1630 issue: Issue::error(
1631 source_engine,
1632 span.clone(),
1633 format!("Struct pattern is missing the {}field{} {}.",
1634 if *missing_fields_are_public { "public " } else { "" },
1635 plural_s(missing_fields.len()),
1636 sequence_to_str(missing_fields, Enclosing::DoubleQuote, 2)
1637 )
1638 ),
1639 hints: vec![
1640 Hint::help(
1641 source_engine,
1642 span.clone(),
1643 "Struct pattern must either contain or ignore each struct field.".to_string()
1644 ),
1645 Hint::info(
1646 source_engine,
1647 struct_decl_span.clone(),
1648 format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1649 number_to_str(*total_number_of_fields),
1650 plural_s(*total_number_of_fields),
1651 )
1652 ),
1653 ],
1654 help: vec![
1655 format!("Consider ignoring {} field{} {}by using the `_` pattern{} `{}: _`.",
1659 singular_plural(missing_fields.len(), "the", "individual"),
1660 plural_s(missing_fields.len()),
1661 singular_plural(missing_fields.len(), &format!("\"{}\" ", missing_fields[0]), ""),
1662 singular_plural(missing_fields.len(), ":", ". E.g.,"),
1663 missing_fields[0]
1664 ),
1665 "Alternatively, consider ignoring all the missing fields by ending the struct pattern with `..`.".to_string(),
1666 ],
1667 },
1668 MatchStructPatternMustIgnorePrivateFields { private_fields, struct_name, struct_decl_span, all_fields_are_private, span } => Diagnostic {
1669 reason: Some(Reason::new(code(1), "Struct pattern must ignore inaccessible private fields".to_string())),
1670 issue: Issue::error(
1671 source_engine,
1672 span.clone(),
1673 format!("Struct pattern must ignore inaccessible private field{} {}.",
1674 plural_s(private_fields.len()),
1675 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1676 )
1677 ),
1678 hints: vec![
1679 Hint::help(
1680 source_engine,
1681 span.clone(),
1682 format!("To ignore the private field{}, end the struct pattern with `..`.",
1683 plural_s(private_fields.len()),
1684 )
1685 ),
1686 Hint::info(
1687 source_engine,
1688 struct_decl_span.clone(),
1689 format!("Struct \"{struct_name}\" is declared here, and has {}.",
1690 if *all_fields_are_private {
1691 "all private fields".to_string()
1692 } else {
1693 format!("private field{} {}",
1694 plural_s(private_fields.len()),
1695 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1696 )
1697 }
1698 )
1699 ),
1700 ],
1701 help: vec![],
1702 },
1703 TraitNotImportedAtFunctionApplication { trait_name, function_name, function_call_site_span, trait_constraint_span, trait_candidates } => {
1704 let mut trait_candidates = trait_candidates.clone();
1706 trait_candidates.sort();
1707 let trait_candidates = &trait_candidates; Diagnostic {
1710 reason: Some(Reason::new(code(1), "Trait is not imported".to_string())),
1711 issue: Issue::error(
1712 source_engine,
1713 function_call_site_span.clone(),
1714 format!(
1715 "Trait \"{trait_name}\" is not imported {}when calling \"{function_name}\".",
1716 get_file_name(source_engine, function_call_site_span.source_id())
1717 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1718 )
1719 ),
1720 hints: {
1721 let mut hints = vec![
1722 Hint::help(
1723 source_engine,
1724 function_call_site_span.clone(),
1725 format!("This import is needed because \"{function_name}\" requires \"{trait_name}\" in one of its trait constraints.")
1726 ),
1727 Hint::info(
1728 source_engine,
1729 trait_constraint_span.clone(),
1730 format!("In the definition of \"{function_name}\", \"{trait_name}\" is used in this trait constraint.")
1731 ),
1732 ];
1733
1734 match trait_candidates.len() {
1735 0 => (),
1740 1 => hints.push(Hint::help(
1742 source_engine,
1743 function_call_site_span.clone(),
1744 format!(
1745 "Import the \"{trait_name}\" trait {}by using: `use {};`.",
1746 get_file_name(source_engine, function_call_site_span.source_id())
1747 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" ")),
1748 trait_candidates[0]
1749 )
1750 )),
1751 _ => hints.push(Hint::help(
1753 source_engine,
1754 function_call_site_span.clone(),
1755 format!(
1756 "To import the proper \"{trait_name}\" {}follow the detailed instructions given below.",
1757 get_file_name(source_engine, function_call_site_span.source_id())
1758 .map_or("".to_string(), |file_name| format!("into \"{file_name}\" "))
1759 )
1760 )),
1761 }
1762
1763 hints
1764 },
1765 help: {
1766 let mut help = vec![];
1767
1768 if trait_candidates.len() > 1 {
1769 help.push(format!("There are these {} traits with the name \"{trait_name}\" available in the modules:", number_to_str(trait_candidates.len())));
1770 for trait_candidate in trait_candidates.iter() {
1771 help.push(format!("{}- {trait_candidate}", Indent::Single));
1772 }
1773 help.push("To import the proper one follow these steps:".to_string());
1774 help.push(format!(
1775 "{}1. Look at the definition of the \"{function_name}\"{}.",
1776 Indent::Single,
1777 get_file_name(source_engine, trait_constraint_span.source_id())
1778 .map_or("".to_string(), |file_name| format!(" in the \"{file_name}\""))
1779 ));
1780 help.push(format!(
1781 "{}2. Detect which exact \"{trait_name}\" is used in the trait constraint in the \"{function_name}\".",
1782 Indent::Single
1783 ));
1784 help.push(format!(
1785 "{}3. Import that \"{trait_name}\"{}.",
1786 Indent::Single,
1787 get_file_name(source_engine, function_call_site_span.source_id())
1788 .map_or("".to_string(), |file_name| format!(" into \"{file_name}\""))
1789 ));
1790 help.push(format!("{} E.g., assuming it is the first one on the list, use: `use {};`", Indent::Double, trait_candidates[0]));
1791 }
1792
1793 help
1794 },
1795 }
1796 },
1797 ExpressionCannotBeDereferenced { expression_type, span } => Diagnostic {
1799 reason: Some(Reason::new(code(1), "Expression cannot be dereferenced".to_string())),
1800 issue: Issue::error(
1801 source_engine,
1802 span.clone(),
1803 format!("This expression cannot be dereferenced, because it is of type \"{expression_type}\", which is not a reference type.")
1804 ),
1805 hints: vec![
1806 Hint::help(
1807 source_engine,
1808 span.clone(),
1809 "In Sway, only references can be dereferenced.".to_string()
1810 ),
1811 Hint::help(
1812 source_engine,
1813 span.clone(),
1814 "Are you missing the reference operator `&` somewhere in the code?".to_string()
1815 ),
1816 ],
1817 help: vec![],
1818 },
1819 StructInstantiationMissingFields { field_names, struct_name, span, struct_decl_span, total_number_of_fields } => Diagnostic {
1820 reason: Some(Reason::new(code(1), "Struct instantiation has missing fields".to_string())),
1821 issue: Issue::error(
1822 source_engine,
1823 span.clone(),
1824 format!("Instantiation of the struct \"{struct_name}\" is missing the field{} {}.",
1825 plural_s(field_names.len()),
1826 sequence_to_str(field_names, Enclosing::DoubleQuote, 2)
1827 )
1828 ),
1829 hints: vec![
1830 Hint::help(
1831 source_engine,
1832 span.clone(),
1833 "Struct instantiation must initialize all the fields of the struct.".to_string()
1834 ),
1835 Hint::info(
1836 source_engine,
1837 struct_decl_span.clone(),
1838 format!("Struct \"{struct_name}\" is declared here, and has {} field{}.",
1839 number_to_str(*total_number_of_fields),
1840 plural_s(*total_number_of_fields),
1841 )
1842 ),
1843 ],
1844 help: vec![],
1845 },
1846 StructCannotBeInstantiated { struct_name, span, struct_decl_span, private_fields, constructors, all_fields_are_private, is_in_storage_declaration, struct_can_be_changed } => Diagnostic {
1847 reason: Some(Reason::new(code(1), "Struct cannot be instantiated due to inaccessible private fields".to_string())),
1848 issue: Issue::error(
1849 source_engine,
1850 span.clone(),
1851 format!("\"{struct_name}\" cannot be {}instantiated in this {}, due to {}inaccessible private field{}.",
1852 if *is_in_storage_declaration { "" } else { "directly " },
1853 if *is_in_storage_declaration { "storage declaration" } else { "module" },
1854 singular_plural(private_fields.len(), "an ", ""),
1855 plural_s(private_fields.len())
1856 )
1857 ),
1858 hints: vec![
1859 Hint::help(
1860 source_engine,
1861 span.clone(),
1862 format!("Inaccessible field{} {} {}.",
1863 plural_s(private_fields.len()),
1864 is_are(private_fields.len()),
1865 sequence_to_str(private_fields, Enclosing::DoubleQuote, 5)
1866 )
1867 ),
1868 Hint::help(
1869 source_engine,
1870 span.clone(),
1871 if *is_in_storage_declaration {
1872 "Structs with private fields can be instantiated in storage declarations only if they are declared in the same module as the storage.".to_string()
1873 } else {
1874 "Structs with private fields can be instantiated only within the module in which they are declared.".to_string()
1875 }
1876 ),
1877 if *is_in_storage_declaration {
1878 Hint::help(
1879 source_engine,
1880 span.clone(),
1881 "They can still be initialized in storage declarations if they have public constructors that evaluate to a constant.".to_string()
1882 )
1883 } else {
1884 Hint::none()
1885 },
1886 if *is_in_storage_declaration {
1887 Hint::help(
1888 source_engine,
1889 span.clone(),
1890 "They can always be stored in storage by using the `read` and `write` functions provided in the `std::storage::storage_api`.".to_string()
1891 )
1892 } else {
1893 Hint::none()
1894 },
1895 if !*is_in_storage_declaration && !constructors.is_empty() {
1896 Hint::help(
1897 source_engine,
1898 span.clone(),
1899 format!("\"{struct_name}\" can be instantiated via public constructors suggested below.")
1900 )
1901 } else {
1902 Hint::none()
1903 },
1904 Hint::info(
1905 source_engine,
1906 struct_decl_span.clone(),
1907 format!("Struct \"{struct_name}\" is declared here, and has {}.",
1908 if *all_fields_are_private {
1909 "all private fields".to_string()
1910 } else {
1911 format!("private field{} {}",
1912 plural_s(private_fields.len()),
1913 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1914 )
1915 }
1916 )
1917 ),
1918 ],
1919 help: {
1920 let mut help = vec![];
1921
1922 if *is_in_storage_declaration {
1923 help.push(format!("Consider initializing \"{struct_name}\" by finding an available constructor that evaluates to a constant{}.",
1924 if *struct_can_be_changed {
1925 ", or implement a new one"
1926 } else {
1927 ""
1928 }
1929 ));
1930
1931 if !constructors.is_empty() {
1932 help.push("Check these already available constructors. They might evaluate to a constant:".to_string());
1933 for constructor in sequence_to_list(constructors, Indent::Single, usize::MAX) {
1935 help.push(constructor);
1936 }
1937 };
1938
1939 help.push(Diagnostic::help_empty_line());
1940
1941 help.push(format!("Or you can always store instances of \"{struct_name}\" in the contract storage, by using the `std::storage::storage_api`:"));
1942 help.push(format!("{}use std::storage::storage_api::{{read, write}};", Indent::Single));
1943 help.push(format!("{}write(STORAGE_KEY, 0, my_{});", Indent::Single, to_snake_case(struct_name.as_str())));
1944 help.push(format!("{}let my_{}_option = read::<{struct_name}>(STORAGE_KEY, 0);", Indent::Single, to_snake_case(struct_name.as_str())));
1945 }
1946 else if !constructors.is_empty() {
1947 help.push(format!("Consider instantiating \"{struct_name}\" by using one of the available constructors{}:",
1948 if *struct_can_be_changed {
1949 ", or implement a new one"
1950 } else {
1951 ""
1952 }
1953 ));
1954 for constructor in sequence_to_list(constructors, Indent::Single, 5) {
1955 help.push(constructor);
1956 }
1957 }
1958
1959 if *struct_can_be_changed {
1960 if *is_in_storage_declaration || !constructors.is_empty() {
1961 help.push(Diagnostic::help_empty_line());
1962 }
1963
1964 if !*is_in_storage_declaration && constructors.is_empty() {
1965 help.push(format!("Consider implementing a public constructor for \"{struct_name}\"."));
1966 };
1967
1968 help.push(
1969 format!("Alternatively, consider declaring {} as public in \"{struct_name}\": `pub {}: ...,`.",
1975 if *all_fields_are_private {
1976 "all fields".to_string()
1977 } else {
1978 format!("{} {}",
1979 singular_plural(private_fields.len(), "the field", "the fields"),
1980 sequence_to_str(private_fields, Enclosing::DoubleQuote, 2)
1981 )
1982 },
1983 if *all_fields_are_private {
1984 "<field>".to_string()
1985 } else {
1986 match &private_fields[..] {
1987 [field] => format!("{field}"),
1988 _ => "<field>".to_string(),
1989 }
1990 },
1991 )
1992 )
1993 };
1994
1995 help
1996 }
1997 },
1998 StructFieldIsPrivate { field_name, struct_name, field_decl_span, struct_can_be_changed, usage_context } => Diagnostic {
1999 reason: Some(Reason::new(code(1), "Private struct field is inaccessible".to_string())),
2000 issue: Issue::error(
2001 source_engine,
2002 field_name.span(),
2003 format!("Private field \"{field_name}\" {}is inaccessible in this module.",
2004 match usage_context {
2005 StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => "".to_string(),
2006 StorageAccess | StructFieldAccess => format!("of the struct \"{struct_name}\" "),
2007 }
2008 )
2009 ),
2010 hints: vec![
2011 Hint::help(
2012 source_engine,
2013 field_name.span(),
2014 format!("Private fields can only be {} within the module in which their struct is declared.",
2015 match usage_context {
2016 StructInstantiation { .. } | StorageDeclaration { .. } => "initialized",
2017 StorageAccess | StructFieldAccess => "accessed",
2018 PatternMatching { .. } => "matched",
2019 }
2020 )
2021 ),
2022 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2023 Hint::help(
2024 source_engine,
2025 field_name.span(),
2026 "Otherwise, they must be ignored by ending the struct pattern with `..`.".to_string()
2027 )
2028 } else {
2029 Hint::none()
2030 },
2031 Hint::info(
2032 source_engine,
2033 field_decl_span.clone(),
2034 format!("Field \"{field_name}\" {}is declared here as private.",
2035 match usage_context {
2036 StructInstantiation { .. } | StorageDeclaration { .. } | PatternMatching { .. } => format!("of the struct \"{struct_name}\" "),
2037 StorageAccess | StructFieldAccess => "".to_string(),
2038 }
2039 )
2040 ),
2041 ],
2042 help: vec![
2043 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2044 format!("Consider removing the field \"{field_name}\" from the struct pattern, and ending the pattern with `..`.")
2045 } else {
2046 Diagnostic::help_none()
2047 },
2048 if *struct_can_be_changed {
2049 match usage_context {
2050 StorageAccess | StructFieldAccess | PatternMatching { .. } => {
2051 format!("{} declaring the field \"{field_name}\" as public in \"{struct_name}\": `pub {field_name}: ...,`.",
2052 if matches!(usage_context, PatternMatching { has_rest_pattern } if !has_rest_pattern) {
2053 "Alternatively, consider"
2054 } else {
2055 "Consider"
2056 }
2057 )
2058 },
2059 _ => Diagnostic::help_none(),
2061 }
2062 } else {
2063 Diagnostic::help_none()
2064 },
2065 ],
2066 },
2067 StructFieldDoesNotExist { field_name, available_fields, is_public_struct_access, struct_name, struct_decl_span, struct_is_empty, usage_context } => Diagnostic {
2068 reason: Some(Reason::new(code(1), "Struct field does not exist".to_string())),
2069 issue: Issue::error(
2070 source_engine,
2071 field_name.span(),
2072 format!("Field \"{field_name}\" does not exist in the struct \"{struct_name}\".")
2073 ),
2074 hints: {
2075 let public = if *is_public_struct_access { "public " } else { "" };
2076
2077 let (hint, show_struct_decl) = if *struct_is_empty {
2078 (Some(format!("\"{struct_name}\" is an empty struct. It doesn't have any fields.")), false)
2079 }
2080 else if (matches!(usage_context, StorageAccess) && *is_public_struct_access && available_fields.is_empty())
2085 ||
2086 (matches!(usage_context, StructInstantiation { struct_can_be_instantiated: false } | StorageDeclaration { struct_can_be_instantiated: false })) {
2087 (None, false)
2093 } else if !available_fields.is_empty() {
2094 const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2096 match &available_fields[..] {
2097 [field] => (Some(format!("Only available {public}field is \"{field}\".")), false),
2098 _ => (Some(format!("Available {public}fields are {}.", sequence_to_str(available_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY))),
2099 available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2100 ),
2101 }
2102 }
2103 else {
2104 (None, false)
2105 };
2106
2107 let mut hints = vec![];
2108
2109 if let Some(hint) = hint {
2110 hints.push(Hint::help(source_engine, field_name.span(), hint));
2111 };
2112
2113 if show_struct_decl {
2114 hints.push(Hint::info(
2115 source_engine,
2116 struct_decl_span.clone(),
2117 format!("Struct \"{struct_name}\" is declared here, and has {} {public}fields.",
2118 number_to_str(available_fields.len())
2119 )
2120 ));
2121 }
2122
2123 hints
2124 },
2125 help: vec![],
2126 },
2127 StructFieldDuplicated { field_name, duplicate } => Diagnostic {
2128 reason: Some(Reason::new(code(1), "Struct field has multiple definitions".to_string())),
2129 issue: Issue::error(
2130 source_engine,
2131 field_name.span(),
2132 format!("Field \"{field_name}\" has multiple definitions.")
2133 ),
2134 hints: {
2135 vec![
2136 Hint::info(
2137 source_engine,
2138 duplicate.span(),
2139 "Field definition duplicated here.".into(),
2140 )
2141 ]
2142 },
2143 help: vec![],
2144 },
2145 NotIndexable { actually, span } => Diagnostic {
2146 reason: Some(Reason::new(code(1), "Type is not indexable".to_string())),
2147 issue: Issue::error(
2148 source_engine,
2149 span.clone(),
2150 format!("This expression has type \"{actually}\", which is not an indexable type.")
2151 ),
2152 hints: vec![],
2153 help: vec![
2154 "Index operator `[]` can be used only on indexable types.".to_string(),
2155 "In Sway, indexable types are:".to_string(),
2156 format!("{}- arrays. E.g., `[u64;3]`.", Indent::Single),
2157 format!("{}- references, direct or indirect, to arrays. E.g., `&[u64;3]` or `&&&[u64;3]`.", Indent::Single),
2158 ],
2159 },
2160 FieldAccessOnNonStruct { actually, storage_variable, field_name, span } => Diagnostic {
2161 reason: Some(Reason::new(code(1), "Field access requires a struct".to_string())),
2162 issue: Issue::error(
2163 source_engine,
2164 span.clone(),
2165 format!("{} has type \"{actually}\", which is not a struct{}.",
2166 if let Some(storage_variable) = storage_variable {
2167 format!("Storage variable \"{storage_variable}\"")
2168 } else {
2169 "This expression".to_string()
2170 },
2171 if storage_variable.is_some() {
2172 ""
2173 } else {
2174 " or a reference to a struct"
2175 }
2176 )
2177 ),
2178 hints: vec![
2179 Hint::info(
2180 source_engine,
2181 field_name.span(),
2182 format!("Field access happens here, on \"{field_name}\".")
2183 )
2184 ],
2185 help: if storage_variable.is_some() {
2186 vec![
2187 "Fields can only be accessed on storage variables that are structs.".to_string(),
2188 ]
2189 } else {
2190 vec![
2191 "In Sway, fields can be accessed on:".to_string(),
2192 format!("{}- structs. E.g., `my_struct.field`.", Indent::Single),
2193 format!("{}- references, direct or indirect, to structs. E.g., `(&my_struct).field` or `(&&&my_struct).field`.", Indent::Single),
2194 ]
2195 }
2196 },
2197 SymbolWithMultipleBindings { name, paths, span } => Diagnostic {
2198 reason: Some(Reason::new(code(1), "Multiple bindings exist for symbol in the scope".to_string())),
2199 issue: Issue::error(
2200 source_engine,
2201 span.clone(),
2202 format!("The following paths are all valid bindings for symbol \"{}\": {}.", name, sequence_to_str(&paths.iter().map(|path| format!("{path}::{name}")).collect::<Vec<_>>(), Enclosing::DoubleQuote, 2)),
2203 ),
2204 hints: vec![],
2205 help: vec![format!("Consider using a fully qualified name, e.g., `{}::{}`.", paths[0], name)],
2206 },
2207 StorageFieldDoesNotExist { field_name, available_fields, storage_decl_span } => Diagnostic {
2208 reason: Some(Reason::new(code(1), "Storage field does not exist".to_string())),
2209 issue: Issue::error(
2210 source_engine,
2211 field_name.span(),
2212 format!("Storage field \"{field_name}\" does not exist in the storage.")
2213 ),
2214 hints: {
2215 let (hint, show_storage_decl) = if available_fields.is_empty() {
2216 ("The storage is empty. It doesn't have any fields.".to_string(), false)
2217 } else {
2218 const NUM_OF_FIELDS_TO_DISPLAY: usize = 4;
2219 let display_fields = available_fields.iter().map(|(path, field_name)| {
2220 let path = path.iter().map(ToString::to_string).collect::<Vec<_>>().join("::");
2221 if path.is_empty() {
2222 format!("storage.{field_name}")
2223 } else {
2224 format!("storage::{path}.{field_name}")
2225 }
2226 }).collect::<Vec<_>>();
2227 match &display_fields[..] {
2228 [field] => (format!("Only available storage field is \"{field}\"."), false),
2229 _ => (format!("Available storage fields are {}.", sequence_to_str(&display_fields, Enclosing::DoubleQuote, NUM_OF_FIELDS_TO_DISPLAY)),
2230 available_fields.len() > NUM_OF_FIELDS_TO_DISPLAY
2231 ),
2232 }
2233 };
2234
2235 let mut hints = vec![];
2236
2237 hints.push(Hint::help(source_engine, field_name.span(), hint));
2238
2239 if show_storage_decl {
2240 hints.push(Hint::info(
2241 source_engine,
2242 storage_decl_span.clone(),
2243 format!("Storage is declared here, and has {} fields.",
2244 number_to_str(available_fields.len())
2245 )
2246 ));
2247 }
2248
2249 hints
2250 },
2251 help: vec![],
2252 },
2253 TupleIndexOutOfBounds { index, count, tuple_type, span, prefix_span } => Diagnostic {
2254 reason: Some(Reason::new(code(1), "Tuple index is out of bounds".to_string())),
2255 issue: Issue::error(
2256 source_engine,
2257 span.clone(),
2258 format!("Tuple index {index} is out of bounds. The tuple has only {count} element{}.", plural_s(*count))
2259 ),
2260 hints: vec![
2261 Hint::info(
2262 source_engine,
2263 prefix_span.clone(),
2264 format!("This expression has type \"{tuple_type}\".")
2265 ),
2266 ],
2267 help: vec![],
2268 },
2269 TupleElementAccessOnNonTuple { actually, span, index, index_span } => Diagnostic {
2270 reason: Some(Reason::new(code(1), "Tuple element access requires a tuple".to_string())),
2271 issue: Issue::error(
2272 source_engine,
2273 span.clone(),
2274 format!("This expression has type \"{actually}\", which is not a tuple or a reference to a tuple.")
2275 ),
2276 hints: vec![
2277 Hint::info(
2278 source_engine,
2279 index_span.clone(),
2280 format!("Tuple element access happens here, on the index {index}.")
2281 )
2282 ],
2283 help: vec![
2284 "In Sway, tuple elements can be accessed on:".to_string(),
2285 format!("{}- tuples. E.g., `my_tuple.1`.", Indent::Single),
2286 format!("{}- references, direct or indirect, to tuples. E.g., `(&my_tuple).1` or `(&&&my_tuple).1`.", Indent::Single),
2287 ],
2288 },
2289 RefMutCannotReferenceConstant { constant, span } => Diagnostic {
2290 reason: Some(Reason::new(code(1), "References to mutable values cannot reference constants".to_string())),
2291 issue: Issue::error(
2292 source_engine,
2293 span.clone(),
2294 format!("\"{constant}\" is a constant. `&mut` cannot reference constants.")
2295 ),
2296 hints: vec![],
2297 help: vec![
2298 "Consider:".to_string(),
2299 format!("{}- taking a reference without `mut`: `&{constant}`.", Indent::Single),
2300 format!("{}- referencing a mutable copy of the constant, by returning it from a block: `&mut {{ {constant} }}`.", Indent::Single)
2301 ],
2302 },
2303 RefMutCannotReferenceImmutableVariable { decl_name, span } => Diagnostic {
2304 reason: Some(Reason::new(code(1), "References to mutable values cannot reference immutable variables".to_string())),
2305 issue: Issue::error(
2306 source_engine,
2307 span.clone(),
2308 format!("\"{decl_name}\" is an immutable variable. `&mut` cannot reference immutable variables.")
2309 ),
2310 hints: vec![
2311 Hint::info(
2312 source_engine,
2313 decl_name.span(),
2314 format!("Variable \"{decl_name}\" is declared here as immutable.")
2315 ),
2316 ],
2317 help: vec![
2318 "Consider:".to_string(),
2319 format!("{}- declaring \"{decl_name}\" as mutable.", Indent::Single),
2321 format!("{}- taking a reference without `mut`: `&{decl_name}`.", Indent::Single),
2322 format!("{}- referencing a mutable copy of \"{decl_name}\", by returning it from a block: `&mut {{ {decl_name} }}`.", Indent::Single)
2323 ],
2324 },
2325 ConflictingImplsForTraitAndType { trait_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => Diagnostic {
2326 reason: Some(Reason::new(code(1), "Trait is already implemented for type".to_string())),
2327 issue: Issue::error(
2328 source_engine,
2329 second_impl_span.clone(),
2330 if type_implementing_for == type_implementing_for_unaliased {
2331 format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\".")
2332 } else {
2333 format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").")
2334 }
2335 ),
2336 hints: vec![
2337 Hint::info(
2338 source_engine,
2339 existing_impl_span.clone(),
2340 if type_implementing_for == type_implementing_for_unaliased {
2341 format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\".",
2342 call_path_suffix_with_args(trait_name)
2343 )
2344 } else {
2345 format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").",
2346 call_path_suffix_with_args(trait_name)
2347 )
2348 }
2349 ),
2350 ],
2351 help: vec![
2352 "In Sway, there can be at most one implementation of a trait for any given type.".to_string(),
2353 "This property is called \"trait coherence\".".to_string(),
2354 ],
2355 },
2356 DuplicateDeclDefinedForType { decl_kind, decl_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => {
2357 let decl_kind_snake_case = sway_types::style::to_upper_camel_case(decl_kind);
2358 Diagnostic {
2359 reason: Some(Reason::new(code(1), "Type contains duplicate declarations".to_string())),
2360 issue: Issue::error(
2361 source_engine,
2362 second_impl_span.clone(),
2363 if type_implementing_for == type_implementing_for_unaliased {
2364 format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\".")
2365 } else {
2366 format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").")
2367 }
2368 ),
2369 hints: vec![
2370 Hint::info(
2371 source_engine,
2372 existing_impl_span.clone(),
2373 format!("\"{decl_name}\" previously defined here.")
2374 )
2375 ],
2376 help: vec![
2377 "A type may not contain two or more declarations of the same name".to_string(),
2378 ],
2379 }
2380 },
2381 MarkerTraitExplicitlyImplemented { marker_trait_full_name, span} => Diagnostic {
2382 reason: Some(Reason::new(code(1), "Marker traits cannot be explicitly implemented".to_string())),
2383 issue: Issue::error(
2384 source_engine,
2385 span.clone(),
2386 format!("Trait \"{marker_trait_full_name}\" is a marker trait and cannot be explicitly implemented.")
2387 ),
2388 hints: vec![],
2389 help: match marker_trait_name(marker_trait_full_name) {
2390 "Error" => vec![
2391 "\"Error\" marker trait is automatically implemented by the compiler for string slices".to_string(),
2392 "and enums annotated with the `#[error_type]` attribute.".to_string(),
2393 ],
2394 "Enum" => vec![
2395 "\"Enum\" marker trait is automatically implemented by the compiler for all enum types.".to_string(),
2396 ],
2397 _ => vec![],
2398 }
2399 },
2400 AssignmentToNonMutableVariable { lhs_span, decl_name } => Diagnostic {
2401 reason: Some(Reason::new(code(1), "Immutable variables cannot be assigned to".to_string())),
2402 issue: Issue::error(
2403 source_engine,
2404 lhs_span.clone(),
2405 format!("{} cannot be assigned to, because {} is an immutable variable.",
2409 if decl_name.as_str() == lhs_span.as_str() { format!("\"{decl_name}\"")
2411 } else {
2412 "This expression".to_string()
2413 },
2414 if decl_name.as_str() == lhs_span.as_str() {
2415 "it".to_string()
2416 } else {
2417 format!("\"{decl_name}\"")
2418 }
2419 )
2420 ),
2421 hints: vec![
2422 Hint::info(
2423 source_engine,
2424 decl_name.span(),
2425 format!("Variable \"{decl_name}\" is declared here as immutable.")
2426 ),
2427 ],
2428 help: vec![
2429 format!("Consider declaring \"{decl_name}\" as mutable."),
2431 ],
2432 },
2433 AssignmentToConstantOrConfigurable { lhs_span, is_configurable, decl_name } => Diagnostic {
2434 reason: Some(Reason::new(code(1), format!("{} cannot be assigned to",
2435 if *is_configurable {
2436 "Configurables"
2437 } else {
2438 "Constants"
2439 }
2440 ))),
2441 issue: Issue::error(
2442 source_engine,
2443 lhs_span.clone(),
2444 format!("{} cannot be assigned to, because {} is a {}.",
2448 if decl_name.as_str() == lhs_span.as_str() { format!("\"{decl_name}\"")
2450 } else {
2451 "This expression".to_string()
2452 },
2453 if decl_name.as_str() == lhs_span.as_str() {
2454 "it".to_string()
2455 } else {
2456 format!("\"{decl_name}\"")
2457 },
2458 if *is_configurable {
2459 "configurable"
2460 } else {
2461 "constant"
2462 }
2463 )
2464 ),
2465 hints: vec![
2466 Hint::info(
2467 source_engine,
2468 decl_name.span(),
2469 format!("{} \"{decl_name}\" is declared here.",
2470 if *is_configurable {
2471 "Configurable"
2472 } else {
2473 "Constant"
2474 }
2475 )
2476 ),
2477 ],
2478 help: vec![],
2479 },
2480 DeclAssignmentTargetCannotBeAssignedTo { decl_name, decl_friendly_type_name, lhs_span } => Diagnostic {
2481 reason: Some(Reason::new(code(1), "Assignment target cannot be assigned to".to_string())),
2482 issue: Issue::error(
2483 source_engine,
2484 lhs_span.clone(),
2485 format!("{} cannot be assigned to, because {} is {}{decl_friendly_type_name} and not a mutable variable.",
2489 match decl_name {
2490 Some(decl_name) if decl_name.as_str() == lhs_span.as_str() => format!("\"{decl_name}\""),
2492 _ => "This".to_string(),
2493 },
2494 match decl_name {
2495 Some(decl_name) if decl_name.as_str() == lhs_span.as_str() =>
2496 "it".to_string(),
2497 Some(decl_name) => format!("\"{}\"", decl_name.as_str()),
2498 _ => "it".to_string(),
2499 },
2500 a_or_an(decl_friendly_type_name)
2501 )
2502 ),
2503 hints: vec![
2504 match decl_name {
2505 Some(decl_name) => Hint::info(
2506 source_engine,
2507 decl_name.span(),
2508 format!("{} \"{decl_name}\" is declared here.", ascii_sentence_case(&decl_friendly_type_name.to_string()))
2509 ),
2510 _ => Hint::none(),
2511 }
2512 ],
2513 help: vec![],
2514 },
2515 AssignmentViaNonMutableReference { decl_reference_name, decl_reference_rhs, decl_reference_type, span } => Diagnostic {
2516 reason: Some(Reason::new(code(1), "Reference is not a reference to a mutable value (`&mut`)".to_string())),
2517 issue: Issue::error(
2518 source_engine,
2519 span.clone(),
2520 format!("{} is not a reference to a mutable value (`&mut`).",
2524 match decl_reference_name {
2525 Some(decl_reference_name) => format!("Reference \"{decl_reference_name}\""),
2526 _ => "This reference expression".to_string(),
2527 }
2528 )
2529 ),
2530 hints: vec![
2531 match decl_reference_name {
2532 Some(decl_reference_name) => Hint::info(
2533 source_engine,
2534 decl_reference_name.span(),
2535 format!("Reference \"{decl_reference_name}\" is declared here as a reference to immutable value.")
2536 ),
2537 _ => Hint::none(),
2538 },
2539 match decl_reference_rhs {
2540 Some(decl_reference_rhs) => Hint::info(
2541 source_engine,
2542 decl_reference_rhs.clone(),
2543 format!("This expression has type \"{decl_reference_type}\" instead of \"&mut {}\".",
2544 &decl_reference_type[1..]
2545 )
2546 ),
2547 _ => Hint::info(
2548 source_engine,
2549 span.clone(),
2550 format!("It has type \"{decl_reference_type}\" instead of \"&mut {}\".",
2551 &decl_reference_type[1..]
2552 )
2553 ),
2554 },
2555 match decl_reference_rhs {
2556 Some(decl_reference_rhs) if decl_reference_rhs.as_str().starts_with('&') => Hint::help(
2557 source_engine,
2558 decl_reference_rhs.clone(),
2559 format!("Consider taking here a reference to a mutable value: `&mut {}`.",
2560 first_line(decl_reference_rhs.as_str()[1..].trim(), true)
2561 )
2562 ),
2563 _ => Hint::none(),
2564 },
2565 ],
2566 help: vec![
2567 format!("{} dereferenced in assignment targets must {} references to mutable values (`&mut`).",
2568 if decl_reference_name.is_some() {
2569 "References"
2570 } else {
2571 "Reference expressions"
2572 },
2573 if decl_reference_name.is_some() {
2574 "be"
2575 } else {
2576 "result in"
2577 }
2578 ),
2579 ],
2580 },
2581 Unimplemented { feature, help, span } => Diagnostic {
2582 reason: Some(Reason::new(code(1), "Used feature is currently not implemented".to_string())),
2583 issue: Issue::error(
2584 source_engine,
2585 span.clone(),
2586 format!("{feature} is currently not implemented.")
2587 ),
2588 hints: vec![],
2589 help: help.clone(),
2590 },
2591 MatchedValueIsNotValid { supported_types_message, span } => Diagnostic {
2592 reason: Some(Reason::new(code(1), "Matched value is not valid".to_string())),
2593 issue: Issue::error(
2594 source_engine,
2595 span.clone(),
2596 "This cannot be matched.".to_string()
2597 ),
2598 hints: vec![],
2599 help: {
2600 let mut help = vec![];
2601
2602 help.push("Matched value must be an expression whose result is of one of the types supported in pattern matching.".to_string());
2603 help.push(Diagnostic::help_empty_line());
2604 for msg in supported_types_message {
2605 help.push(msg.to_string());
2606 }
2607
2608 help
2609 }
2610 },
2611 TypeIsNotValidAsImplementingFor { invalid_type, trait_name, span } => Diagnostic {
2612 reason: Some(Reason::new(code(1), "Self type of an impl block is not valid".to_string())),
2613 issue: Issue::error(
2614 source_engine,
2615 span.clone(),
2616 format!("{invalid_type} is not a valid type in the self type of {} impl block.",
2617 match trait_name {
2618 Some(_) => "a trait",
2619 None => "an",
2620 }
2621 )
2622 ),
2623 hints: vec![
2624 if matches!(invalid_type, InvalidImplementingForType::SelfType) {
2625 Hint::help(
2626 source_engine,
2627 span.clone(),
2628 format!("Replace {invalid_type} with the actual type that you want to implement for.")
2629 )
2630 } else {
2631 Hint::none()
2632 }
2633 ],
2634 help: {
2635 if matches!(invalid_type, InvalidImplementingForType::Placeholder) {
2636 vec![
2637 format!("Are you trying to implement {} for any type?",
2638 match trait_name {
2639 Some(trait_name) => format!("trait \"{trait_name}\""),
2640 None => "functionality".to_string(),
2641 }
2642 ),
2643 Diagnostic::help_empty_line(),
2644 "If so, use generic type parameters instead.".to_string(),
2645 "E.g., instead of:".to_string(),
2646 format!("{}impl {}_",
2655 Indent::Single,
2656 match trait_name {
2657 Some(_) => "SomeTrait for ",
2658 None => "",
2659 }
2660 ),
2661 "use:".to_string(),
2662 format!("{}impl<T> {}T",
2663 Indent::Single,
2664 match trait_name {
2665 Some(_) => "SomeTrait for ",
2666 None => "",
2667 }
2668 ),
2669 ]
2670 } else {
2671 vec![]
2672 }
2673 }
2674 },
2675 ModulePathIsNotAnExpression { module_path, span } => Diagnostic {
2676 reason: Some(Reason::new(code(1), "Module path is not an expression".to_string())),
2677 issue: Issue::error(
2678 source_engine,
2679 span.clone(),
2680 "This is a module path, and not an expression.".to_string()
2681 ),
2682 hints: vec![
2683 Hint::help(
2684 source_engine,
2685 span.clone(),
2686 "An expression is expected at this location, but a module path is found.".to_string()
2687 ),
2688 ],
2689 help: vec![
2690 "In expressions, module paths can only be used to fully qualify names with a path.".to_string(),
2691 format!("E.g., `{module_path}::SOME_CONSTANT` or `{module_path}::some_function()`."),
2692 ]
2693 },
2694 Parse { error } => {
2695 match &error.kind {
2696 ParseErrorKind::UnassignableExpression { erroneous_expression_kind, erroneous_expression_span } => Diagnostic {
2697 reason: Some(Reason::new(code(1), "Expression cannot be assigned to".to_string())),
2698 issue: Issue::error(
2703 source_engine,
2704 error.span.clone(),
2705 format!("This expression cannot be assigned to, because it {} {}{}.",
2706 if &error.span == erroneous_expression_span { "is"
2708 } else {
2709 "contains"
2710 },
2711 if *erroneous_expression_kind == "parentheses" {
2712 ""
2713 } else {
2714 a_or_an(erroneous_expression_kind)
2715 },
2716 erroneous_expression_kind
2717 )
2718 ),
2719 hints: vec![
2720 if &error.span != erroneous_expression_span {
2721 Hint::info(
2722 source_engine,
2723 erroneous_expression_span.clone(),
2724 format!("{} the contained {erroneous_expression_kind}.",
2725 if *erroneous_expression_kind == "parentheses" {
2726 "These are"
2727 } else {
2728 "This is"
2729 }
2730 )
2731 )
2732 } else {
2733 Hint::none()
2734 },
2735 ],
2736 help: vec![
2737 format!("{} cannot be {}an assignment target.",
2738 ascii_sentence_case(&erroneous_expression_kind.to_string()),
2739 if &error.span == erroneous_expression_span {
2740 ""
2741 } else {
2742 "a part of "
2743 }
2744 ),
2745 Diagnostic::help_empty_line(),
2746 "In Sway, assignment targets must be one of the following:".to_string(),
2747 format!("{}- Expressions starting with a mutable variable, optionally having", Indent::Single),
2748 format!("{} array or tuple element accesses, struct field accesses,", Indent::Single),
2749 format!("{} or arbitrary combinations of those.", Indent::Single),
2750 format!("{} E.g., `mut_var` or `mut_struct.field` or `mut_array[x + y].field.1`.", Indent::Single),
2751 Diagnostic::help_empty_line(),
2752 format!("{}- Dereferencing of an arbitrary expression that results", Indent::Single),
2753 format!("{} in a reference to a mutable value.", Indent::Single),
2754 format!("{} E.g., `*ref_to_mutable_value` or `*max_mut(&mut x, &mut y)`.", Indent::Single),
2755 ]
2756 },
2757 ParseErrorKind::UnrecognizedOpCode { known_op_codes } => Diagnostic {
2758 reason: Some(Reason::new(code(1), "Assembly instruction is unknown".to_string())),
2759 issue: Issue::error(
2760 source_engine,
2761 error.span.clone(),
2762 format!("\"{}\" is not a known assembly instruction.",
2763 error.span.as_str()
2764 )
2765 ),
2766 hints: {
2767 let suggestions = &did_you_mean(error.span.as_str(), known_op_codes.iter(), 2);
2768 if suggestions.is_empty() {
2769 vec![]
2770 } else {
2771 vec![
2772 Hint::help(
2773 source_engine,
2774 error.span.clone(),
2775 format!("Did you mean {}?", sequence_to_str_or(suggestions, Enclosing::DoubleQuote, 2))
2776 ),
2777 ]
2778 }
2779 },
2780 help: vec![]
2781 },
2782 _ => Diagnostic {
2783 issue: Issue::error(source_engine, self.span(), format!("{}", self)),
2788 ..Default::default()
2789 },
2790 }
2791 },
2792 ConfigurableMissingAbiDecodeInPlace { span } => Diagnostic {
2793 reason: Some(Reason::new(code(1), "Configurables need a function named \"abi_decode_in_place\" to be in scope".to_string())),
2794 issue: Issue::error(
2795 source_engine,
2796 span.clone(),
2797 String::new()
2798 ),
2799 hints: vec![],
2800 help: vec![
2801 "The function \"abi_decode_in_place\" is usually defined in the standard library module \"std::codec\".".into(),
2802 "Verify that you are using a version of the \"std\" standard library that contains this function.".into(),
2803 ],
2804 },
2805 StorageAccessMismatched { span, is_pure, suggested_attributes, storage_access_violations } => Diagnostic {
2806 reason: Some(Reason::new(code(1), format!("{} function cannot {} storage",
2810 if *is_pure {
2811 "Pure"
2812 } else {
2813 "Storage read-only"
2814 },
2815 if *is_pure {
2816 "access"
2817 } else {
2818 "write to"
2819 }
2820 ))),
2821 issue: Issue::error(
2822 source_engine,
2823 span.clone(),
2824 format!("Function \"{}\" is {} and cannot {} storage.",
2825 span.as_str(),
2826 if *is_pure {
2827 "pure"
2828 } else {
2829 "declared as `#[storage(read)]`"
2830 },
2831 if *is_pure {
2832 "access"
2833 } else {
2834 "write to"
2835 },
2836 )
2837 ),
2838 hints: storage_access_violations
2839 .iter()
2840 .map(|(span, storage_access)| Hint::info(
2841 source_engine,
2842 span.clone(),
2843 format!("{storage_access}")
2844 ))
2845 .collect(),
2846 help: vec![
2847 format!("Consider declaring the function \"{}\" as `#[{STORAGE_PURITY_ATTRIBUTE_NAME}({suggested_attributes})]`,",
2848 span.as_str()
2849 ),
2850 format!("or removing the {} from the function body.",
2851 if *is_pure {
2852 "storage access code".to_string()
2853 } else {
2854 format!("storage write{}", plural_s(storage_access_violations.len()))
2855 }
2856 ),
2857 ],
2858 },
2859 MultipleImplsSatisfyingTraitForType { span, type_annotation , trait_names, trait_types_and_names: trait_types_and_spans } => Diagnostic {
2860 reason: Some(Reason::new(code(1), format!("Multiple impls satisfying {} for {}", trait_names.join("+"), type_annotation))),
2861 issue: Issue::error(
2862 source_engine,
2863 span.clone(),
2864 String::new()
2865 ),
2866 hints: vec![],
2867 help: vec![format!("Trait{} implemented for types:\n{}", if trait_names.len() > 1 {"s"} else {""}, trait_types_and_spans.iter().enumerate().map(|(e, (type_id, name))|
2868 format!("#{} {} for {}", e, name, type_id.clone())
2869 ).collect::<Vec<_>>().join("\n"))],
2870 },
2871 MultipleContractsMethodsWithTheSameName { spans } => Diagnostic {
2872 reason: Some(Reason::new(code(1), "Multiple contracts methods with the same name.".into())),
2873 issue: Issue::error(
2874 source_engine,
2875 spans[0].clone(),
2876 "This is the first method".into()
2877 ),
2878 hints: spans.iter().skip(1).map(|span| {
2879 Hint::error(source_engine, span.clone(), "This is the duplicated method.".into())
2880 }).collect(),
2881 help: vec!["Contract methods names must be unique, even when implementing multiple ABIs.".into()],
2882 },
2883 FunctionSelectorClash { method_name, span, other_method_name, other_span } => Diagnostic {
2884 reason: Some(Reason::new(code(1), format!("Methods {method_name} and {other_method_name} have clashing function selectors."))),
2885 issue: Issue::error(
2886 source_engine,
2887 span.clone(),
2888 String::new()
2889 ),
2890 hints: vec![Hint::error(source_engine, other_span.clone(), format!("The declaration of {other_method_name} is here"))],
2891 help: vec![format!("The methods of a contract must have distinct function selectors, which are computed from the method hash. \nRenaming one of the methods should solve the problem")]
2892 },
2893 _ => Diagnostic {
2894 issue: Issue::error(source_engine, self.span(), format!("{}", self)),
2899 ..Default::default()
2900 }
2901 }
2902 }
2903}
2904
2905#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
2906pub enum TypeNotAllowedReason {
2907 #[error(
2908 "Returning a type containing `raw_slice` from `main()` is not allowed. \
2909 Consider converting it into a flat `raw_slice` first."
2910 )]
2911 NestedSliceReturnNotAllowedInMain,
2912
2913 #[error("The type \"{ty}\" is not allowed in storage.")]
2914 TypeNotAllowedInContractStorage { ty: String },
2915
2916 #[error("`str` or a type containing `str` on `main()` arguments is not allowed.")]
2917 StringSliceInMainParameters,
2918
2919 #[error("Returning `str` or a type containing `str` from `main()` is not allowed.")]
2920 StringSliceInMainReturn,
2921
2922 #[error("`str` or a type containing `str` on `configurables` is not allowed.")]
2923 StringSliceInConfigurables,
2924
2925 #[error("`str` or a type containing `str` on `const` is not allowed.")]
2926 StringSliceInConst,
2927
2928 #[error("slices or types containing slices on `const` are not allowed.")]
2929 SliceInConst,
2930
2931 #[error("references, pointers, slices, string slices or types containing any of these are not allowed.")]
2932 NotAllowedInTransmute,
2933}
2934
2935#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2936pub enum StructFieldUsageContext {
2937 StructInstantiation { struct_can_be_instantiated: bool },
2938 StorageDeclaration { struct_can_be_instantiated: bool },
2939 StorageAccess,
2940 PatternMatching { has_rest_pattern: bool },
2941 StructFieldAccess,
2942 }
2947
2948#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2949pub enum InvalidImplementingForType {
2950 SelfType,
2951 Placeholder,
2952 Other,
2953}
2954
2955impl fmt::Display for InvalidImplementingForType {
2956 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2957 match self {
2958 Self::SelfType => f.write_str("\"Self\""),
2959 Self::Placeholder => f.write_str("Placeholder `_`"),
2960 Self::Other => f.write_str("This"),
2961 }
2962 }
2963}
2964
2965#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2967pub enum ShadowingSource {
2968 Const,
2970 LetVar,
2972 PatternMatchingStructFieldVar,
2975}
2976
2977impl fmt::Display for ShadowingSource {
2978 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2979 match self {
2980 Self::Const => f.write_str("Constant"),
2981 Self::LetVar => f.write_str("Variable"),
2982 Self::PatternMatchingStructFieldVar => f.write_str("Pattern variable"),
2983 }
2984 }
2985}
2986
2987#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2991pub enum StorageAccess {
2992 Clear,
2993 ReadWord,
2994 ReadSlots,
2995 WriteWord,
2996 WriteSlots,
2997 ImpureFunctionCall(Span, bool, bool),
3001}
3002
3003impl StorageAccess {
3004 pub fn is_write(&self) -> bool {
3005 matches!(
3006 self,
3007 Self::Clear | Self::WriteWord | Self::WriteSlots | Self::ImpureFunctionCall(_, _, true)
3008 )
3009 }
3010}
3011
3012impl fmt::Display for StorageAccess {
3013 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3014 match self {
3015 Self::Clear => f.write_str("Clearing the storage happens here."),
3016 Self::ReadWord => f.write_str("Reading a word from the storage happens here."),
3017 Self::ReadSlots => f.write_str("Reading storage slots happens here."),
3018 Self::WriteWord => f.write_str("Writing a word to the storage happens here."),
3019 Self::WriteSlots => f.write_str("Writing to storage slots happens here."),
3020 Self::ImpureFunctionCall(call_path, reads, writes) => f.write_fmt(format_args!(
3021 "Function \"{}\" {} the storage.",
3022 call_path_suffix_with_args(&call_path.as_str().to_string()),
3023 match (reads, writes) {
3024 (true, true) => "reads from and writes to",
3025 (true, false) => "reads from",
3026 (false, true) => "writes to",
3027 (false, false) => unreachable!(
3028 "Function \"{}\" is impure, so it must read from or write to the storage.",
3029 call_path.as_str()
3030 ),
3031 }
3032 )),
3033 }
3034 }
3035}
3036
3037fn marker_trait_name(marker_trait_full_name: &str) -> &str {
3045 const MARKER_TRAITS_MODULE: &str = "std::marker::";
3046 assert!(
3047 marker_trait_full_name.starts_with(MARKER_TRAITS_MODULE),
3048 "`marker_trait_full_name` must start with \"std::marker::\", but it was \"{}\"",
3049 marker_trait_full_name
3050 );
3051
3052 let lower_boundary = MARKER_TRAITS_MODULE.len();
3053 let name_part = &marker_trait_full_name[lower_boundary..];
3054
3055 let upper_boundary = marker_trait_full_name.len() - lower_boundary;
3056 let only_name_len = std::cmp::min(
3057 name_part.find(':').unwrap_or(upper_boundary),
3058 name_part.find('<').unwrap_or(upper_boundary),
3059 );
3060 let upper_boundary = lower_boundary + only_name_len;
3061
3062 &marker_trait_full_name[lower_boundary..upper_boundary]
3063}