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 "{}" cannot 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::ConstTypeNotVarFree => {
776                "Constant type must not depend on its value.".into()
777            }
778            SemanticDiagnosticKind::UnsupportedConstant => {
779                "This expression is not supported as constant.".into()
780            }
781            SemanticDiagnosticKind::FailedConstantCalculation => {
782                "Failed to calculate constant.".into()
783            }
784            SemanticDiagnosticKind::ConstantCalculationDepthExceeded => {
785                "Constant calculation depth exceeded.".into()
786            }
787            SemanticDiagnosticKind::InnerFailedConstantCalculation(inner, _) => inner.format(db),
788            SemanticDiagnosticKind::DivisionByZero => "Division by zero.".into(),
789            SemanticDiagnosticKind::ExternTypeWithImplGenericsNotSupported => {
790                "Extern types with impl generics are not supported.".into()
791            }
792            SemanticDiagnosticKind::MissingSemicolon => "Missing semicolon".into(),
793            SemanticDiagnosticKind::TraitMismatch { expected_trt, actual_trt } => {
794                format!(
795                    "Expected an impl of `{:?}`. Got an impl of `{:?}`.",
796                    expected_trt.debug(db),
797                    actual_trt.debug(db),
798                )
799            }
800            SemanticDiagnosticKind::InternalInferenceError(err) => err.format(db),
801            SemanticDiagnosticKind::DerefNonRef { ty } => {
802                format!("Type `{}` cannot be dereferenced", ty.format(db))
803            }
804            SemanticDiagnosticKind::NoImplementationOfIndexOperator { ty, inference_errors } => {
805                if inference_errors.is_empty() {
806                    format!(
807                        "Type `{}` does not implement the `Index` trait nor the `IndexView` trait.",
808                        ty.format(db)
809                    )
810                } else {
811                    format!(
812                        "Type `{}` could not be indexed.\n{}",
813                        ty.format(db),
814                        inference_errors.format(db)
815                    )
816                }
817            }
818            SemanticDiagnosticKind::MultipleImplementationOfIndexOperator(ty) => {
819                format!(
820                    r#"Type "{}" implements both the "Index" trait and the "IndexView" trait."#,
821                    ty.format(db)
822                )
823            }
824            SemanticDiagnosticKind::UnsupportedInlineArguments => {
825                "Unsupported `inline` arguments.".into()
826            }
827            SemanticDiagnosticKind::RedundantInlineAttribute => {
828                "Redundant `inline` attribute.".into()
829            }
830            SemanticDiagnosticKind::InlineAttrForExternFunctionNotAllowed => {
831                "`inline` attribute is not allowed for extern functions.".into()
832            }
833            SemanticDiagnosticKind::InlineAlwaysWithImplGenericArgNotAllowed => {
834                "`#[inline(always)]` is not allowed for functions with impl generic parameters."
835                    .into()
836            }
837            SemanticDiagnosticKind::CannotCallMethod {
838                ty,
839                method_name,
840                inference_errors,
841                relevant_traits,
842            } => {
843                if !inference_errors.is_empty() {
844                    return format!(
845                        "Method `{}` could not be called on type `{}`.\n{}",
846                        method_name.long(db),
847                        ty.format(db),
848                        inference_errors.format(db)
849                    );
850                }
851                if !relevant_traits.is_empty() {
852                    let suggestions = relevant_traits
853                        .iter()
854                        .map(|trait_path| format!("`{trait_path}`"))
855                        .collect::<Vec<_>>()
856                        .join(", ");
857
858                    format!(
859                        "Method `{}` not found on type `{}`. Consider importing one of the \
860                         following traits: {}.",
861                        method_name.long(db),
862                        ty.format(db),
863                        suggestions
864                    )
865                } else {
866                    format!(
867                        "Method `{}` not found on type `{}`. Did you import the correct trait and \
868                         impl?",
869                        method_name.long(db),
870                        ty.format(db)
871                    )
872                }
873            }
874            SemanticDiagnosticKind::TailExpressionNotAllowedInLoop => {
875                "Tail expression not allowed in a `loop` block.".into()
876            }
877            SemanticDiagnosticKind::ContinueOnlyAllowedInsideALoop => {
878                "`continue` only allowed inside a `loop`.".into()
879            }
880            SemanticDiagnosticKind::BreakOnlyAllowedInsideALoop => {
881                "`break` only allowed inside a `loop`.".into()
882            }
883            SemanticDiagnosticKind::BreakWithValueOnlyAllowedInsideALoop => {
884                "Can only break with a value inside a `loop`.".into()
885            }
886            SemanticDiagnosticKind::ErrorPropagateNotAllowedInsideALoop => {
887                "`?` not allowed inside a `loop`.".into()
888            }
889            SemanticDiagnosticKind::ConstGenericParamNotSupported => {
890                "Const generic args are not allowed in this context.".into()
891            }
892            SemanticDiagnosticKind::NegativeImplsNotEnabled => {
893                "Negative impls are not enabled in the current crate.".into()
894            }
895            SemanticDiagnosticKind::NegativeImplsOnlyOnImpls => {
896                "Negative impls supported only in impl definitions.".into()
897            }
898            SemanticDiagnosticKind::ImplicitPrecedenceAttrForExternFunctionNotAllowed => {
899                "`implicit_precedence` attribute is not allowed for extern functions.".into()
900            }
901            SemanticDiagnosticKind::RedundantImplicitPrecedenceAttribute => {
902                "Redundant `implicit_precedence` attribute.".into()
903            }
904            SemanticDiagnosticKind::UnsupportedImplicitPrecedenceArguments => {
905                "Unsupported `implicit_precedence` arguments.".into()
906            }
907            SemanticDiagnosticKind::UnsupportedFeatureAttrArguments => {
908                "`feature` attribute argument should be a single string.".into()
909            }
910            SemanticDiagnosticKind::UnsupportedAllowAttrArguments => {
911                // TODO(orizi): Add information about the allowed arguments.
912                "`allow` attribute argument not supported.".into()
913            }
914            SemanticDiagnosticKind::UnsupportedPubArgument => "Unsupported `pub` argument.".into(),
915            SemanticDiagnosticKind::UnknownStatementAttribute => {
916                "Unknown statement attribute.".into()
917            }
918            SemanticDiagnosticKind::InlineMacroNotFound(macro_name) => {
919                format!("Inline macro `{}` not found.", macro_name.long(db))
920            }
921            SemanticDiagnosticKind::InlineMacroFailed(macro_name) => {
922                format!("Inline macro `{}` failed.", macro_name.long(db))
923            }
924            SemanticDiagnosticKind::InlineMacroNoMatchingRule(macro_name) => {
925                format!("No matching rule found in inline macro `{}`.", macro_name.long(db))
926            }
927            SemanticDiagnosticKind::MacroCallToNotAMacro(name) => {
928                format!("Call to `{}` which is not a macro.", name.long(db))
929            }
930            SemanticDiagnosticKind::UnknownGenericParam(name) => {
931                format!("Unknown generic parameter `{}`.", name.long(db))
932            }
933            SemanticDiagnosticKind::PositionalGenericAfterNamed => {
934                "Positional generic parameters must come before named generic parameters.".into()
935            }
936            SemanticDiagnosticKind::GenericArgDuplicate(name) => {
937                format!("Generic argument `{}` is specified more than once.", name.long(db))
938            }
939            SemanticDiagnosticKind::TooManyGenericArguments { expected, actual } => {
940                format!("Expected {expected} generic arguments, found {actual}.")
941            }
942            SemanticDiagnosticKind::GenericArgOutOfOrder(name) => {
943                format!("Generic argument `{}` is out of order.", name.long(db))
944            }
945            SemanticDiagnosticKind::ArgPassedToNegativeImpl => {
946                "Only `_` is valid as a negative impl argument.".into()
947            }
948            SemanticDiagnosticKind::CouponForExternFunctionNotAllowed => {
949                "Coupon cannot be used with extern functions.".into()
950            }
951            SemanticDiagnosticKind::CouponArgumentNoModifiers => {
952                "The __coupon__ argument cannot have modifiers.".into()
953            }
954            SemanticDiagnosticKind::CouponsDisabled => {
955                "Coupons are disabled in the current crate.\nYou can enable them by enabling the \
956                 coupons experimental feature in the crate config."
957                    .into()
958            }
959            SemanticDiagnosticKind::ReprPtrsDisabled => {
960                "Representation pointers are disabled in the current crate.\nYou can enable them \
961                 by enabling the `repr_ptrs` experimental feature in the crate config."
962                    .into()
963            }
964            SemanticDiagnosticKind::AssignmentToReprPtrVariable { .. } => {
965                "Cannot assign to a variable with a taken pointer".into()
966            }
967            SemanticDiagnosticKind::StructBaseStructExpressionNotLast => {
968                "The base struct must always be the last argument.".into()
969            }
970            SemanticDiagnosticKind::StructBaseStructExpressionNoEffect => {
971                "Base struct has no effect, all the fields in the struct have already been \
972                 specified."
973                    .into()
974            }
975            SemanticDiagnosticKind::FixedSizeArrayTypeNonSingleType => {
976                "Fixed size array type must have exactly one type.".into()
977            }
978            SemanticDiagnosticKind::FixedSizeArrayTypeEmptySize => {
979                "Fixed size array type must have a size clause.".into()
980            }
981            SemanticDiagnosticKind::FixedSizeArrayNonNumericSize => {
982                "Fixed size array type must have a positive integer size.".into()
983            }
984            SemanticDiagnosticKind::FixedSizeArrayNonSingleValue => {
985                "Fixed size array with defined size must have exactly one value.".into()
986            }
987            SemanticDiagnosticKind::FixedSizeArraySizeTooBig => {
988                "Fixed size array size must be smaller than 2^15.".into()
989            }
990            SemanticDiagnosticKind::SelfNotSupportedInContext => {
991                "`Self` is not supported in this context.".into()
992            }
993            SemanticDiagnosticKind::SelfMustBeFirst => {
994                "`Self` can only be the first segment of a path.".into()
995            }
996            SemanticDiagnosticKind::DollarNotSupportedInContext => {
997                "`$` is not supported in this context.".into()
998            }
999            SemanticDiagnosticKind::UnknownResolverModifier { modifier } => {
1000                format!("`${}` is not supported.", modifier.long(db))
1001            }
1002            SemanticDiagnosticKind::EmptyPathAfterResolverModifier => {
1003                "Expected path after modifier.".into()
1004            }
1005            SemanticDiagnosticKind::CannotCreateInstancesOfPhantomTypes => {
1006                "Can not create instances of phantom types.".into()
1007            }
1008            SemanticDiagnosticKind::NonPhantomTypeContainingPhantomType => {
1009                "Non-phantom type containing phantom type.".into()
1010            }
1011            SemanticDiagnosticKind::DerefCycle { deref_chain } => {
1012                format!("Deref impls cycle detected:\n{deref_chain}")
1013            }
1014            SemanticDiagnosticKind::NoImplementationOfTrait {
1015                ty,
1016                trait_name,
1017                inference_errors,
1018            } => {
1019                if inference_errors.is_empty() {
1020                    format!(
1021                        "Implementation of trait `{}` not found on type `{}`. Did you import the \
1022                         correct trait and impl?",
1023                        trait_name.long(db),
1024                        ty.format(db)
1025                    )
1026                } else {
1027                    format!(
1028                        "Could not find implementation of trait `{}` on type `{}`.\n{}",
1029                        trait_name.long(db),
1030                        ty.format(db),
1031                        inference_errors.format(db)
1032                    )
1033                }
1034            }
1035            SemanticDiagnosticKind::CallExpressionRequiresFunction { ty, inference_errors } => {
1036                if inference_errors.is_empty() {
1037                    format!("Call expression requires a function, found `{}`.", ty.format(db))
1038                } else {
1039                    format!(
1040                        "Call expression requires a function, found `{}`.\n{}",
1041                        ty.format(db),
1042                        inference_errors.format(db)
1043                    )
1044                }
1045            }
1046            SemanticDiagnosticKind::CompilerTraitReImplementation { trait_id } => {
1047                format!(
1048                    "Trait `{}` should not be implemented outside of the corelib.",
1049                    trait_id.full_path(db)
1050                )
1051            }
1052            SemanticDiagnosticKind::ClosureInGlobalScope => {
1053                "Closures are not allowed in this context.".into()
1054            }
1055            SemanticDiagnosticKind::MaybeMissingColonColon => "Are you missing a `::`?.".into(),
1056            SemanticDiagnosticKind::CallingShadowedFunction { shadowed_function_name } => {
1057                format!(
1058                    "Function `{}` is shadowed by a local variable.",
1059                    shadowed_function_name.long(db)
1060                )
1061            }
1062            SemanticDiagnosticKind::RefClosureArgument => {
1063                "Arguments to closure functions cannot be references".into()
1064            }
1065            SemanticDiagnosticKind::RefClosureParam => {
1066                "Closure parameters cannot be references".into()
1067            }
1068            SemanticDiagnosticKind::MustBeNextToTypeOrTrait { trait_id } => {
1069                format!(
1070                    "'{}' implementation must be defined in the same module as either the type \
1071                     being dereferenced or the trait itself",
1072                    trait_id.name(db).long(db)
1073                )
1074            }
1075            SemanticDiagnosticKind::MutableCapturedVariable => {
1076                "Capture of mutable variables in a closure is not supported".into()
1077            }
1078            SemanticDiagnosticKind::NonTraitTypeConstrained { identifier, concrete_trait_id } => {
1079                format!(
1080                    "associated type `{}` not found for `{}`",
1081                    identifier.long(db),
1082                    concrete_trait_id.full_path(db)
1083                )
1084            }
1085            SemanticDiagnosticKind::DuplicateTypeConstraint {
1086                concrete_trait_type_id: trait_type_id,
1087            } => {
1088                format!(
1089                    "the value of the associated type `{}` in trait `{}` is already specified",
1090                    trait_type_id.trait_type(db).name(db).long(db),
1091                    trait_type_id.concrete_trait(db).full_path(db)
1092                )
1093            }
1094            SemanticDiagnosticKind::TypeConstraintsSyntaxNotEnabled => {
1095                "Type constraints syntax is not enabled in the current crate.".into()
1096            }
1097            SemanticDiagnosticKind::PatternMissingArgs(path) => {
1098                format!(
1099                    "Pattern missing subpattern for the payload of variant. Consider using `{}(_)`",
1100                    path.segments(db)
1101                        .elements(db)
1102                        .map(|seg| seg.identifier(db).long(db))
1103                        .join("::")
1104                )
1105            }
1106            SemanticDiagnosticKind::UndefinedMacroPlaceholder(name) => {
1107                format!("Undefined macro placeholder: '{}'.", name.long(db))
1108            }
1109            SemanticDiagnosticKind::UserDefinedInlineMacrosDisabled => {
1110                "User defined inline macros are disabled in the current crate.".into()
1111            }
1112            SemanticDiagnosticKind::NonNeverLetElseType => concat!(
1113                "`else` clause of `let...else` must exit the scope. ",
1114                "Consider using `return`, `continue`, ..."
1115            )
1116            .into(),
1117            SemanticDiagnosticKind::OnlyTypeOrConstParamsInNegImpl => {
1118                "Negative impls may only use type or const generic parameters.".into()
1119            }
1120        }
1121    }
1122    fn location(&self, db: &'db dyn Database) -> SpanInFile<'db> {
1123        if let SemanticDiagnosticKind::MacroGeneratedCodeParserDiagnostic(parser_diagnostic) =
1124            &self.kind
1125        {
1126            return SpanInFile { file_id: parser_diagnostic.file_id, span: parser_diagnostic.span };
1127        };
1128
1129        let mut location = self.stable_location.span_in_file(db);
1130        if self.after {
1131            location = location.after();
1132        }
1133        location
1134    }
1135
1136    fn severity(&self) -> Severity {
1137        match &self.kind {
1138            SemanticDiagnosticKind::UnusedVariable
1139            | SemanticDiagnosticKind::UnhandledMustUseType { .. }
1140            | SemanticDiagnosticKind::UnhandledMustUseFunction
1141            | SemanticDiagnosticKind::TraitInTraitMustBeExplicit
1142            | SemanticDiagnosticKind::ImplInImplMustBeExplicit
1143            | SemanticDiagnosticKind::TraitItemForbiddenInTheTrait
1144            | SemanticDiagnosticKind::TraitItemForbiddenInItsImpl
1145            | SemanticDiagnosticKind::ImplItemForbiddenInTheImpl
1146            | SemanticDiagnosticKind::UnstableFeature { .. }
1147            | SemanticDiagnosticKind::DeprecatedFeature { .. }
1148            | SemanticDiagnosticKind::UnusedImport { .. }
1149            | SemanticDiagnosticKind::CallingShadowedFunction { .. }
1150            | SemanticDiagnosticKind::UnusedConstant
1151            | SemanticDiagnosticKind::UnusedUse
1152            | SemanticDiagnosticKind::PatternMissingArgs(_)
1153            | SemanticDiagnosticKind::UnsupportedAllowAttrArguments => Severity::Warning,
1154            SemanticDiagnosticKind::PluginDiagnostic(diag) => diag.severity,
1155            _ => Severity::Error,
1156        }
1157    }
1158
1159    fn notes(&self, _db: &dyn Database) -> &[DiagnosticNote<'_>] {
1160        match &self.kind {
1161            SemanticDiagnosticKind::InnerFailedConstantCalculation(_, notes) => notes,
1162            SemanticDiagnosticKind::AssignmentToReprPtrVariable(notes) => notes,
1163            _ => &[],
1164        }
1165    }
1166
1167    fn error_code(&self) -> Option<ErrorCode> {
1168        self.kind.error_code()
1169    }
1170
1171    fn is_same_kind(&self, other: &Self) -> bool {
1172        other.kind == self.kind
1173    }
1174}
1175
1176#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
1177pub enum SemanticDiagnosticKind<'db> {
1178    ModuleFileNotFound(String),
1179    Unsupported,
1180    UnknownLiteral,
1181    UnknownBinaryOperator,
1182    UnknownTrait,
1183    UnknownImpl,
1184    UnexpectedElement {
1185        expected: Vec<ElementKind>,
1186        actual: ElementKind,
1187    },
1188    UnknownType,
1189    UnknownEnum,
1190    LiteralError(LiteralError<'db>),
1191    NotAVariant,
1192    NotAStruct,
1193    NotAType,
1194    NotATrait,
1195    NotAnImpl,
1196    ImplItemNotInTrait {
1197        impl_def_id: ImplDefId<'db>,
1198        impl_item_name: SmolStrId<'db>,
1199        trait_id: TraitId<'db>,
1200        item_kind: String,
1201    },
1202    ImplicitImplNotInferred {
1203        trait_impl_id: TraitImplId<'db>,
1204        concrete_trait_id: ConcreteTraitId<'db>,
1205    },
1206    GenericsNotSupportedInItem {
1207        scope: String,
1208        item_kind: String,
1209    },
1210    UnexpectedGenericArgs,
1211    UnknownMember,
1212    CannotCreateInstancesOfPhantomTypes,
1213    NonPhantomTypeContainingPhantomType,
1214    MemberSpecifiedMoreThanOnce,
1215    StructBaseStructExpressionNotLast,
1216    StructBaseStructExpressionNoEffect,
1217    ConstCycle,
1218    UseCycle,
1219    TypeAliasCycle,
1220    ImplAliasCycle,
1221    ImplRequirementCycle,
1222    MissingMember(SmolStrId<'db>),
1223    WrongNumberOfParameters {
1224        impl_def_id: ImplDefId<'db>,
1225        impl_function_id: ImplFunctionId<'db>,
1226        trait_id: TraitId<'db>,
1227        expected: usize,
1228        actual: usize,
1229    },
1230    WrongNumberOfArguments {
1231        expected: usize,
1232        actual: usize,
1233    },
1234    WrongParameterType {
1235        impl_def_id: ImplDefId<'db>,
1236        impl_function_id: ImplFunctionId<'db>,
1237        trait_id: TraitId<'db>,
1238        expected_ty: semantic::TypeId<'db>,
1239        actual_ty: semantic::TypeId<'db>,
1240    },
1241    VariantCtorNotImmutable,
1242    TraitParamMutable {
1243        trait_id: TraitId<'db>,
1244        function_id: TraitFunctionId<'db>,
1245    },
1246    ParameterShouldBeReference {
1247        impl_def_id: ImplDefId<'db>,
1248        impl_function_id: ImplFunctionId<'db>,
1249        trait_id: TraitId<'db>,
1250    },
1251    ParameterShouldNotBeReference {
1252        impl_def_id: ImplDefId<'db>,
1253        impl_function_id: ImplFunctionId<'db>,
1254        trait_id: TraitId<'db>,
1255    },
1256    WrongParameterName {
1257        impl_def_id: ImplDefId<'db>,
1258        impl_function_id: ImplFunctionId<'db>,
1259        trait_id: TraitId<'db>,
1260        expected_name: SmolStrId<'db>,
1261    },
1262    WrongGenericParamTraitForImplFunction {
1263        impl_def_id: ImplDefId<'db>,
1264        impl_function_id: ImplFunctionId<'db>,
1265        trait_id: TraitId<'db>,
1266        expected_trait: ConcreteTraitId<'db>,
1267        actual_trait: ConcreteTraitId<'db>,
1268    },
1269    WrongGenericParamKindForImplFunction {
1270        impl_def_id: ImplDefId<'db>,
1271        impl_function_id: ImplFunctionId<'db>,
1272        trait_id: TraitId<'db>,
1273        expected_kind: GenericKind,
1274        actual_kind: GenericKind,
1275    },
1276    WrongType {
1277        expected_ty: semantic::TypeId<'db>,
1278        actual_ty: semantic::TypeId<'db>,
1279    },
1280    InconsistentBinding,
1281    WrongArgumentType {
1282        expected_ty: semantic::TypeId<'db>,
1283        actual_ty: semantic::TypeId<'db>,
1284    },
1285    WrongReturnType {
1286        expected_ty: semantic::TypeId<'db>,
1287        actual_ty: semantic::TypeId<'db>,
1288    },
1289    WrongExprType {
1290        expected_ty: semantic::TypeId<'db>,
1291        actual_ty: semantic::TypeId<'db>,
1292    },
1293    WrongNumberOfGenericParamsForImplFunction {
1294        expected: usize,
1295        actual: usize,
1296    },
1297    WrongReturnTypeForImpl {
1298        impl_def_id: ImplDefId<'db>,
1299        impl_function_id: ImplFunctionId<'db>,
1300        trait_id: TraitId<'db>,
1301        expected_ty: semantic::TypeId<'db>,
1302        actual_ty: semantic::TypeId<'db>,
1303    },
1304    AmbiguousTrait {
1305        trait_function_id0: TraitFunctionId<'db>,
1306        trait_function_id1: TraitFunctionId<'db>,
1307    },
1308    VariableNotFound(SmolStrId<'db>),
1309    MissingVariableInPattern,
1310    VariableDefinedMultipleTimesInPattern(SmolStrId<'db>),
1311    StructMemberRedefinition {
1312        struct_id: StructId<'db>,
1313        member_name: SmolStrId<'db>,
1314    },
1315    EnumVariantRedefinition {
1316        enum_id: EnumId<'db>,
1317        variant_name: SmolStrId<'db>,
1318    },
1319    InfiniteSizeType(semantic::TypeId<'db>),
1320    ArrayOfZeroSizedElements(semantic::TypeId<'db>),
1321    ParamNameRedefinition {
1322        function_title_id: Option<FunctionTitleId<'db>>,
1323        param_name: SmolStrId<'db>,
1324    },
1325    ConditionNotBool(semantic::TypeId<'db>),
1326    IncompatibleArms {
1327        multi_arm_expr_kind: MultiArmExprKind,
1328        pending_ty: semantic::TypeId<'db>,
1329        different_ty: semantic::TypeId<'db>,
1330    },
1331    TypeHasNoMembers {
1332        ty: semantic::TypeId<'db>,
1333        member_name: SmolStrId<'db>,
1334    },
1335    CannotCallMethod {
1336        ty: semantic::TypeId<'db>,
1337        method_name: SmolStrId<'db>,
1338        inference_errors: TraitInferenceErrors<'db>,
1339        relevant_traits: Vec<String>,
1340    },
1341    NoSuchStructMember {
1342        struct_id: StructId<'db>,
1343        member_name: SmolStrId<'db>,
1344    },
1345    NoSuchTypeMember {
1346        ty: semantic::TypeId<'db>,
1347        member_name: SmolStrId<'db>,
1348    },
1349    MemberNotVisible(SmolStrId<'db>),
1350    NoSuchVariant {
1351        enum_id: EnumId<'db>,
1352        variant_name: SmolStrId<'db>,
1353    },
1354    ReturnTypeNotErrorPropagateType,
1355    IncompatibleErrorPropagateType {
1356        return_ty: semantic::TypeId<'db>,
1357        err_ty: semantic::TypeId<'db>,
1358    },
1359    ErrorPropagateOnNonErrorType(semantic::TypeId<'db>),
1360    UnhandledMustUseType(semantic::TypeId<'db>),
1361    UnstableFeature {
1362        feature_name: SmolStrId<'db>,
1363        note: Option<SmolStrId<'db>>,
1364    },
1365    DeprecatedFeature {
1366        feature_name: SmolStrId<'db>,
1367        note: Option<SmolStrId<'db>>,
1368    },
1369    InternalFeature {
1370        feature_name: SmolStrId<'db>,
1371        note: Option<SmolStrId<'db>>,
1372    },
1373    FeatureMarkerDiagnostic(FeatureMarkerDiagnostic),
1374    UnhandledMustUseFunction,
1375    UnusedVariable,
1376    UnusedConstant,
1377    UnusedUse,
1378    MultipleConstantDefinition(SmolStrId<'db>),
1379    MultipleDefinitionforBinding(SmolStrId<'db>),
1380    MultipleGenericItemDefinition(SmolStrId<'db>),
1381    UnsupportedUseItemInStatement,
1382    ConstGenericParamNotSupported,
1383    NegativeImplsNotEnabled,
1384    NegativeImplsOnlyOnImpls,
1385    RefArgNotAVariable,
1386    RefArgNotMutable,
1387    RefArgNotExplicit,
1388    ImmutableArgWithModifiers,
1389    AssignmentToImmutableVar,
1390    InvalidLhsForAssignment,
1391    InvalidMemberExpression,
1392    InvalidPath,
1393    PathNotFound(NotFoundItemType),
1394    AmbiguousPath(Vec<ModuleItemId<'db>>),
1395    UseSelfNonMulti,
1396    UseSelfEmptyPath,
1397    UseStarEmptyPath,
1398    GlobalUsesNotSupportedInEdition(Edition),
1399    TraitInTraitMustBeExplicit,
1400    ImplInImplMustBeExplicit,
1401    TraitItemForbiddenInTheTrait,
1402    TraitItemForbiddenInItsImpl,
1403    ImplItemForbiddenInTheImpl,
1404    SuperUsedInRootModule,
1405    SuperUsedInMacroCallTopLevel,
1406    ItemNotVisible(ModuleItemId<'db>, Vec<ModuleId<'db>>),
1407    UnusedImport(UseId<'db>),
1408    RedundantModifier {
1409        current_modifier: SmolStrId<'db>,
1410        previous_modifier: SmolStrId<'db>,
1411    },
1412    ReferenceLocalVariable,
1413    UnexpectedEnumPattern(semantic::TypeId<'db>),
1414    UnexpectedStructPattern(semantic::TypeId<'db>),
1415    UnexpectedTuplePattern(semantic::TypeId<'db>),
1416    UnexpectedFixedSizeArrayPattern(semantic::TypeId<'db>),
1417    WrongNumberOfTupleElements {
1418        expected: usize,
1419        actual: usize,
1420    },
1421    WrongNumberOfFixedSizeArrayElements {
1422        expected: usize,
1423        actual: usize,
1424    },
1425    WrongEnum {
1426        expected_enum: EnumId<'db>,
1427        actual_enum: EnumId<'db>,
1428    },
1429    InvalidCopyTraitImpl(InferenceError<'db>),
1430    InvalidDropTraitImpl(InferenceError<'db>),
1431    InvalidImplItem(SmolStrId<'db>),
1432    MissingItemsInImpl(Vec<SmolStrId<'db>>),
1433    PassPanicAsNopanic {
1434        impl_function_id: ImplFunctionId<'db>,
1435        trait_id: TraitId<'db>,
1436    },
1437    PassConstAsNonConst {
1438        impl_function_id: ImplFunctionId<'db>,
1439        trait_id: TraitId<'db>,
1440    },
1441    PanicableFromNonPanicable,
1442    PanicableExternFunction,
1443    MacroGeneratedCodeParserDiagnostic(ParserDiagnostic<'db>),
1444    PluginDiagnostic(PluginDiagnostic<'db>),
1445    NameDefinedMultipleTimes(SmolStrId<'db>),
1446    NonPrivateUseStar,
1447    SelfGlobalUse,
1448    NamedArgumentsAreNotSupported,
1449    ArgPassedToNegativeImpl,
1450    UnnamedArgumentFollowsNamed,
1451    NamedArgumentMismatch {
1452        expected: SmolStrId<'db>,
1453        found: SmolStrId<'db>,
1454    },
1455    UnsupportedOutsideOfFunction(UnsupportedOutsideOfFunctionFeatureName),
1456    ConstTypeNotVarFree,
1457    UnsupportedConstant,
1458    FailedConstantCalculation,
1459    ConstantCalculationDepthExceeded,
1460    InnerFailedConstantCalculation(Box<SemanticDiagnostic<'db>>, Vec<DiagnosticNote<'db>>),
1461    DivisionByZero,
1462    ExternTypeWithImplGenericsNotSupported,
1463    MissingSemicolon,
1464    TraitMismatch {
1465        expected_trt: semantic::ConcreteTraitId<'db>,
1466        actual_trt: semantic::ConcreteTraitId<'db>,
1467    },
1468    DerefNonRef {
1469        ty: semantic::TypeId<'db>,
1470    },
1471    InternalInferenceError(InferenceError<'db>),
1472    NoImplementationOfIndexOperator {
1473        ty: semantic::TypeId<'db>,
1474        inference_errors: TraitInferenceErrors<'db>,
1475    },
1476    NoImplementationOfTrait {
1477        ty: semantic::TypeId<'db>,
1478        trait_name: SmolStrId<'db>,
1479        inference_errors: TraitInferenceErrors<'db>,
1480    },
1481    CallExpressionRequiresFunction {
1482        ty: semantic::TypeId<'db>,
1483        inference_errors: TraitInferenceErrors<'db>,
1484    },
1485    MultipleImplementationOfIndexOperator(semantic::TypeId<'db>),
1486
1487    UnsupportedInlineArguments,
1488    RedundantInlineAttribute,
1489    InlineAttrForExternFunctionNotAllowed,
1490    InlineAlwaysWithImplGenericArgNotAllowed,
1491    TailExpressionNotAllowedInLoop,
1492    ContinueOnlyAllowedInsideALoop,
1493    BreakOnlyAllowedInsideALoop,
1494    BreakWithValueOnlyAllowedInsideALoop,
1495    ErrorPropagateNotAllowedInsideALoop,
1496    ImplicitPrecedenceAttrForExternFunctionNotAllowed,
1497    RedundantImplicitPrecedenceAttribute,
1498    UnsupportedImplicitPrecedenceArguments,
1499    UnsupportedFeatureAttrArguments,
1500    UnsupportedAllowAttrArguments,
1501    UnsupportedPubArgument,
1502    UnknownStatementAttribute,
1503    InlineMacroNotFound(SmolStrId<'db>),
1504    InlineMacroFailed(SmolStrId<'db>),
1505    InlineMacroNoMatchingRule(SmolStrId<'db>),
1506    MacroCallToNotAMacro(SmolStrId<'db>),
1507    UnknownGenericParam(SmolStrId<'db>),
1508    PositionalGenericAfterNamed,
1509    GenericArgDuplicate(SmolStrId<'db>),
1510    TooManyGenericArguments {
1511        expected: usize,
1512        actual: usize,
1513    },
1514    GenericArgOutOfOrder(SmolStrId<'db>),
1515    CouponForExternFunctionNotAllowed,
1516    CouponArgumentNoModifiers,
1517    /// Coupons are disabled in the current crate.
1518    CouponsDisabled,
1519    /// Representation pointers are disabled in the current crate.
1520    ReprPtrsDisabled,
1521    /// Cannot assign to a variable with a taken pointer.
1522    AssignmentToReprPtrVariable(Vec<DiagnosticNote<'db>>),
1523    FixedSizeArrayTypeNonSingleType,
1524    FixedSizeArrayTypeEmptySize,
1525    FixedSizeArrayNonNumericSize,
1526    FixedSizeArrayNonSingleValue,
1527    FixedSizeArraySizeTooBig,
1528    SelfNotSupportedInContext,
1529    SelfMustBeFirst,
1530    DollarNotSupportedInContext,
1531    UnknownResolverModifier {
1532        modifier: SmolStrId<'db>,
1533    },
1534    EmptyPathAfterResolverModifier,
1535    DerefCycle {
1536        deref_chain: String,
1537    },
1538    CompilerTraitReImplementation {
1539        trait_id: TraitId<'db>,
1540    },
1541    ClosureInGlobalScope,
1542    MaybeMissingColonColon,
1543    CallingShadowedFunction {
1544        shadowed_function_name: SmolStrId<'db>,
1545    },
1546    RefClosureArgument,
1547    RefClosureParam,
1548    MustBeNextToTypeOrTrait {
1549        trait_id: TraitId<'db>,
1550    },
1551    MutableCapturedVariable,
1552    NonTraitTypeConstrained {
1553        identifier: SmolStrId<'db>,
1554        concrete_trait_id: ConcreteTraitId<'db>,
1555    },
1556    DuplicateTypeConstraint {
1557        concrete_trait_type_id: ConcreteTraitTypeId<'db>,
1558    },
1559    TypeConstraintsSyntaxNotEnabled,
1560    PatternMissingArgs(ast::ExprPath<'db>),
1561    UndefinedMacroPlaceholder(SmolStrId<'db>),
1562    UserDefinedInlineMacrosDisabled,
1563    NonNeverLetElseType,
1564    OnlyTypeOrConstParamsInNegImpl,
1565}
1566
1567/// The kind of an expression with multiple possible return types.
1568#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1569pub enum MultiArmExprKind {
1570    If,
1571    Match,
1572    Loop,
1573}
1574
1575impl<'db> SemanticDiagnosticKind<'db> {
1576    pub fn error_code(&self) -> Option<ErrorCode> {
1577        Some(match &self {
1578            Self::UnusedVariable => error_code!(E0001),
1579            Self::CannotCallMethod { .. } => {
1580                error_code!(E0002)
1581            }
1582            Self::MissingMember(_) => error_code!(E0003),
1583            Self::MissingItemsInImpl(_) => error_code!(E0004),
1584            Self::ModuleFileNotFound(_) => error_code!(E0005),
1585            Self::PathNotFound(_) => error_code!(E0006),
1586            Self::NoSuchTypeMember { .. } => error_code!(E0007),
1587            _ => return None,
1588        })
1589    }
1590}
1591
1592// TODO(Gil): It seems to have the same functionality as ElementKind, maybe we can merge them.
1593#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1594pub enum NotFoundItemType {
1595    Identifier,
1596    Function,
1597    Type,
1598    Trait,
1599    Impl,
1600    Macro,
1601}
1602
1603#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1604pub enum UnsupportedOutsideOfFunctionFeatureName {
1605    ReturnStatement,
1606    ErrorPropagate,
1607}
1608
1609#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1610pub enum ElementKind {
1611    Constant,
1612    Variable,
1613    Module,
1614    Function,
1615    Type,
1616    Variant,
1617    Trait,
1618    Impl,
1619    Macro,
1620}
1621impl<'db> From<&ResolvedConcreteItem<'db>> for ElementKind {
1622    fn from(val: &ResolvedConcreteItem<'db>) -> Self {
1623        match val {
1624            ResolvedConcreteItem::Constant(_) => ElementKind::Constant,
1625            ResolvedConcreteItem::Module(_) => ElementKind::Module,
1626            ResolvedConcreteItem::Function(_) => ElementKind::Function,
1627            ResolvedConcreteItem::Type(_) => ElementKind::Type,
1628            ResolvedConcreteItem::Variant(_) => ElementKind::Variant,
1629            ResolvedConcreteItem::Trait(_) | ResolvedConcreteItem::SelfTrait(_) => {
1630                ElementKind::Trait
1631            }
1632            ResolvedConcreteItem::Impl(_) => ElementKind::Impl,
1633            ResolvedConcreteItem::Macro(_) => ElementKind::Macro,
1634        }
1635    }
1636}
1637impl<'db> From<&ResolvedGenericItem<'db>> for ElementKind {
1638    fn from(val: &ResolvedGenericItem<'db>) -> Self {
1639        match val {
1640            ResolvedGenericItem::GenericConstant(_)
1641            | ResolvedGenericItem::TraitItem(TraitItemId::Constant(_)) => ElementKind::Constant,
1642            ResolvedGenericItem::Module(_) => ElementKind::Module,
1643            ResolvedGenericItem::GenericFunction(_)
1644            | ResolvedGenericItem::TraitItem(TraitItemId::Function(_)) => ElementKind::Function,
1645            ResolvedGenericItem::GenericType(_)
1646            | ResolvedGenericItem::GenericTypeAlias(_)
1647            | ResolvedGenericItem::TraitItem(TraitItemId::Type(_)) => ElementKind::Type,
1648            ResolvedGenericItem::Variant(_) => ElementKind::Variant,
1649            ResolvedGenericItem::Trait(_) => ElementKind::Trait,
1650            ResolvedGenericItem::Impl(_)
1651            | ResolvedGenericItem::GenericImplAlias(_)
1652            | ResolvedGenericItem::TraitItem(TraitItemId::Impl(_)) => ElementKind::Impl,
1653            ResolvedGenericItem::Variable(_) => ElementKind::Variable,
1654            ResolvedGenericItem::Macro(_) => ElementKind::Macro,
1655        }
1656    }
1657}
1658impl Display for ElementKind {
1659    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1660        let res = match self {
1661            ElementKind::Constant => "constant",
1662            ElementKind::Variable => "variable",
1663            ElementKind::Module => "module",
1664            ElementKind::Function => "function",
1665            ElementKind::Type => "type",
1666            ElementKind::Variant => "variant",
1667            ElementKind::Trait => "trait",
1668            ElementKind::Impl => "impl",
1669            ElementKind::Macro => "macro",
1670        };
1671        write!(f, "{res}")
1672    }
1673}
1674
1675/// A list of trait functions and the inference errors that occurred while trying to infer them.
1676#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
1677pub struct TraitInferenceErrors<'db> {
1678    pub traits_and_errors: Vec<(TraitFunctionId<'db>, InferenceError<'db>)>,
1679}
1680impl<'db> TraitInferenceErrors<'db> {
1681    /// Is the error list empty.
1682    pub fn is_empty(&self) -> bool {
1683        self.traits_and_errors.is_empty()
1684    }
1685    /// Format the list of errors.
1686    fn format(&self, db: &dyn Database) -> String {
1687        self.traits_and_errors
1688            .iter()
1689            .map(|(trait_function_id, inference_error)| {
1690                format!(
1691                    "Candidate `{}` inference failed with: {}",
1692                    trait_function_id.full_path(db),
1693                    inference_error.format(db)
1694                )
1695            })
1696            .join("\n")
1697    }
1698}