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