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