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