cairo_lang_semantic/
diagnostic.rs

1use std::fmt::Display;
2
3use cairo_lang_debug::DebugWithDb;
4use cairo_lang_defs::diagnostic_utils::StableLocation;
5use cairo_lang_defs::ids::{
6    EnumId, FunctionTitleId, GenericKind, ImplDefId, ImplFunctionId, ModuleId, ModuleItemId,
7    NamedLanguageElementId, StructId, TopLevelLanguageElementId, TraitFunctionId, TraitId,
8    TraitImplId, TraitItemId, UseId,
9};
10use cairo_lang_defs::plugin::PluginDiagnostic;
11use cairo_lang_diagnostics::{
12    DiagnosticAdded, DiagnosticEntry, DiagnosticNote, DiagnosticsBuilder, ErrorCode, Severity,
13    error_code,
14};
15use cairo_lang_filesystem::db::Edition;
16use cairo_lang_filesystem::ids::{SmolStrId, SpanInFile};
17use cairo_lang_filesystem::span::TextWidth;
18use cairo_lang_parser::ParserDiagnostic;
19use cairo_lang_syntax as syntax;
20use cairo_lang_syntax::node::ast;
21use cairo_lang_syntax::node::helpers::GetIdentifier;
22use itertools::Itertools;
23use salsa::Database;
24use syntax::node::ids::SyntaxStablePtrId;
25
26use crate::corelib::LiteralError;
27use crate::expr::inference::InferenceError;
28use crate::items::feature_kind::FeatureMarkerDiagnostic;
29use crate::items::trt::ConcreteTraitTypeId;
30use crate::resolve::{ResolvedConcreteItem, ResolvedGenericItem};
31use crate::types::peel_snapshots;
32use crate::{ConcreteTraitId, semantic};
33
34#[cfg(test)]
35#[path = "diagnostic_test.rs"]
36mod test;
37
38pub type SemanticDiagnostics<'db> = DiagnosticsBuilder<'db, SemanticDiagnostic<'db>>;
39pub trait SemanticDiagnosticsBuilder<'db> {
40    /// Report a diagnostic in the location of the given ptr.
41    fn report(
42        &mut self,
43        stable_ptr: impl Into<SyntaxStablePtrId<'db>>,
44        kind: SemanticDiagnosticKind<'db>,
45    ) -> DiagnosticAdded;
46    /// Report a diagnostic in the location after the given ptr (with width 0).
47    fn report_after(
48        &mut self,
49        stable_ptr: impl Into<SyntaxStablePtrId<'db>>,
50        kind: SemanticDiagnosticKind<'db>,
51    ) -> DiagnosticAdded;
52    /// Report a diagnostic in a sub-span of the location of the given ptr. The inner span is
53    /// specified by an offset from the start of the pointer location and a width.
54    fn report_with_inner_span(
55        &mut self,
56        stable_ptr: impl Into<SyntaxStablePtrId<'db>>,
57        inner_span: (TextWidth, TextWidth),
58        kind: SemanticDiagnosticKind<'db>,
59    ) -> DiagnosticAdded;
60}
61impl<'db> SemanticDiagnosticsBuilder<'db> for SemanticDiagnostics<'db> {
62    fn report(
63        &mut self,
64        stable_ptr: impl Into<SyntaxStablePtrId<'db>>,
65        kind: SemanticDiagnosticKind<'db>,
66    ) -> DiagnosticAdded {
67        self.add(SemanticDiagnostic::new(StableLocation::new(stable_ptr.into()), kind))
68    }
69    fn report_after(
70        &mut self,
71        stable_ptr: impl Into<SyntaxStablePtrId<'db>>,
72        kind: SemanticDiagnosticKind<'db>,
73    ) -> DiagnosticAdded {
74        self.add(SemanticDiagnostic::new_after(StableLocation::new(stable_ptr.into()), kind))
75    }
76    fn report_with_inner_span(
77        &mut self,
78        stable_ptr: impl Into<SyntaxStablePtrId<'db>>,
79        inner_span: (TextWidth, TextWidth),
80        kind: SemanticDiagnosticKind<'db>,
81    ) -> DiagnosticAdded {
82        self.add(SemanticDiagnostic::new(
83            StableLocation::with_inner_span(stable_ptr.into(), inner_span),
84            kind,
85        ))
86    }
87}
88
89#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
90pub struct SemanticDiagnostic<'db> {
91    pub stable_location: StableLocation<'db>,
92    pub kind: SemanticDiagnosticKind<'db>,
93    /// true if the diagnostic should be reported *after* the given location. Normally false, in
94    /// which case the diagnostic points to the given location (as-is).
95    pub after: bool,
96}
97impl<'db> SemanticDiagnostic<'db> {
98    /// Create a diagnostic in the given location.
99    pub fn new(stable_location: StableLocation<'db>, kind: SemanticDiagnosticKind<'db>) -> Self {
100        SemanticDiagnostic { stable_location, kind, after: false }
101    }
102    /// Create a diagnostic in the location after the given location (with width 0).
103    pub fn new_after(
104        stable_location: StableLocation<'db>,
105        kind: SemanticDiagnosticKind<'db>,
106    ) -> Self {
107        SemanticDiagnostic { stable_location, kind, after: true }
108    }
109}
110impl<'db> DiagnosticEntry<'db> for SemanticDiagnostic<'db> {
111    fn format(&self, db: &dyn Database) -> String {
112        match &self.kind {
113            SemanticDiagnosticKind::ModuleFileNotFound(path) => {
114                format!("Module file not found. Expected path: {path}")
115            }
116            SemanticDiagnosticKind::Unsupported => "Unsupported feature.".into(),
117            SemanticDiagnosticKind::UnknownLiteral => "Unknown literal.".into(),
118            SemanticDiagnosticKind::UnknownBinaryOperator => "Unknown binary operator.".into(),
119            SemanticDiagnosticKind::UnknownTrait => "Unknown trait.".into(),
120            SemanticDiagnosticKind::UnknownImpl => "Unknown impl.".into(),
121            SemanticDiagnosticKind::UnexpectedElement { expected, actual } => {
122                let expected_str = expected.iter().map(|kind| kind.to_string()).join(" or ");
123                format!("Expected {expected_str}, found {actual}.")
124            }
125            SemanticDiagnosticKind::UnknownType => "Unknown type.".into(),
126            SemanticDiagnosticKind::UnknownEnum => "Unknown enum.".into(),
127            SemanticDiagnosticKind::LiteralError(literal_error) => literal_error.format(db),
128            SemanticDiagnosticKind::NotAVariant => {
129                "Not a variant. Use the full name Enum::Variant.".into()
130            }
131            SemanticDiagnosticKind::NotAStruct => "Not a struct.".into(),
132            SemanticDiagnosticKind::NotAType => "Not a type.".into(),
133            SemanticDiagnosticKind::NotATrait => "Not a trait.".into(),
134            SemanticDiagnosticKind::NotAnImpl => "Not an impl.".into(),
135            SemanticDiagnosticKind::ImplItemNotInTrait {
136                impl_def_id,
137                impl_item_name,
138                trait_id,
139                item_kind,
140            } => {
141                format!(
142                    "Impl item {item_kind} `{}::{}` is not a member of trait `{}`.",
143                    impl_def_id.name(db).long(db),
144                    impl_item_name.long(db),
145                    trait_id.name(db).long(db)
146                )
147            }
148            SemanticDiagnosticKind::ImplicitImplNotInferred {
149                trait_impl_id,
150                concrete_trait_id,
151            } => {
152                format!(
153                    "Cannot infer implicit impl `{}.`\nCould not find implementation of trait \
154                     `{:?}`",
155                    trait_impl_id.name(db).long(db),
156                    concrete_trait_id.debug(db)
157                )
158            }
159            SemanticDiagnosticKind::GenericsNotSupportedInItem { scope, item_kind } => {
160                format!("Generic parameters are not supported in {scope} item {item_kind}.")
161            }
162            SemanticDiagnosticKind::UnexpectedGenericArgs => "Unexpected generic arguments".into(),
163            SemanticDiagnosticKind::UnknownMember => "Unknown member.".into(),
164            SemanticDiagnosticKind::MemberSpecifiedMoreThanOnce => {
165                "Member specified more than once.".into()
166            }
167            SemanticDiagnosticKind::ConstCycle => {
168                "Cycle detected while resolving 'const' items.".into()
169            }
170            SemanticDiagnosticKind::UseCycle => {
171                "Cycle detected while resolving 'use' items.".into()
172            }
173            SemanticDiagnosticKind::TypeAliasCycle => {
174                "Cycle detected while resolving type-alias/impl-type items.".into()
175            }
176            SemanticDiagnosticKind::ImplAliasCycle => {
177                "Cycle detected while resolving 'impls alias' items.".into()
178            }
179            SemanticDiagnosticKind::ImplRequirementCycle => {
180                "Cycle detected while resolving generic param. Try specifying the generic impl \
181                 parameter explicitly to break the cycle."
182                    .into()
183            }
184            SemanticDiagnosticKind::MissingMember(member_name) => {
185                format!(r#"Missing member "{}"."#, member_name.long(db))
186            }
187            SemanticDiagnosticKind::WrongNumberOfParameters {
188                impl_def_id,
189                impl_function_id,
190                trait_id,
191                expected,
192                actual,
193            } => {
194                let function_name = impl_function_id.name(db).long(db);
195                format!(
196                    "The number of parameters in the impl function `{}::{}` is incompatible with \
197                     `{}::{}`. Expected: {}, actual: {}.",
198                    impl_def_id.name(db).long(db),
199                    function_name,
200                    trait_id.name(db).long(db),
201                    function_name,
202                    expected,
203                    actual,
204                )
205            }
206            SemanticDiagnosticKind::WrongNumberOfArguments { expected, actual } => {
207                format!("Wrong number of arguments. Expected {expected}, found: {actual}")
208            }
209            SemanticDiagnosticKind::WrongParameterType {
210                impl_def_id,
211                impl_function_id,
212                trait_id,
213                expected_ty,
214                actual_ty,
215            } => {
216                let function_name = impl_function_id.name(db).long(db);
217                format!(
218                    "Parameter type of impl function `{}::{}` is incompatible with `{}::{}`. \
219                     Expected: `{}`, actual: `{}`.",
220                    impl_def_id.name(db).long(db),
221                    function_name,
222                    trait_id.name(db).long(db),
223                    function_name,
224                    expected_ty.format(db),
225                    actual_ty.format(db)
226                )
227            }
228            SemanticDiagnosticKind::VariantCtorNotImmutable => {
229                "Variant constructor argument must be immutable.".to_string()
230            }
231            SemanticDiagnosticKind::TraitParamMutable { trait_id, function_id } => {
232                format!(
233                    "Parameter of trait function `{}::{}` can't be defined as mutable.",
234                    trait_id.name(db).long(db),
235                    function_id.name(db).long(db),
236                )
237            }
238            SemanticDiagnosticKind::ParameterShouldBeReference {
239                impl_def_id,
240                impl_function_id,
241                trait_id,
242            } => {
243                let function_name = impl_function_id.name(db).long(db);
244                format!(
245                    "Parameter of impl function {}::{} is incompatible with {}::{}. It should be \
246                     a reference.",
247                    impl_def_id.name(db).long(db),
248                    function_name,
249                    trait_id.name(db).long(db),
250                    function_name,
251                )
252            }
253            SemanticDiagnosticKind::ParameterShouldNotBeReference {
254                impl_def_id,
255                impl_function_id,
256                trait_id,
257            } => {
258                let function_name = impl_function_id.name(db).long(db);
259                format!(
260                    "Parameter of impl function {}::{} is incompatible with {}::{}. It should not \
261                     be a reference.",
262                    impl_def_id.name(db).long(db),
263                    function_name,
264                    trait_id.name(db).long(db),
265                    function_name,
266                )
267            }
268            SemanticDiagnosticKind::WrongParameterName {
269                impl_def_id,
270                impl_function_id,
271                trait_id,
272                expected_name,
273            } => {
274                let function_name = impl_function_id.name(db).long(db);
275                format!(
276                    "Parameter name of impl function {}::{function_name} is incompatible with \
277                     {}::{function_name} parameter `{}`.",
278                    impl_def_id.name(db).long(db),
279                    trait_id.name(db).long(db),
280                    expected_name.long(db)
281                )
282            }
283            SemanticDiagnosticKind::WrongType { expected_ty, actual_ty } => {
284                format!(
285                    r#"Expected type "{}", found: "{}"."#,
286                    expected_ty.format(db),
287                    actual_ty.format(db)
288                )
289            }
290            SemanticDiagnosticKind::InconsistentBinding => "variable is bound inconsistently \
291                                                            across alternatives separated by `|` \
292                                                            bound in different ways"
293                .into(),
294            SemanticDiagnosticKind::WrongArgumentType { expected_ty, actual_ty } => {
295                let diagnostic_prefix = format!(
296                    r#"Unexpected argument type. Expected: "{}", found: "{}"."#,
297                    expected_ty.format(db),
298                    actual_ty.format(db)
299                );
300                if (expected_ty.is_fully_concrete(db) && actual_ty.is_fully_concrete(db))
301                    || peel_snapshots(db, *expected_ty).0 == peel_snapshots(db, *actual_ty).0
302                {
303                    diagnostic_prefix
304                } else {
305                    format!(
306                        "{diagnostic_prefix}\nIt is possible that the type inference failed \
307                         because the types differ in the number of snapshots.\nConsider adding or \
308                         removing snapshots."
309                    )
310                }
311            }
312            SemanticDiagnosticKind::WrongReturnType { expected_ty, actual_ty } => {
313                format!(
314                    r#"Unexpected return type. Expected: "{}", found: "{}"."#,
315                    expected_ty.format(db),
316                    actual_ty.format(db)
317                )
318            }
319            SemanticDiagnosticKind::WrongExprType { expected_ty, actual_ty } => {
320                format!(
321                    r#"Unexpected expression type. Expected: "{}", found: "{}"."#,
322                    expected_ty.format(db),
323                    actual_ty.format(db)
324                )
325            }
326            SemanticDiagnosticKind::WrongNumberOfGenericParamsForImplFunction {
327                expected,
328                actual,
329            } => {
330                format!(
331                    "Wrong number of generic parameters for impl function. Expected: {expected}, \
332                     found: {actual}."
333                )
334            }
335            SemanticDiagnosticKind::WrongReturnTypeForImpl {
336                impl_def_id,
337                impl_function_id,
338                trait_id,
339                expected_ty,
340                actual_ty,
341            } => {
342                let function_name = impl_function_id.name(db).long(db);
343                format!(
344                    "Return type of impl function `{}::{}` is incompatible with `{}::{}`. \
345                     Expected: `{}`, actual: `{}`.",
346                    impl_def_id.name(db).long(db),
347                    function_name,
348                    trait_id.name(db).long(db),
349                    function_name,
350                    expected_ty.format(db),
351                    actual_ty.format(db)
352                )
353            }
354            SemanticDiagnosticKind::WrongGenericParamTraitForImplFunction {
355                impl_def_id,
356                impl_function_id,
357                trait_id,
358                expected_trait,
359                actual_trait,
360            } => {
361                let function_name = impl_function_id.name(db).long(db);
362                format!(
363                    "Generic parameter trait of impl function `{}::{}` is incompatible with \
364                     `{}::{}`. Expected: `{:?}`, actual: `{:?}`.",
365                    impl_def_id.name(db).long(db),
366                    function_name,
367                    trait_id.name(db).long(db),
368                    function_name,
369                    expected_trait.debug(db),
370                    actual_trait.debug(db)
371                )
372            }
373            SemanticDiagnosticKind::WrongGenericParamKindForImplFunction {
374                impl_def_id,
375                impl_function_id,
376                trait_id,
377                expected_kind,
378                actual_kind,
379            } => {
380                let function_name = impl_function_id.name(db).long(db);
381                format!(
382                    "Generic parameter kind of impl function `{}::{}` is incompatible with \
383                     `{}::{}`. Expected: `{:?}`, actual: `{:?}`.",
384                    impl_def_id.name(db).long(db),
385                    function_name,
386                    trait_id.name(db).long(db),
387                    function_name,
388                    expected_kind,
389                    actual_kind
390                )
391            }
392            SemanticDiagnosticKind::AmbiguousTrait { trait_function_id0, trait_function_id1 } => {
393                format!(
394                    "Ambiguous method call. More than one applicable trait function with a \
395                     suitable self type was found: {} and {}. Consider adding type annotations or \
396                     explicitly refer to the impl function.",
397                    trait_function_id0.full_path(db),
398                    trait_function_id1.full_path(db)
399                )
400            }
401            SemanticDiagnosticKind::VariableNotFound(name) => {
402                format!(r#"Variable "{}" not found."#, name.long(db))
403            }
404            SemanticDiagnosticKind::MissingVariableInPattern => {
405                "Missing variable in pattern.".into()
406            }
407            SemanticDiagnosticKind::VariableDefinedMultipleTimesInPattern(name) => {
408                format!(r#"Redefinition of variable name "{}" in pattern."#, name.long(db))
409            }
410            SemanticDiagnosticKind::StructMemberRedefinition { struct_id, member_name } => {
411                format!(
412                    r#"Redefinition of member "{}" on struct "{}"."#,
413                    member_name.long(db),
414                    struct_id.full_path(db)
415                )
416            }
417            SemanticDiagnosticKind::EnumVariantRedefinition { enum_id, variant_name } => {
418                format!(
419                    r#"Redefinition of variant "{}" on enum "{}"."#,
420                    variant_name.long(db),
421                    enum_id.full_path(db)
422                )
423            }
424            SemanticDiagnosticKind::InfiniteSizeType(ty) => {
425                format!(r#"Recursive type "{}" has infinite size."#, ty.format(db))
426            }
427            SemanticDiagnosticKind::ArrayOfZeroSizedElements(ty) => {
428                format!(r#"Cannot have array of type "{}" that is zero sized."#, ty.format(db))
429            }
430            SemanticDiagnosticKind::ParamNameRedefinition { function_title_id, param_name } => {
431                format!(
432                    r#"Redefinition of parameter name "{}"{}"#,
433                    param_name.long(db),
434                    function_title_id
435                        .map(|function_title_id| format!(
436                            r#" in function "{}"."#,
437                            function_title_id.full_path(db)
438                        ))
439                        .unwrap_or(".".into()),
440                )
441            }
442            SemanticDiagnosticKind::ConditionNotBool(condition_ty) => {
443                format!(r#"Condition has type "{}", expected bool."#, condition_ty.format(db))
444            }
445            SemanticDiagnosticKind::IncompatibleArms {
446                multi_arm_expr_kind: incompatibility_kind,
447                pending_ty: first_ty,
448                different_ty,
449            } => {
450                let prefix = match incompatibility_kind {
451                    MultiArmExprKind::Match => "Match arms have incompatible types",
452                    MultiArmExprKind::If => "If blocks have incompatible types",
453                    MultiArmExprKind::Loop => "Loop has incompatible return types",
454                };
455                format!(r#"{prefix}: "{}" and "{}""#, first_ty.format(db), different_ty.format(db))
456            }
457            SemanticDiagnosticKind::TypeHasNoMembers { ty, member_name: _ } => {
458                format!(r#"Type "{}" has no members."#, ty.format(db))
459            }
460            SemanticDiagnosticKind::NoSuchStructMember { struct_id, member_name } => {
461                format!(
462                    r#"Struct "{}" has no member "{}""#,
463                    struct_id.full_path(db),
464                    member_name.long(db)
465                )
466            }
467            SemanticDiagnosticKind::NoSuchTypeMember { ty, member_name } => {
468                format!(r#"Type "{}" has no member "{}""#, ty.format(db), member_name.long(db))
469            }
470            SemanticDiagnosticKind::MemberNotVisible(member_name) => {
471                format!(r#"Member "{}" is not visible in this context."#, member_name.long(db))
472            }
473            SemanticDiagnosticKind::NoSuchVariant { enum_id, variant_name } => {
474                format!(
475                    r#"Enum "{}" has no variant "{}""#,
476                    enum_id.full_path(db),
477                    variant_name.long(db)
478                )
479            }
480            SemanticDiagnosticKind::ReturnTypeNotErrorPropagateType => {
481                "`?` can only be used in a function with `Option` or `Result` return type.".into()
482            }
483            SemanticDiagnosticKind::IncompatibleErrorPropagateType { return_ty, err_ty } => {
484                format!(
485                    r#"Return type "{}" does not wrap error "{}""#,
486                    return_ty.format(db),
487                    err_ty.format(db)
488                )
489            }
490            SemanticDiagnosticKind::ErrorPropagateOnNonErrorType(ty) => {
491                format!(r#"Type "{}" can not error propagate"#, ty.format(db))
492            }
493            SemanticDiagnosticKind::UnhandledMustUseType(ty) => {
494                format!(r#"Unhandled `#[must_use]` type `{}`"#, ty.format(db))
495            }
496            SemanticDiagnosticKind::UnhandledMustUseFunction => {
497                "Unhandled `#[must_use]` function.".into()
498            }
499            SemanticDiagnosticKind::UnstableFeature { feature_name, note } => {
500                format!(
501                    "Usage of unstable feature `{0}` with no `#[feature({0})]` attribute.{1}",
502                    feature_name.long(db),
503                    note.as_ref()
504                        .map(|note| format!(" Note: {}", note.long(db)))
505                        .unwrap_or_default()
506                )
507            }
508            SemanticDiagnosticKind::DeprecatedFeature { feature_name, note } => {
509                format!(
510                    "Usage of deprecated feature `{0}` with no `#[feature({0})]` attribute.{1}",
511                    feature_name.long(db),
512                    note.as_ref()
513                        .map(|note| format!(" Note: {}", note.long(db)))
514                        .unwrap_or_default()
515                )
516            }
517            SemanticDiagnosticKind::InternalFeature { feature_name, note } => {
518                format!(
519                    "Usage of internal feature `{0}` with no `#[feature({0})]` attribute.{1}",
520                    feature_name.long(db),
521                    note.as_ref()
522                        .map(|note| format!(" Note: {}", note.long(db)))
523                        .unwrap_or_default()
524                )
525            }
526            SemanticDiagnosticKind::FeatureMarkerDiagnostic(diagnostic) => match diagnostic {
527                FeatureMarkerDiagnostic::MultipleMarkers => {
528                    "Multiple feature marker attributes.".into()
529                }
530                FeatureMarkerDiagnostic::MissingAllowFeature => {
531                    "Missing `feature` arg for feature marker attribute.".into()
532                }
533                FeatureMarkerDiagnostic::UnsupportedArgument => {
534                    "Unsupported argument for feature marker attribute.".into()
535                }
536                FeatureMarkerDiagnostic::DuplicatedArgument => {
537                    "Duplicated argument for feature marker attribute.".into()
538                }
539            },
540            SemanticDiagnosticKind::UnusedVariable => {
541                "Unused variable. Consider ignoring by prefixing with `_`.".into()
542            }
543            SemanticDiagnosticKind::UnusedConstant => {
544                "Unused constant. Consider ignoring by prefixing with `_`.".into()
545            }
546            SemanticDiagnosticKind::MultipleConstantDefinition(constant_name) => {
547                format!(r#"Multiple definitions of constant "{}"."#, constant_name.long(db))
548            }
549            SemanticDiagnosticKind::UnusedUse => "Unused use.".into(),
550            SemanticDiagnosticKind::MultipleDefinitionforBinding(name) => {
551                format!(
552                    r#"Multiple definitions of identifier '{}' as constant and variable."#,
553                    name.long(db)
554                )
555            }
556            SemanticDiagnosticKind::MultipleGenericItemDefinition(type_name) => {
557                format!(r#"Multiple definitions of an item "{}"."#, type_name.long(db))
558            }
559            SemanticDiagnosticKind::UnsupportedUseItemInStatement => {
560                "Unsupported use item in statement.".into()
561            }
562            SemanticDiagnosticKind::InvalidMemberExpression => "Invalid member expression.".into(),
563            SemanticDiagnosticKind::InvalidPath => "Invalid path.".into(),
564            SemanticDiagnosticKind::RefArgNotAVariable => "ref argument must be a variable.".into(),
565            SemanticDiagnosticKind::RefArgNotMutable => {
566                "ref argument must be a mutable variable.".into()
567            }
568            SemanticDiagnosticKind::RefArgNotExplicit => {
569                "ref argument must be passed with a preceding 'ref'.".into()
570            }
571            SemanticDiagnosticKind::ImmutableArgWithModifiers => {
572                "Argument to immutable parameter cannot have modifiers.".into()
573            }
574            SemanticDiagnosticKind::AssignmentToImmutableVar => {
575                "Cannot assign to an immutable variable.".into()
576            }
577            SemanticDiagnosticKind::InvalidLhsForAssignment => {
578                "Invalid left-hand side of assignment.".into()
579            }
580            SemanticDiagnosticKind::PathNotFound(item_type) => match item_type {
581                NotFoundItemType::Identifier => "Identifier not found.".into(),
582                NotFoundItemType::Function => "Function not found.".into(),
583                NotFoundItemType::Type => "Type not found.".into(),
584                NotFoundItemType::Trait => "Trait not found.".into(),
585                NotFoundItemType::Impl => "Impl not found.".into(),
586                NotFoundItemType::Macro => "Macro not found.".into(),
587            },
588            SemanticDiagnosticKind::AmbiguousPath(module_items) => {
589                format!(
590                    "Ambiguous path. Multiple matching items: {}",
591                    module_items.iter().map(|item| format!("`{}`", item.full_path(db))).join(", ")
592                )
593            }
594            SemanticDiagnosticKind::UseSelfNonMulti => {
595                "`self` in `use` items is not allowed not in multi.".into()
596            }
597            SemanticDiagnosticKind::UseSelfEmptyPath => {
598                "`self` in `use` items is not allowed for empty path.".into()
599            }
600            SemanticDiagnosticKind::UseStarEmptyPath => {
601                "`*` in `use` items is not allowed for empty path.".into()
602            }
603            SemanticDiagnosticKind::GlobalUsesNotSupportedInEdition(edition) => {
604                format!("Global `use` item is not supported in `{edition:?}` edition.")
605            }
606            SemanticDiagnosticKind::TraitInTraitMustBeExplicit => {
607                "In a trait, paths of the same trait must be fully explicit. Either use `Self` if \
608                 this is the intention, or explicitly specify all the generic arguments."
609                    .to_string()
610            }
611            SemanticDiagnosticKind::ImplInImplMustBeExplicit => {
612                "In an impl, paths of the same impl must be fully explicit. Either use `Self` if \
613                 this is the intention, or explicitly specify all the generic arguments."
614                    .to_string()
615            }
616            SemanticDiagnosticKind::TraitItemForbiddenInTheTrait => {
617                "In a trait, paths of the same trait are not allowed. Did you mean to use `Self::`?"
618                    .to_string()
619            }
620            SemanticDiagnosticKind::TraitItemForbiddenInItsImpl => "In an impl, paths of the \
621                                                                    impl's trait are not allowed. \
622                                                                    Did you mean to use `Self::`?"
623                .to_string(),
624            SemanticDiagnosticKind::ImplItemForbiddenInTheImpl => {
625                "In an impl, paths of the same impl are not allowed. Did you mean to use `Self::`?"
626                    .to_string()
627            }
628            SemanticDiagnosticKind::SuperUsedInRootModule => {
629                "'super' cannot be used for the crate's root module.".into()
630            }
631            SemanticDiagnosticKind::SuperUsedInMacroCallTopLevel => {
632                "`super` used in macro call top level.".into()
633            }
634            SemanticDiagnosticKind::ItemNotVisible(item_id, containing_modules) => {
635                format!(
636                    "Item `{}` is not visible in this context{}.",
637                    item_id.full_path(db),
638                    if containing_modules.is_empty() {
639                        "".to_string()
640                    } else if let [module_id] = &containing_modules[..] {
641                        format!(" through module `{}`", module_id.full_path(db))
642                    } else {
643                        format!(
644                            " through any of the modules: {}",
645                            containing_modules
646                                .iter()
647                                .map(|module_id| format!("`{}`", module_id.full_path(db)))
648                                .join(", ")
649                        )
650                    }
651                )
652            }
653            SemanticDiagnosticKind::UnusedImport(use_id) => {
654                format!("Unused import: `{}`", use_id.full_path(db))
655            }
656            SemanticDiagnosticKind::UnexpectedEnumPattern(ty) => {
657                format!(r#"Unexpected type for enum pattern. "{}" is not an enum."#, ty.format(db),)
658            }
659            SemanticDiagnosticKind::UnexpectedStructPattern(ty) => {
660                format!(
661                    r#"Unexpected type for struct pattern. "{}" is not a struct."#,
662                    ty.format(db),
663                )
664            }
665            SemanticDiagnosticKind::UnexpectedTuplePattern(ty) => {
666                format!(r#"Unexpected type for tuple pattern. "{}" is not a tuple."#, ty.format(db),)
667            }
668            SemanticDiagnosticKind::UnexpectedFixedSizeArrayPattern(ty) => {
669                format!(
670                    "Unexpected type for fixed size array pattern. \"{}\" is not a fixed size \
671                     array.",
672                    ty.format(db),
673                )
674            }
675            SemanticDiagnosticKind::WrongNumberOfTupleElements { expected, actual } => format!(
676                r#"Wrong number of tuple elements in pattern. Expected: {expected}. Got: {actual}."#,
677            ),
678            SemanticDiagnosticKind::WrongNumberOfFixedSizeArrayElements { expected, actual } => {
679                format!(
680                    "Wrong number of fixed size array elements in pattern. Expected: {expected}. \
681                     Got: {actual}.",
682                )
683            }
684            SemanticDiagnosticKind::WrongEnum { expected_enum, actual_enum } => {
685                format!(
686                    r#"Wrong enum in pattern. Expected: "{}". Got: "{}"."#,
687                    expected_enum.full_path(db),
688                    actual_enum.full_path(db)
689                )
690            }
691            SemanticDiagnosticKind::RedundantModifier { current_modifier, previous_modifier } => {
692                format!(
693                    "`{}` modifier was specified after another modifier (`{}`). Only a single \
694                     modifier is allowed.",
695                    current_modifier.long(db),
696                    previous_modifier.long(db)
697                )
698            }
699            SemanticDiagnosticKind::ReferenceLocalVariable => {
700                "`ref` is only allowed for function parameters, not for local variables."
701                    .to_string()
702            }
703            SemanticDiagnosticKind::InvalidCopyTraitImpl(inference_error) => {
704                format!("Invalid copy trait implementation, {}", inference_error.format(db))
705            }
706            SemanticDiagnosticKind::InvalidDropTraitImpl(inference_error) => {
707                format!("Invalid drop trait implementation, {}", inference_error.format(db))
708            }
709            SemanticDiagnosticKind::InvalidImplItem(item_kw) => {
710                format!("`{}` is not allowed inside impl.", item_kw.long(db))
711            }
712            SemanticDiagnosticKind::MissingItemsInImpl(item_names) => {
713                format!(
714                    "Not all trait items are implemented. Missing: {}.",
715                    item_names.iter().map(|name| format!("'{}'", name.long(db))).join(", ")
716                )
717            }
718            SemanticDiagnosticKind::PassPanicAsNopanic { impl_function_id, trait_id } => {
719                let name = impl_function_id.name(db).long(db);
720                let trait_name = trait_id.name(db).long(db);
721                format!(
722                    "The signature of function `{name}` is incompatible with trait \
723                     `{trait_name}`. The trait function is declared as nopanic."
724                )
725            }
726            SemanticDiagnosticKind::PassConstAsNonConst { impl_function_id, trait_id } => {
727                let name = impl_function_id.name(db).long(db);
728                let trait_name = trait_id.name(db).long(db);
729                format!(
730                    "The signature of function `{name}` is incompatible with trait \
731                     `{trait_name}`. The trait function is declared as const."
732                )
733            }
734            SemanticDiagnosticKind::PanicableFromNonPanicable => {
735                "Function is declared as nopanic but calls a function that may panic.".into()
736            }
737            SemanticDiagnosticKind::PanicableExternFunction => {
738                "An extern function must be marked as nopanic.".into()
739            }
740            SemanticDiagnosticKind::PluginDiagnostic(diagnostic) => {
741                format!("Plugin diagnostic: {}", diagnostic.message)
742            }
743            SemanticDiagnosticKind::MacroGeneratedCodeParserDiagnostic(parser_diagnostic) => {
744                format!("Parser error in macro-expanded code: {}", parser_diagnostic.format(db))
745            }
746            SemanticDiagnosticKind::NameDefinedMultipleTimes(name) => {
747                format!("The name `{}` is defined multiple times.", name.long(db))
748            }
749            SemanticDiagnosticKind::NonPrivateUseStar => {
750                "`pub` not supported for global `use`.".into()
751            }
752            SemanticDiagnosticKind::SelfGlobalUse => {
753                "cannot glob-import a module into itself".into()
754            }
755            SemanticDiagnosticKind::NamedArgumentsAreNotSupported => {
756                "Named arguments are not supported in this context.".into()
757            }
758            SemanticDiagnosticKind::UnnamedArgumentFollowsNamed => {
759                "Unnamed arguments cannot follow named arguments.".into()
760            }
761            SemanticDiagnosticKind::NamedArgumentMismatch { expected, found } => {
762                format!(
763                    "Unexpected argument name. Expected: '{}', found '{}'.",
764                    expected.long(db),
765                    found.long(db)
766                )
767            }
768            SemanticDiagnosticKind::UnsupportedOutsideOfFunction(feature_name) => {
769                let feature_name_str = match feature_name {
770                    UnsupportedOutsideOfFunctionFeatureName::ReturnStatement => "Return statement",
771                    UnsupportedOutsideOfFunctionFeatureName::ErrorPropagate => "The '?' operator",
772                };
773                format!("{feature_name_str} is not supported outside of functions.")
774            }
775            SemanticDiagnosticKind::UnsupportedConstant => {
776                "This expression is not supported as constant.".into()
777            }
778            SemanticDiagnosticKind::FailedConstantCalculation => {
779                "Failed to calculate constant.".into()
780            }
781            SemanticDiagnosticKind::ConstantCalculationDepthExceeded => {
782                "Constant calculation depth exceeded.".into()
783            }
784            SemanticDiagnosticKind::InnerFailedConstantCalculation(inner, _) => inner.format(db),
785            SemanticDiagnosticKind::DivisionByZero => "Division by zero.".into(),
786            SemanticDiagnosticKind::ExternTypeWithImplGenericsNotSupported => {
787                "Extern types with impl generics are not supported.".into()
788            }
789            SemanticDiagnosticKind::MissingSemicolon => "Missing semicolon".into(),
790            SemanticDiagnosticKind::TraitMismatch { expected_trt, actual_trt } => {
791                format!(
792                    "Expected an impl of `{:?}`. Got an impl of `{:?}`.",
793                    expected_trt.debug(db),
794                    actual_trt.debug(db),
795                )
796            }
797            SemanticDiagnosticKind::InternalInferenceError(err) => err.format(db),
798            SemanticDiagnosticKind::DerefNonRef { ty } => {
799                format!("Type `{}` cannot be dereferenced", ty.format(db))
800            }
801            SemanticDiagnosticKind::NoImplementationOfIndexOperator { ty, inference_errors } => {
802                if inference_errors.is_empty() {
803                    format!(
804                        "Type `{}` does not implement the `Index` trait nor the `IndexView` trait.",
805                        ty.format(db)
806                    )
807                } else {
808                    format!(
809                        "Type `{}` could not be indexed.\n{}",
810                        ty.format(db),
811                        inference_errors.format(db)
812                    )
813                }
814            }
815            SemanticDiagnosticKind::MultipleImplementationOfIndexOperator(ty) => {
816                format!(
817                    r#"Type "{}" implements both the "Index" trait and the "IndexView" trait."#,
818                    ty.format(db)
819                )
820            }
821            SemanticDiagnosticKind::UnsupportedInlineArguments => {
822                "Unsupported `inline` arguments.".into()
823            }
824            SemanticDiagnosticKind::RedundantInlineAttribute => {
825                "Redundant `inline` attribute.".into()
826            }
827            SemanticDiagnosticKind::InlineAttrForExternFunctionNotAllowed => {
828                "`inline` attribute is not allowed for extern functions.".into()
829            }
830            SemanticDiagnosticKind::InlineAlwaysWithImplGenericArgNotAllowed => {
831                "`#[inline(always)]` is not allowed for functions with impl generic parameters."
832                    .into()
833            }
834            SemanticDiagnosticKind::CannotCallMethod {
835                ty,
836                method_name,
837                inference_errors,
838                relevant_traits,
839            } => {
840                if !inference_errors.is_empty() {
841                    return format!(
842                        "Method `{}` could not be called on type `{}`.\n{}",
843                        method_name.long(db),
844                        ty.format(db),
845                        inference_errors.format(db)
846                    );
847                }
848                if !relevant_traits.is_empty() {
849                    let suggestions = relevant_traits
850                        .iter()
851                        .map(|trait_path| format!("`{trait_path}`"))
852                        .collect::<Vec<_>>()
853                        .join(", ");
854
855                    format!(
856                        "Method `{}` not found on type `{}`. Consider importing one of the \
857                         following traits: {}.",
858                        method_name.long(db),
859                        ty.format(db),
860                        suggestions
861                    )
862                } else {
863                    format!(
864                        "Method `{}` not found on type `{}`. Did you import the correct trait and \
865                         impl?",
866                        method_name.long(db),
867                        ty.format(db)
868                    )
869                }
870            }
871            SemanticDiagnosticKind::TailExpressionNotAllowedInLoop => {
872                "Tail expression not allowed in a `loop` block.".into()
873            }
874            SemanticDiagnosticKind::ContinueOnlyAllowedInsideALoop => {
875                "`continue` only allowed inside a `loop`.".into()
876            }
877            SemanticDiagnosticKind::BreakOnlyAllowedInsideALoop => {
878                "`break` only allowed inside a `loop`.".into()
879            }
880            SemanticDiagnosticKind::BreakWithValueOnlyAllowedInsideALoop => {
881                "Can only break with a value inside a `loop`.".into()
882            }
883            SemanticDiagnosticKind::ErrorPropagateNotAllowedInsideALoop => {
884                "`?` not allowed inside a `loop`.".into()
885            }
886            SemanticDiagnosticKind::ConstGenericParamNotSupported => {
887                "Const generic args are not allowed in this context.".into()
888            }
889            SemanticDiagnosticKind::NegativeImplsNotEnabled => {
890                "Negative impls are not enabled in the current crate.".into()
891            }
892            SemanticDiagnosticKind::NegativeImplsOnlyOnImpls => {
893                "Negative impls supported only in impl definitions.".into()
894            }
895            SemanticDiagnosticKind::ImplicitPrecedenceAttrForExternFunctionNotAllowed => {
896                "`implicit_precedence` attribute is not allowed for extern functions.".into()
897            }
898            SemanticDiagnosticKind::RedundantImplicitPrecedenceAttribute => {
899                "Redundant `implicit_precedence` attribute.".into()
900            }
901            SemanticDiagnosticKind::UnsupportedImplicitPrecedenceArguments => {
902                "Unsupported `implicit_precedence` arguments.".into()
903            }
904            SemanticDiagnosticKind::UnsupportedFeatureAttrArguments => {
905                "`feature` attribute argument should be a single string.".into()
906            }
907            SemanticDiagnosticKind::UnsupportedAllowAttrArguments => {
908                // TODO(orizi): Add information about the allowed arguments.
909                "`allow` attribute argument not supported.".into()
910            }
911            SemanticDiagnosticKind::UnsupportedPubArgument => "Unsupported `pub` argument.".into(),
912            SemanticDiagnosticKind::UnknownStatementAttribute => {
913                "Unknown statement attribute.".into()
914            }
915            SemanticDiagnosticKind::InlineMacroNotFound(macro_name) => {
916                format!("Inline macro `{}` not found.", macro_name.long(db))
917            }
918            SemanticDiagnosticKind::InlineMacroFailed(macro_name) => {
919                format!("Inline macro `{}` failed.", macro_name.long(db))
920            }
921            SemanticDiagnosticKind::InlineMacroNoMatchingRule(macro_name) => {
922                format!("No matching rule found in inline macro `{}`.", macro_name.long(db))
923            }
924            SemanticDiagnosticKind::MacroCallToNotAMacro(name) => {
925                format!("Call to `{}` which is not a macro.", name.long(db))
926            }
927            SemanticDiagnosticKind::UnknownGenericParam(name) => {
928                format!("Unknown generic parameter `{}`.", name.long(db))
929            }
930            SemanticDiagnosticKind::PositionalGenericAfterNamed => {
931                "Positional generic parameters must come before named generic parameters.".into()
932            }
933            SemanticDiagnosticKind::GenericArgDuplicate(name) => {
934                format!("Generic argument `{}` is specified more than once.", name.long(db))
935            }
936            SemanticDiagnosticKind::TooManyGenericArguments { expected, actual } => {
937                format!("Expected {expected} generic arguments, found {actual}.")
938            }
939            SemanticDiagnosticKind::GenericArgOutOfOrder(name) => {
940                format!("Generic argument `{}` is out of order.", name.long(db))
941            }
942            SemanticDiagnosticKind::ArgPassedToNegativeImpl => {
943                "Only `_` is valid as a negative impl argument.".into()
944            }
945            SemanticDiagnosticKind::CouponForExternFunctionNotAllowed => {
946                "Coupon cannot be used with extern functions.".into()
947            }
948            SemanticDiagnosticKind::CouponArgumentNoModifiers => {
949                "The __coupon__ argument cannot have modifiers.".into()
950            }
951            SemanticDiagnosticKind::CouponsDisabled => {
952                "Coupons are disabled in the current crate.\nYou can enable them by enabling the \
953                 coupons experimental feature in the crate config."
954                    .into()
955            }
956            SemanticDiagnosticKind::ReprPtrsDisabled => {
957                "Representation pointers are disabled in the current crate.\nYou can enable them \
958                 by enabling the `repr_ptrs` experimental feature in the crate config."
959                    .into()
960            }
961            SemanticDiagnosticKind::AssignmentToReprPtrVariable { .. } => {
962                "Cannot assign to a variable with a taken pointer".into()
963            }
964            SemanticDiagnosticKind::StructBaseStructExpressionNotLast => {
965                "The base struct must always be the last argument.".into()
966            }
967            SemanticDiagnosticKind::StructBaseStructExpressionNoEffect => {
968                "Base struct has no effect, all the fields in the struct have already been \
969                 specified."
970                    .into()
971            }
972            SemanticDiagnosticKind::FixedSizeArrayTypeNonSingleType => {
973                "Fixed size array type must have exactly one type.".into()
974            }
975            SemanticDiagnosticKind::FixedSizeArrayTypeEmptySize => {
976                "Fixed size array type must have a size clause.".into()
977            }
978            SemanticDiagnosticKind::FixedSizeArrayNonNumericSize => {
979                "Fixed size array type must have a positive integer size.".into()
980            }
981            SemanticDiagnosticKind::FixedSizeArrayNonSingleValue => {
982                "Fixed size array with defined size must have exactly one value.".into()
983            }
984            SemanticDiagnosticKind::FixedSizeArraySizeTooBig => {
985                "Fixed size array size must be smaller than 2^15.".into()
986            }
987            SemanticDiagnosticKind::SelfNotSupportedInContext => {
988                "`Self` is not supported in this context.".into()
989            }
990            SemanticDiagnosticKind::SelfMustBeFirst => {
991                "`Self` can only be the first segment of a path.".into()
992            }
993            SemanticDiagnosticKind::DollarNotSupportedInContext => {
994                "`$` is not supported in this context.".into()
995            }
996            SemanticDiagnosticKind::UnknownResolverModifier { modifier } => {
997                format!("`${}` is not supported.", modifier.long(db))
998            }
999            SemanticDiagnosticKind::EmptyPathAfterResolverModifier => {
1000                "Expected path after modifier.".into()
1001            }
1002            SemanticDiagnosticKind::CannotCreateInstancesOfPhantomTypes => {
1003                "Can not create instances of phantom types.".into()
1004            }
1005            SemanticDiagnosticKind::NonPhantomTypeContainingPhantomType => {
1006                "Non-phantom type containing phantom type.".into()
1007            }
1008            SemanticDiagnosticKind::DerefCycle { deref_chain } => {
1009                format!("Deref impls cycle detected:\n{deref_chain}")
1010            }
1011            SemanticDiagnosticKind::NoImplementationOfTrait {
1012                ty,
1013                trait_name,
1014                inference_errors,
1015            } => {
1016                if inference_errors.is_empty() {
1017                    format!(
1018                        "Implementation of trait `{}` not found on type `{}`. Did you import the \
1019                         correct trait and impl?",
1020                        trait_name.long(db),
1021                        ty.format(db)
1022                    )
1023                } else {
1024                    format!(
1025                        "Could not find implementation of trait `{}` on type `{}`.\n{}",
1026                        trait_name.long(db),
1027                        ty.format(db),
1028                        inference_errors.format(db)
1029                    )
1030                }
1031            }
1032            SemanticDiagnosticKind::CallExpressionRequiresFunction { ty, inference_errors } => {
1033                if inference_errors.is_empty() {
1034                    format!("Call expression requires a function, found `{}`.", ty.format(db))
1035                } else {
1036                    format!(
1037                        "Call expression requires a function, found `{}`.\n{}",
1038                        ty.format(db),
1039                        inference_errors.format(db)
1040                    )
1041                }
1042            }
1043            SemanticDiagnosticKind::CompilerTraitReImplementation { trait_id } => {
1044                format!(
1045                    "Trait `{}` should not be implemented outside of the corelib.",
1046                    trait_id.full_path(db)
1047                )
1048            }
1049            SemanticDiagnosticKind::ClosureInGlobalScope => {
1050                "Closures are not allowed in this context.".into()
1051            }
1052            SemanticDiagnosticKind::MaybeMissingColonColon => "Are you missing a `::`?.".into(),
1053            SemanticDiagnosticKind::CallingShadowedFunction { shadowed_function_name } => {
1054                format!(
1055                    "Function `{}` is shadowed by a local variable.",
1056                    shadowed_function_name.long(db)
1057                )
1058            }
1059            SemanticDiagnosticKind::RefClosureArgument => {
1060                "Arguments to closure functions cannot be references".into()
1061            }
1062            SemanticDiagnosticKind::RefClosureParam => {
1063                "Closure parameters cannot be references".into()
1064            }
1065            SemanticDiagnosticKind::MustBeNextToTypeOrTrait { trait_id } => {
1066                format!(
1067                    "'{}' implementation must be defined in the same module as either the type \
1068                     being dereferenced or the trait itself",
1069                    trait_id.name(db).long(db)
1070                )
1071            }
1072            SemanticDiagnosticKind::MutableCapturedVariable => {
1073                "Capture of mutable variables in a closure is not supported".into()
1074            }
1075            SemanticDiagnosticKind::NonTraitTypeConstrained { identifier, concrete_trait_id } => {
1076                format!(
1077                    "associated type `{}` not found for `{}`",
1078                    identifier.long(db),
1079                    concrete_trait_id.full_path(db)
1080                )
1081            }
1082            SemanticDiagnosticKind::DuplicateTypeConstraint {
1083                concrete_trait_type_id: trait_type_id,
1084            } => {
1085                format!(
1086                    "the value of the associated type `{}` in trait `{}` is already specified",
1087                    trait_type_id.trait_type(db).name(db).long(db),
1088                    trait_type_id.concrete_trait(db).full_path(db)
1089                )
1090            }
1091            SemanticDiagnosticKind::TypeConstraintsSyntaxNotEnabled => {
1092                "Type constraints syntax is not enabled in the current crate.".into()
1093            }
1094            SemanticDiagnosticKind::PatternMissingArgs(path) => {
1095                format!(
1096                    "Pattern missing subpattern for the payload of variant. Consider using `{}(_)`",
1097                    path.segments(db)
1098                        .elements(db)
1099                        .map(|seg| seg.identifier(db).long(db))
1100                        .join("::")
1101                )
1102            }
1103            SemanticDiagnosticKind::UndefinedMacroPlaceholder(name) => {
1104                format!("Undefined macro placeholder: '{}'.", name.long(db))
1105            }
1106            SemanticDiagnosticKind::UserDefinedInlineMacrosDisabled => {
1107                "User defined inline macros are disabled in the current crate.".into()
1108            }
1109            SemanticDiagnosticKind::NonNeverLetElseType => concat!(
1110                "`else` clause of `let...else` must exit the scope. ",
1111                "Consider using `return`, `continue`, ..."
1112            )
1113            .into(),
1114        }
1115    }
1116    fn location(&self, db: &'db dyn Database) -> SpanInFile<'db> {
1117        if let SemanticDiagnosticKind::MacroGeneratedCodeParserDiagnostic(parser_diagnostic) =
1118            &self.kind
1119        {
1120            return SpanInFile { file_id: parser_diagnostic.file_id, span: parser_diagnostic.span };
1121        };
1122
1123        let mut location = self.stable_location.span_in_file(db);
1124        if self.after {
1125            location = location.after();
1126        }
1127        location
1128    }
1129
1130    fn severity(&self) -> Severity {
1131        match &self.kind {
1132            SemanticDiagnosticKind::UnusedVariable
1133            | SemanticDiagnosticKind::UnhandledMustUseType { .. }
1134            | SemanticDiagnosticKind::UnhandledMustUseFunction
1135            | SemanticDiagnosticKind::TraitInTraitMustBeExplicit
1136            | SemanticDiagnosticKind::ImplInImplMustBeExplicit
1137            | SemanticDiagnosticKind::TraitItemForbiddenInTheTrait
1138            | SemanticDiagnosticKind::TraitItemForbiddenInItsImpl
1139            | SemanticDiagnosticKind::ImplItemForbiddenInTheImpl
1140            | SemanticDiagnosticKind::UnstableFeature { .. }
1141            | SemanticDiagnosticKind::DeprecatedFeature { .. }
1142            | SemanticDiagnosticKind::UnusedImport { .. }
1143            | SemanticDiagnosticKind::CallingShadowedFunction { .. }
1144            | SemanticDiagnosticKind::UnusedConstant
1145            | SemanticDiagnosticKind::UnusedUse
1146            | SemanticDiagnosticKind::PatternMissingArgs(_)
1147            | SemanticDiagnosticKind::UnsupportedAllowAttrArguments => Severity::Warning,
1148            SemanticDiagnosticKind::PluginDiagnostic(diag) => diag.severity,
1149            _ => Severity::Error,
1150        }
1151    }
1152
1153    fn notes(&self, _db: &dyn Database) -> &[DiagnosticNote<'_>] {
1154        match &self.kind {
1155            SemanticDiagnosticKind::InnerFailedConstantCalculation(_, notes) => notes,
1156            SemanticDiagnosticKind::AssignmentToReprPtrVariable(notes) => notes,
1157            _ => &[],
1158        }
1159    }
1160
1161    fn error_code(&self) -> Option<ErrorCode> {
1162        self.kind.error_code()
1163    }
1164
1165    fn is_same_kind(&self, other: &Self) -> bool {
1166        other.kind == self.kind
1167    }
1168}
1169
1170#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
1171pub enum SemanticDiagnosticKind<'db> {
1172    ModuleFileNotFound(String),
1173    Unsupported,
1174    UnknownLiteral,
1175    UnknownBinaryOperator,
1176    UnknownTrait,
1177    UnknownImpl,
1178    UnexpectedElement {
1179        expected: Vec<ElementKind>,
1180        actual: ElementKind,
1181    },
1182    UnknownType,
1183    UnknownEnum,
1184    LiteralError(LiteralError<'db>),
1185    NotAVariant,
1186    NotAStruct,
1187    NotAType,
1188    NotATrait,
1189    NotAnImpl,
1190    ImplItemNotInTrait {
1191        impl_def_id: ImplDefId<'db>,
1192        impl_item_name: SmolStrId<'db>,
1193        trait_id: TraitId<'db>,
1194        item_kind: String,
1195    },
1196    ImplicitImplNotInferred {
1197        trait_impl_id: TraitImplId<'db>,
1198        concrete_trait_id: ConcreteTraitId<'db>,
1199    },
1200    GenericsNotSupportedInItem {
1201        scope: String,
1202        item_kind: String,
1203    },
1204    UnexpectedGenericArgs,
1205    UnknownMember,
1206    CannotCreateInstancesOfPhantomTypes,
1207    NonPhantomTypeContainingPhantomType,
1208    MemberSpecifiedMoreThanOnce,
1209    StructBaseStructExpressionNotLast,
1210    StructBaseStructExpressionNoEffect,
1211    ConstCycle,
1212    UseCycle,
1213    TypeAliasCycle,
1214    ImplAliasCycle,
1215    ImplRequirementCycle,
1216    MissingMember(SmolStrId<'db>),
1217    WrongNumberOfParameters {
1218        impl_def_id: ImplDefId<'db>,
1219        impl_function_id: ImplFunctionId<'db>,
1220        trait_id: TraitId<'db>,
1221        expected: usize,
1222        actual: usize,
1223    },
1224    WrongNumberOfArguments {
1225        expected: usize,
1226        actual: usize,
1227    },
1228    WrongParameterType {
1229        impl_def_id: ImplDefId<'db>,
1230        impl_function_id: ImplFunctionId<'db>,
1231        trait_id: TraitId<'db>,
1232        expected_ty: semantic::TypeId<'db>,
1233        actual_ty: semantic::TypeId<'db>,
1234    },
1235    VariantCtorNotImmutable,
1236    TraitParamMutable {
1237        trait_id: TraitId<'db>,
1238        function_id: TraitFunctionId<'db>,
1239    },
1240    ParameterShouldBeReference {
1241        impl_def_id: ImplDefId<'db>,
1242        impl_function_id: ImplFunctionId<'db>,
1243        trait_id: TraitId<'db>,
1244    },
1245    ParameterShouldNotBeReference {
1246        impl_def_id: ImplDefId<'db>,
1247        impl_function_id: ImplFunctionId<'db>,
1248        trait_id: TraitId<'db>,
1249    },
1250    WrongParameterName {
1251        impl_def_id: ImplDefId<'db>,
1252        impl_function_id: ImplFunctionId<'db>,
1253        trait_id: TraitId<'db>,
1254        expected_name: SmolStrId<'db>,
1255    },
1256    WrongGenericParamTraitForImplFunction {
1257        impl_def_id: ImplDefId<'db>,
1258        impl_function_id: ImplFunctionId<'db>,
1259        trait_id: TraitId<'db>,
1260        expected_trait: ConcreteTraitId<'db>,
1261        actual_trait: ConcreteTraitId<'db>,
1262    },
1263    WrongGenericParamKindForImplFunction {
1264        impl_def_id: ImplDefId<'db>,
1265        impl_function_id: ImplFunctionId<'db>,
1266        trait_id: TraitId<'db>,
1267        expected_kind: GenericKind,
1268        actual_kind: GenericKind,
1269    },
1270    WrongType {
1271        expected_ty: semantic::TypeId<'db>,
1272        actual_ty: semantic::TypeId<'db>,
1273    },
1274    InconsistentBinding,
1275    WrongArgumentType {
1276        expected_ty: semantic::TypeId<'db>,
1277        actual_ty: semantic::TypeId<'db>,
1278    },
1279    WrongReturnType {
1280        expected_ty: semantic::TypeId<'db>,
1281        actual_ty: semantic::TypeId<'db>,
1282    },
1283    WrongExprType {
1284        expected_ty: semantic::TypeId<'db>,
1285        actual_ty: semantic::TypeId<'db>,
1286    },
1287    WrongNumberOfGenericParamsForImplFunction {
1288        expected: usize,
1289        actual: usize,
1290    },
1291    WrongReturnTypeForImpl {
1292        impl_def_id: ImplDefId<'db>,
1293        impl_function_id: ImplFunctionId<'db>,
1294        trait_id: TraitId<'db>,
1295        expected_ty: semantic::TypeId<'db>,
1296        actual_ty: semantic::TypeId<'db>,
1297    },
1298    AmbiguousTrait {
1299        trait_function_id0: TraitFunctionId<'db>,
1300        trait_function_id1: TraitFunctionId<'db>,
1301    },
1302    VariableNotFound(SmolStrId<'db>),
1303    MissingVariableInPattern,
1304    VariableDefinedMultipleTimesInPattern(SmolStrId<'db>),
1305    StructMemberRedefinition {
1306        struct_id: StructId<'db>,
1307        member_name: SmolStrId<'db>,
1308    },
1309    EnumVariantRedefinition {
1310        enum_id: EnumId<'db>,
1311        variant_name: SmolStrId<'db>,
1312    },
1313    InfiniteSizeType(semantic::TypeId<'db>),
1314    ArrayOfZeroSizedElements(semantic::TypeId<'db>),
1315    ParamNameRedefinition {
1316        function_title_id: Option<FunctionTitleId<'db>>,
1317        param_name: SmolStrId<'db>,
1318    },
1319    ConditionNotBool(semantic::TypeId<'db>),
1320    IncompatibleArms {
1321        multi_arm_expr_kind: MultiArmExprKind,
1322        pending_ty: semantic::TypeId<'db>,
1323        different_ty: semantic::TypeId<'db>,
1324    },
1325    TypeHasNoMembers {
1326        ty: semantic::TypeId<'db>,
1327        member_name: SmolStrId<'db>,
1328    },
1329    CannotCallMethod {
1330        ty: semantic::TypeId<'db>,
1331        method_name: SmolStrId<'db>,
1332        inference_errors: TraitInferenceErrors<'db>,
1333        relevant_traits: Vec<String>,
1334    },
1335    NoSuchStructMember {
1336        struct_id: StructId<'db>,
1337        member_name: SmolStrId<'db>,
1338    },
1339    NoSuchTypeMember {
1340        ty: semantic::TypeId<'db>,
1341        member_name: SmolStrId<'db>,
1342    },
1343    MemberNotVisible(SmolStrId<'db>),
1344    NoSuchVariant {
1345        enum_id: EnumId<'db>,
1346        variant_name: SmolStrId<'db>,
1347    },
1348    ReturnTypeNotErrorPropagateType,
1349    IncompatibleErrorPropagateType {
1350        return_ty: semantic::TypeId<'db>,
1351        err_ty: semantic::TypeId<'db>,
1352    },
1353    ErrorPropagateOnNonErrorType(semantic::TypeId<'db>),
1354    UnhandledMustUseType(semantic::TypeId<'db>),
1355    UnstableFeature {
1356        feature_name: SmolStrId<'db>,
1357        note: Option<SmolStrId<'db>>,
1358    },
1359    DeprecatedFeature {
1360        feature_name: SmolStrId<'db>,
1361        note: Option<SmolStrId<'db>>,
1362    },
1363    InternalFeature {
1364        feature_name: SmolStrId<'db>,
1365        note: Option<SmolStrId<'db>>,
1366    },
1367    FeatureMarkerDiagnostic(FeatureMarkerDiagnostic),
1368    UnhandledMustUseFunction,
1369    UnusedVariable,
1370    UnusedConstant,
1371    UnusedUse,
1372    MultipleConstantDefinition(SmolStrId<'db>),
1373    MultipleDefinitionforBinding(SmolStrId<'db>),
1374    MultipleGenericItemDefinition(SmolStrId<'db>),
1375    UnsupportedUseItemInStatement,
1376    ConstGenericParamNotSupported,
1377    NegativeImplsNotEnabled,
1378    NegativeImplsOnlyOnImpls,
1379    RefArgNotAVariable,
1380    RefArgNotMutable,
1381    RefArgNotExplicit,
1382    ImmutableArgWithModifiers,
1383    AssignmentToImmutableVar,
1384    InvalidLhsForAssignment,
1385    InvalidMemberExpression,
1386    InvalidPath,
1387    PathNotFound(NotFoundItemType),
1388    AmbiguousPath(Vec<ModuleItemId<'db>>),
1389    UseSelfNonMulti,
1390    UseSelfEmptyPath,
1391    UseStarEmptyPath,
1392    GlobalUsesNotSupportedInEdition(Edition),
1393    TraitInTraitMustBeExplicit,
1394    ImplInImplMustBeExplicit,
1395    TraitItemForbiddenInTheTrait,
1396    TraitItemForbiddenInItsImpl,
1397    ImplItemForbiddenInTheImpl,
1398    SuperUsedInRootModule,
1399    SuperUsedInMacroCallTopLevel,
1400    ItemNotVisible(ModuleItemId<'db>, Vec<ModuleId<'db>>),
1401    UnusedImport(UseId<'db>),
1402    RedundantModifier {
1403        current_modifier: SmolStrId<'db>,
1404        previous_modifier: SmolStrId<'db>,
1405    },
1406    ReferenceLocalVariable,
1407    UnexpectedEnumPattern(semantic::TypeId<'db>),
1408    UnexpectedStructPattern(semantic::TypeId<'db>),
1409    UnexpectedTuplePattern(semantic::TypeId<'db>),
1410    UnexpectedFixedSizeArrayPattern(semantic::TypeId<'db>),
1411    WrongNumberOfTupleElements {
1412        expected: usize,
1413        actual: usize,
1414    },
1415    WrongNumberOfFixedSizeArrayElements {
1416        expected: usize,
1417        actual: usize,
1418    },
1419    WrongEnum {
1420        expected_enum: EnumId<'db>,
1421        actual_enum: EnumId<'db>,
1422    },
1423    InvalidCopyTraitImpl(InferenceError<'db>),
1424    InvalidDropTraitImpl(InferenceError<'db>),
1425    InvalidImplItem(SmolStrId<'db>),
1426    MissingItemsInImpl(Vec<SmolStrId<'db>>),
1427    PassPanicAsNopanic {
1428        impl_function_id: ImplFunctionId<'db>,
1429        trait_id: TraitId<'db>,
1430    },
1431    PassConstAsNonConst {
1432        impl_function_id: ImplFunctionId<'db>,
1433        trait_id: TraitId<'db>,
1434    },
1435    PanicableFromNonPanicable,
1436    PanicableExternFunction,
1437    MacroGeneratedCodeParserDiagnostic(ParserDiagnostic<'db>),
1438    PluginDiagnostic(PluginDiagnostic<'db>),
1439    NameDefinedMultipleTimes(SmolStrId<'db>),
1440    NonPrivateUseStar,
1441    SelfGlobalUse,
1442    NamedArgumentsAreNotSupported,
1443    ArgPassedToNegativeImpl,
1444    UnnamedArgumentFollowsNamed,
1445    NamedArgumentMismatch {
1446        expected: SmolStrId<'db>,
1447        found: SmolStrId<'db>,
1448    },
1449    UnsupportedOutsideOfFunction(UnsupportedOutsideOfFunctionFeatureName),
1450    UnsupportedConstant,
1451    FailedConstantCalculation,
1452    ConstantCalculationDepthExceeded,
1453    InnerFailedConstantCalculation(Box<SemanticDiagnostic<'db>>, Vec<DiagnosticNote<'db>>),
1454    DivisionByZero,
1455    ExternTypeWithImplGenericsNotSupported,
1456    MissingSemicolon,
1457    TraitMismatch {
1458        expected_trt: semantic::ConcreteTraitId<'db>,
1459        actual_trt: semantic::ConcreteTraitId<'db>,
1460    },
1461    DerefNonRef {
1462        ty: semantic::TypeId<'db>,
1463    },
1464    InternalInferenceError(InferenceError<'db>),
1465    NoImplementationOfIndexOperator {
1466        ty: semantic::TypeId<'db>,
1467        inference_errors: TraitInferenceErrors<'db>,
1468    },
1469    NoImplementationOfTrait {
1470        ty: semantic::TypeId<'db>,
1471        trait_name: SmolStrId<'db>,
1472        inference_errors: TraitInferenceErrors<'db>,
1473    },
1474    CallExpressionRequiresFunction {
1475        ty: semantic::TypeId<'db>,
1476        inference_errors: TraitInferenceErrors<'db>,
1477    },
1478    MultipleImplementationOfIndexOperator(semantic::TypeId<'db>),
1479
1480    UnsupportedInlineArguments,
1481    RedundantInlineAttribute,
1482    InlineAttrForExternFunctionNotAllowed,
1483    InlineAlwaysWithImplGenericArgNotAllowed,
1484    TailExpressionNotAllowedInLoop,
1485    ContinueOnlyAllowedInsideALoop,
1486    BreakOnlyAllowedInsideALoop,
1487    BreakWithValueOnlyAllowedInsideALoop,
1488    ErrorPropagateNotAllowedInsideALoop,
1489    ImplicitPrecedenceAttrForExternFunctionNotAllowed,
1490    RedundantImplicitPrecedenceAttribute,
1491    UnsupportedImplicitPrecedenceArguments,
1492    UnsupportedFeatureAttrArguments,
1493    UnsupportedAllowAttrArguments,
1494    UnsupportedPubArgument,
1495    UnknownStatementAttribute,
1496    InlineMacroNotFound(SmolStrId<'db>),
1497    InlineMacroFailed(SmolStrId<'db>),
1498    InlineMacroNoMatchingRule(SmolStrId<'db>),
1499    MacroCallToNotAMacro(SmolStrId<'db>),
1500    UnknownGenericParam(SmolStrId<'db>),
1501    PositionalGenericAfterNamed,
1502    GenericArgDuplicate(SmolStrId<'db>),
1503    TooManyGenericArguments {
1504        expected: usize,
1505        actual: usize,
1506    },
1507    GenericArgOutOfOrder(SmolStrId<'db>),
1508    CouponForExternFunctionNotAllowed,
1509    CouponArgumentNoModifiers,
1510    /// Coupons are disabled in the current crate.
1511    CouponsDisabled,
1512    /// Representation pointers are disabled in the current crate.
1513    ReprPtrsDisabled,
1514    /// Cannot assign to a variable with a taken pointer.
1515    AssignmentToReprPtrVariable(Vec<DiagnosticNote<'db>>),
1516    FixedSizeArrayTypeNonSingleType,
1517    FixedSizeArrayTypeEmptySize,
1518    FixedSizeArrayNonNumericSize,
1519    FixedSizeArrayNonSingleValue,
1520    FixedSizeArraySizeTooBig,
1521    SelfNotSupportedInContext,
1522    SelfMustBeFirst,
1523    DollarNotSupportedInContext,
1524    UnknownResolverModifier {
1525        modifier: SmolStrId<'db>,
1526    },
1527    EmptyPathAfterResolverModifier,
1528    DerefCycle {
1529        deref_chain: String,
1530    },
1531    CompilerTraitReImplementation {
1532        trait_id: TraitId<'db>,
1533    },
1534    ClosureInGlobalScope,
1535    MaybeMissingColonColon,
1536    CallingShadowedFunction {
1537        shadowed_function_name: SmolStrId<'db>,
1538    },
1539    RefClosureArgument,
1540    RefClosureParam,
1541    MustBeNextToTypeOrTrait {
1542        trait_id: TraitId<'db>,
1543    },
1544    MutableCapturedVariable,
1545    NonTraitTypeConstrained {
1546        identifier: SmolStrId<'db>,
1547        concrete_trait_id: ConcreteTraitId<'db>,
1548    },
1549    DuplicateTypeConstraint {
1550        concrete_trait_type_id: ConcreteTraitTypeId<'db>,
1551    },
1552    TypeConstraintsSyntaxNotEnabled,
1553    PatternMissingArgs(ast::ExprPath<'db>),
1554    UndefinedMacroPlaceholder(SmolStrId<'db>),
1555    UserDefinedInlineMacrosDisabled,
1556    NonNeverLetElseType,
1557}
1558
1559/// The kind of an expression with multiple possible return types.
1560#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1561pub enum MultiArmExprKind {
1562    If,
1563    Match,
1564    Loop,
1565}
1566
1567impl<'db> SemanticDiagnosticKind<'db> {
1568    pub fn error_code(&self) -> Option<ErrorCode> {
1569        Some(match &self {
1570            Self::UnusedVariable => error_code!(E0001),
1571            Self::CannotCallMethod { .. } => {
1572                error_code!(E0002)
1573            }
1574            Self::MissingMember(_) => error_code!(E0003),
1575            Self::MissingItemsInImpl(_) => error_code!(E0004),
1576            Self::ModuleFileNotFound(_) => error_code!(E0005),
1577            Self::PathNotFound(_) => error_code!(E0006),
1578            Self::NoSuchTypeMember { .. } => error_code!(E0007),
1579            _ => return None,
1580        })
1581    }
1582}
1583
1584// TODO(Gil): It seems to have the same functionality as ElementKind, maybe we can merge them.
1585#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1586pub enum NotFoundItemType {
1587    Identifier,
1588    Function,
1589    Type,
1590    Trait,
1591    Impl,
1592    Macro,
1593}
1594
1595#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1596pub enum UnsupportedOutsideOfFunctionFeatureName {
1597    ReturnStatement,
1598    ErrorPropagate,
1599}
1600
1601#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1602pub enum ElementKind {
1603    Constant,
1604    Variable,
1605    Module,
1606    Function,
1607    Type,
1608    Variant,
1609    Trait,
1610    Impl,
1611    Macro,
1612}
1613impl<'db> From<&ResolvedConcreteItem<'db>> for ElementKind {
1614    fn from(val: &ResolvedConcreteItem<'db>) -> Self {
1615        match val {
1616            ResolvedConcreteItem::Constant(_) => ElementKind::Constant,
1617            ResolvedConcreteItem::Module(_) => ElementKind::Module,
1618            ResolvedConcreteItem::Function(_) => ElementKind::Function,
1619            ResolvedConcreteItem::Type(_) => ElementKind::Type,
1620            ResolvedConcreteItem::Variant(_) => ElementKind::Variant,
1621            ResolvedConcreteItem::Trait(_) | ResolvedConcreteItem::SelfTrait(_) => {
1622                ElementKind::Trait
1623            }
1624            ResolvedConcreteItem::Impl(_) => ElementKind::Impl,
1625            ResolvedConcreteItem::Macro(_) => ElementKind::Macro,
1626        }
1627    }
1628}
1629impl<'db> From<&ResolvedGenericItem<'db>> for ElementKind {
1630    fn from(val: &ResolvedGenericItem<'db>) -> Self {
1631        match val {
1632            ResolvedGenericItem::GenericConstant(_)
1633            | ResolvedGenericItem::TraitItem(TraitItemId::Constant(_)) => ElementKind::Constant,
1634            ResolvedGenericItem::Module(_) => ElementKind::Module,
1635            ResolvedGenericItem::GenericFunction(_)
1636            | ResolvedGenericItem::TraitItem(TraitItemId::Function(_)) => ElementKind::Function,
1637            ResolvedGenericItem::GenericType(_)
1638            | ResolvedGenericItem::GenericTypeAlias(_)
1639            | ResolvedGenericItem::TraitItem(TraitItemId::Type(_)) => ElementKind::Type,
1640            ResolvedGenericItem::Variant(_) => ElementKind::Variant,
1641            ResolvedGenericItem::Trait(_) => ElementKind::Trait,
1642            ResolvedGenericItem::Impl(_)
1643            | ResolvedGenericItem::GenericImplAlias(_)
1644            | ResolvedGenericItem::TraitItem(TraitItemId::Impl(_)) => ElementKind::Impl,
1645            ResolvedGenericItem::Variable(_) => ElementKind::Variable,
1646            ResolvedGenericItem::Macro(_) => ElementKind::Macro,
1647        }
1648    }
1649}
1650impl Display for ElementKind {
1651    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1652        let res = match self {
1653            ElementKind::Constant => "constant",
1654            ElementKind::Variable => "variable",
1655            ElementKind::Module => "module",
1656            ElementKind::Function => "function",
1657            ElementKind::Type => "type",
1658            ElementKind::Variant => "variant",
1659            ElementKind::Trait => "trait",
1660            ElementKind::Impl => "impl",
1661            ElementKind::Macro => "macro",
1662        };
1663        write!(f, "{res}")
1664    }
1665}
1666
1667/// A list of trait functions and the inference errors that occurred while trying to infer them.
1668#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
1669pub struct TraitInferenceErrors<'db> {
1670    pub traits_and_errors: Vec<(TraitFunctionId<'db>, InferenceError<'db>)>,
1671}
1672impl<'db> TraitInferenceErrors<'db> {
1673    /// Is the error list empty.
1674    pub fn is_empty(&self) -> bool {
1675        self.traits_and_errors.is_empty()
1676    }
1677    /// Format the list of errors.
1678    fn format(&self, db: &dyn Database) -> String {
1679        self.traits_and_errors
1680            .iter()
1681            .map(|(trait_function_id, inference_error)| {
1682                format!(
1683                    "Candidate `{}` inference failed with: {}",
1684                    trait_function_id.full_path(db),
1685                    inference_error.format(db)
1686                )
1687            })
1688            .join("\n")
1689    }
1690}