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