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, DiagnosticLocation, DiagnosticNote, DiagnosticsBuilder,
13    ErrorCode, Severity, error_code,
14};
15use cairo_lang_filesystem::db::Edition;
16use cairo_lang_filesystem::ids::SmolStrId;
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::StructMemberRedefinition { struct_id, member_name } => {
408                format!(
409                    r#"Redefinition of member "{}" on struct "{}"."#,
410                    member_name.long(db),
411                    struct_id.full_path(db)
412                )
413            }
414            SemanticDiagnosticKind::EnumVariantRedefinition { enum_id, variant_name } => {
415                format!(
416                    r#"Redefinition of variant "{}" on enum "{}"."#,
417                    variant_name.long(db),
418                    enum_id.full_path(db)
419                )
420            }
421            SemanticDiagnosticKind::InfiniteSizeType(ty) => {
422                format!(r#"Recursive type "{}" has infinite size."#, ty.format(db))
423            }
424            SemanticDiagnosticKind::ArrayOfZeroSizedElements(ty) => {
425                format!(r#"Cannot have array of type "{}" that is zero sized."#, ty.format(db))
426            }
427            SemanticDiagnosticKind::ParamNameRedefinition { function_title_id, param_name } => {
428                format!(
429                    r#"Redefinition of parameter name "{}"{}"#,
430                    param_name.long(db),
431                    function_title_id
432                        .map(|function_title_id| format!(
433                            r#" in function "{}"."#,
434                            function_title_id.full_path(db)
435                        ))
436                        .unwrap_or(".".into()),
437                )
438            }
439            SemanticDiagnosticKind::ConditionNotBool(condition_ty) => {
440                format!(r#"Condition has type "{}", expected bool."#, condition_ty.format(db))
441            }
442            SemanticDiagnosticKind::IncompatibleArms {
443                multi_arm_expr_kind: incompatibility_kind,
444                pending_ty: first_ty,
445                different_ty,
446            } => {
447                let prefix = match incompatibility_kind {
448                    MultiArmExprKind::Match => "Match arms have incompatible types",
449                    MultiArmExprKind::If => "If blocks have incompatible types",
450                    MultiArmExprKind::Loop => "Loop has incompatible return types",
451                };
452                format!(r#"{prefix}: "{}" and "{}""#, first_ty.format(db), different_ty.format(db))
453            }
454            SemanticDiagnosticKind::TypeHasNoMembers { ty, member_name: _ } => {
455                format!(r#"Type "{}" has no members."#, ty.format(db))
456            }
457            SemanticDiagnosticKind::NoSuchStructMember { struct_id, member_name } => {
458                format!(
459                    r#"Struct "{}" has no member "{}""#,
460                    struct_id.full_path(db),
461                    member_name.long(db)
462                )
463            }
464            SemanticDiagnosticKind::NoSuchTypeMember { ty, member_name } => {
465                format!(r#"Type "{}" has no member "{}""#, ty.format(db), member_name.long(db))
466            }
467            SemanticDiagnosticKind::MemberNotVisible(member_name) => {
468                format!(r#"Member "{}" is not visible in this context."#, member_name.long(db))
469            }
470            SemanticDiagnosticKind::NoSuchVariant { enum_id, variant_name } => {
471                format!(
472                    r#"Enum "{}" has no variant "{}""#,
473                    enum_id.full_path(db),
474                    variant_name.long(db)
475                )
476            }
477            SemanticDiagnosticKind::ReturnTypeNotErrorPropagateType => {
478                "`?` can only be used in a function with `Option` or `Result` return type.".into()
479            }
480            SemanticDiagnosticKind::IncompatibleErrorPropagateType { return_ty, err_ty } => {
481                format!(
482                    r#"Return type "{}" does not wrap error "{}""#,
483                    return_ty.format(db),
484                    err_ty.format(db)
485                )
486            }
487            SemanticDiagnosticKind::ErrorPropagateOnNonErrorType(ty) => {
488                format!(r#"Type "{}" can not error propagate"#, ty.format(db))
489            }
490            SemanticDiagnosticKind::UnhandledMustUseType(ty) => {
491                format!(r#"Unhandled `#[must_use]` type `{}`"#, ty.format(db))
492            }
493            SemanticDiagnosticKind::UnhandledMustUseFunction => {
494                "Unhandled `#[must_use]` function.".into()
495            }
496            SemanticDiagnosticKind::UnstableFeature { feature_name, note } => {
497                format!(
498                    "Usage of unstable feature `{0}` with no `#[feature({0})]` attribute.{1}",
499                    feature_name.long(db),
500                    note.as_ref()
501                        .map(|note| format!(" Note: {}", note.long(db)))
502                        .unwrap_or_default()
503                )
504            }
505            SemanticDiagnosticKind::DeprecatedFeature { feature_name, note } => {
506                format!(
507                    "Usage of deprecated feature `{0}` with no `#[feature({0})]` attribute.{1}",
508                    feature_name.long(db),
509                    note.as_ref()
510                        .map(|note| format!(" Note: {}", note.long(db)))
511                        .unwrap_or_default()
512                )
513            }
514            SemanticDiagnosticKind::InternalFeature { feature_name, note } => {
515                format!(
516                    "Usage of internal feature `{0}` with no `#[feature({0})]` attribute.{1}",
517                    feature_name.long(db),
518                    note.as_ref()
519                        .map(|note| format!(" Note: {}", note.long(db)))
520                        .unwrap_or_default()
521                )
522            }
523            SemanticDiagnosticKind::FeatureMarkerDiagnostic(diagnostic) => match diagnostic {
524                FeatureMarkerDiagnostic::MultipleMarkers => {
525                    "Multiple feature marker attributes.".into()
526                }
527                FeatureMarkerDiagnostic::MissingAllowFeature => {
528                    "Missing `feature` arg for feature marker attribute.".into()
529                }
530                FeatureMarkerDiagnostic::UnsupportedArgument => {
531                    "Unsupported argument for feature marker attribute.".into()
532                }
533                FeatureMarkerDiagnostic::DuplicatedArgument => {
534                    "Duplicated argument for feature marker attribute.".into()
535                }
536            },
537            SemanticDiagnosticKind::UnusedVariable => {
538                "Unused variable. Consider ignoring by prefixing with `_`.".into()
539            }
540            SemanticDiagnosticKind::UnusedConstant => {
541                "Unused constant. Consider ignoring by prefixing with `_`.".into()
542            }
543            SemanticDiagnosticKind::MultipleConstantDefinition(constant_name) => {
544                format!(r#"Multiple definitions of constant "{}"."#, constant_name.long(db))
545            }
546            SemanticDiagnosticKind::UnusedUse => "Unused use.".into(),
547            SemanticDiagnosticKind::MultipleDefinitionforBinding(name) => {
548                format!(
549                    r#"Multiple definitions of identifier '{}' as constant and variable."#,
550                    name.long(db)
551                )
552            }
553            SemanticDiagnosticKind::MultipleGenericItemDefinition(type_name) => {
554                format!(r#"Multiple definitions of an item "{}"."#, type_name.long(db))
555            }
556            SemanticDiagnosticKind::UnsupportedUseItemInStatement => {
557                "Unsupported use item in statement.".into()
558            }
559            SemanticDiagnosticKind::InvalidMemberExpression => "Invalid member expression.".into(),
560            SemanticDiagnosticKind::InvalidPath => "Invalid path.".into(),
561            SemanticDiagnosticKind::RefArgNotAVariable => "ref argument must be a variable.".into(),
562            SemanticDiagnosticKind::RefArgNotMutable => {
563                "ref argument must be a mutable variable.".into()
564            }
565            SemanticDiagnosticKind::RefArgNotExplicit => {
566                "ref argument must be passed with a preceding 'ref'.".into()
567            }
568            SemanticDiagnosticKind::ImmutableArgWithModifiers => {
569                "Argument to immutable parameter cannot have modifiers.".into()
570            }
571            SemanticDiagnosticKind::AssignmentToImmutableVar => {
572                "Cannot assign to an immutable variable.".into()
573            }
574            SemanticDiagnosticKind::InvalidLhsForAssignment => {
575                "Invalid left-hand side of assignment.".into()
576            }
577            SemanticDiagnosticKind::PathNotFound(item_type) => match item_type {
578                NotFoundItemType::Identifier => "Identifier not found.".into(),
579                NotFoundItemType::Function => "Function not found.".into(),
580                NotFoundItemType::Type => "Type not found.".into(),
581                NotFoundItemType::Trait => "Trait not found.".into(),
582                NotFoundItemType::Impl => "Impl not found.".into(),
583                NotFoundItemType::Macro => "Macro not found.".into(),
584            },
585            SemanticDiagnosticKind::AmbiguousPath(module_items) => {
586                format!(
587                    "Ambiguous path. Multiple matching items: {}",
588                    module_items.iter().map(|item| format!("`{}`", item.full_path(db))).join(", ")
589                )
590            }
591            SemanticDiagnosticKind::UseSelfNonMulti => {
592                "`self` in `use` items is not allowed not in multi.".into()
593            }
594            SemanticDiagnosticKind::UseSelfEmptyPath => {
595                "`self` in `use` items is not allowed for empty path.".into()
596            }
597            SemanticDiagnosticKind::UseStarEmptyPath => {
598                "`*` in `use` items is not allowed for empty path.".into()
599            }
600            SemanticDiagnosticKind::GlobalUsesNotSupportedInEdition(edition) => {
601                format!("Global `use` item is not supported in `{edition:?}` edition.")
602            }
603            SemanticDiagnosticKind::TraitInTraitMustBeExplicit => {
604                "In a trait, paths of the same trait must be fully explicit. Either use `Self` if \
605                 this is the intention, or explicitly specify all the generic arguments."
606                    .to_string()
607            }
608            SemanticDiagnosticKind::ImplInImplMustBeExplicit => {
609                "In an impl, paths of the same impl must be fully explicit. Either use `Self` if \
610                 this is the intention, or explicitly specify all the generic arguments."
611                    .to_string()
612            }
613            SemanticDiagnosticKind::TraitItemForbiddenInTheTrait => {
614                "In a trait, paths of the same trait are not allowed. Did you mean to use `Self::`?"
615                    .to_string()
616            }
617            SemanticDiagnosticKind::TraitItemForbiddenInItsImpl => "In an impl, paths of the \
618                                                                    impl's trait are not allowed. \
619                                                                    Did you mean to use `Self::`?"
620                .to_string(),
621            SemanticDiagnosticKind::ImplItemForbiddenInTheImpl => {
622                "In an impl, paths of the same impl are not allowed. Did you mean to use `Self::`?"
623                    .to_string()
624            }
625            SemanticDiagnosticKind::SuperUsedInRootModule => {
626                "'super' cannot be used for the crate's root module.".into()
627            }
628            SemanticDiagnosticKind::SuperUsedInMacroCallTopLevel => {
629                "`super` used in macro call top level.".into()
630            }
631            SemanticDiagnosticKind::ItemNotVisible(item_id, containing_modules) => {
632                format!(
633                    "Item `{}` is not visible in this context{}.",
634                    item_id.full_path(db),
635                    if containing_modules.is_empty() {
636                        "".to_string()
637                    } else if let [module_id] = &containing_modules[..] {
638                        format!(" through module `{}`", module_id.full_path(db))
639                    } else {
640                        format!(
641                            " through any of the modules: {}",
642                            containing_modules
643                                .iter()
644                                .map(|module_id| format!("`{}`", module_id.full_path(db)))
645                                .join(", ")
646                        )
647                    }
648                )
649            }
650            SemanticDiagnosticKind::UnusedImport(use_id) => {
651                format!("Unused import: `{}`", use_id.full_path(db))
652            }
653            SemanticDiagnosticKind::UnexpectedEnumPattern(ty) => {
654                format!(r#"Unexpected type for enum pattern. "{}" is not an enum."#, ty.format(db),)
655            }
656            SemanticDiagnosticKind::UnexpectedStructPattern(ty) => {
657                format!(
658                    r#"Unexpected type for struct pattern. "{}" is not a struct."#,
659                    ty.format(db),
660                )
661            }
662            SemanticDiagnosticKind::UnexpectedTuplePattern(ty) => {
663                format!(r#"Unexpected type for tuple pattern. "{}" is not a tuple."#, ty.format(db),)
664            }
665            SemanticDiagnosticKind::UnexpectedFixedSizeArrayPattern(ty) => {
666                format!(
667                    "Unexpected type for fixed size array pattern. \"{}\" is not a fixed size \
668                     array.",
669                    ty.format(db),
670                )
671            }
672            SemanticDiagnosticKind::WrongNumberOfTupleElements { expected, actual } => format!(
673                r#"Wrong number of tuple elements in pattern. Expected: {expected}. Got: {actual}."#,
674            ),
675            SemanticDiagnosticKind::WrongNumberOfFixedSizeArrayElements { expected, actual } => {
676                format!(
677                    "Wrong number of fixed size array elements in pattern. Expected: {expected}. \
678                     Got: {actual}.",
679                )
680            }
681            SemanticDiagnosticKind::WrongEnum { expected_enum, actual_enum } => {
682                format!(
683                    r#"Wrong enum in pattern. Expected: "{}". Got: "{}"."#,
684                    expected_enum.full_path(db),
685                    actual_enum.full_path(db)
686                )
687            }
688            SemanticDiagnosticKind::RedundantModifier { current_modifier, previous_modifier } => {
689                format!(
690                    "`{}` modifier was specified after another modifier (`{}`). Only a single \
691                     modifier is allowed.",
692                    current_modifier.long(db),
693                    previous_modifier.long(db)
694                )
695            }
696            SemanticDiagnosticKind::ReferenceLocalVariable => {
697                "`ref` is only allowed for function parameters, not for local variables."
698                    .to_string()
699            }
700            SemanticDiagnosticKind::InvalidCopyTraitImpl(inference_error) => {
701                format!("Invalid copy trait implementation, {}", inference_error.format(db))
702            }
703            SemanticDiagnosticKind::InvalidDropTraitImpl(inference_error) => {
704                format!("Invalid drop trait implementation, {}", inference_error.format(db))
705            }
706            SemanticDiagnosticKind::InvalidImplItem(item_kw) => {
707                format!("`{}` is not allowed inside impl.", item_kw.long(db))
708            }
709            SemanticDiagnosticKind::MissingItemsInImpl(item_names) => {
710                format!(
711                    "Not all trait items are implemented. Missing: {}.",
712                    item_names.iter().map(|name| format!("'{}'", name.long(db))).join(", ")
713                )
714            }
715            SemanticDiagnosticKind::PassPanicAsNopanic { impl_function_id, trait_id } => {
716                let name = impl_function_id.name(db).long(db);
717                let trait_name = trait_id.name(db).long(db);
718                format!(
719                    "The signature of function `{name}` is incompatible with trait \
720                     `{trait_name}`. The trait function is declared as nopanic."
721                )
722            }
723            SemanticDiagnosticKind::PassConstAsNonConst { impl_function_id, trait_id } => {
724                let name = impl_function_id.name(db).long(db);
725                let trait_name = trait_id.name(db).long(db);
726                format!(
727                    "The signature of function `{name}` is incompatible with trait \
728                     `{trait_name}`. The trait function is declared as const."
729                )
730            }
731            SemanticDiagnosticKind::PanicableFromNonPanicable => {
732                "Function is declared as nopanic but calls a function that may panic.".into()
733            }
734            SemanticDiagnosticKind::PanicableExternFunction => {
735                "An extern function must be marked as nopanic.".into()
736            }
737            SemanticDiagnosticKind::PluginDiagnostic(diagnostic) => {
738                format!("Plugin diagnostic: {}", diagnostic.message)
739            }
740            SemanticDiagnosticKind::MacroGeneratedCodeParserDiagnostic(parser_diagnostic) => {
741                format!("Parser error in macro-expanded code: {}", parser_diagnostic.format(db))
742            }
743            SemanticDiagnosticKind::NameDefinedMultipleTimes(name) => {
744                format!("The name `{}` is defined multiple times.", name.long(db))
745            }
746            SemanticDiagnosticKind::NonPrivateUseStar => {
747                "`pub` not supported for global `use`.".into()
748            }
749            SemanticDiagnosticKind::SelfGlobalUse => {
750                "cannot glob-import a module into itself".into()
751            }
752            SemanticDiagnosticKind::NamedArgumentsAreNotSupported => {
753                "Named arguments are not supported in this context.".into()
754            }
755            SemanticDiagnosticKind::UnnamedArgumentFollowsNamed => {
756                "Unnamed arguments cannot follow named arguments.".into()
757            }
758            SemanticDiagnosticKind::NamedArgumentMismatch { expected, found } => {
759                format!(
760                    "Unexpected argument name. Expected: '{}', found '{}'.",
761                    expected.long(db),
762                    found.long(db)
763                )
764            }
765            SemanticDiagnosticKind::UnsupportedOutsideOfFunction(feature_name) => {
766                let feature_name_str = match feature_name {
767                    UnsupportedOutsideOfFunctionFeatureName::ReturnStatement => "Return statement",
768                    UnsupportedOutsideOfFunctionFeatureName::ErrorPropagate => "The '?' operator",
769                };
770                format!("{feature_name_str} is not supported outside of functions.")
771            }
772            SemanticDiagnosticKind::UnsupportedConstant => {
773                "This expression is not supported as constant.".into()
774            }
775            SemanticDiagnosticKind::FailedConstantCalculation => {
776                "Failed to calculate constant.".into()
777            }
778            SemanticDiagnosticKind::ConstantCalculationDepthExceeded => {
779                "Constant calculation depth exceeded.".into()
780            }
781            SemanticDiagnosticKind::InnerFailedConstantCalculation(inner, _) => inner.format(db),
782            SemanticDiagnosticKind::DivisionByZero => "Division by zero.".into(),
783            SemanticDiagnosticKind::ExternTypeWithImplGenericsNotSupported => {
784                "Extern types with impl generics are not supported.".into()
785            }
786            SemanticDiagnosticKind::MissingSemicolon => "Missing semicolon".into(),
787            SemanticDiagnosticKind::TraitMismatch { expected_trt, actual_trt } => {
788                format!(
789                    "Expected an impl of `{:?}`. Got an impl of `{:?}`.",
790                    expected_trt.debug(db),
791                    actual_trt.debug(db),
792                )
793            }
794            SemanticDiagnosticKind::InternalInferenceError(err) => err.format(db),
795            SemanticDiagnosticKind::DerefNonRef { ty } => {
796                format!("Type `{}` cannot be dereferenced", ty.format(db))
797            }
798            SemanticDiagnosticKind::NoImplementationOfIndexOperator { ty, inference_errors } => {
799                if inference_errors.is_empty() {
800                    format!(
801                        "Type `{}` does not implement the `Index` trait nor the `IndexView` trait.",
802                        ty.format(db)
803                    )
804                } else {
805                    format!(
806                        "Type `{}` could not be indexed.\n{}",
807                        ty.format(db),
808                        inference_errors.format(db)
809                    )
810                }
811            }
812            SemanticDiagnosticKind::MultipleImplementationOfIndexOperator(ty) => {
813                format!(
814                    r#"Type "{}" implements both the "Index" trait and the "IndexView" trait."#,
815                    ty.format(db)
816                )
817            }
818            SemanticDiagnosticKind::UnsupportedInlineArguments => {
819                "Unsupported `inline` arguments.".into()
820            }
821            SemanticDiagnosticKind::RedundantInlineAttribute => {
822                "Redundant `inline` attribute.".into()
823            }
824            SemanticDiagnosticKind::InlineAttrForExternFunctionNotAllowed => {
825                "`inline` attribute is not allowed for extern functions.".into()
826            }
827            SemanticDiagnosticKind::InlineAlwaysWithImplGenericArgNotAllowed => {
828                "`#[inline(always)]` is not allowed for functions with impl generic parameters."
829                    .into()
830            }
831            SemanticDiagnosticKind::CannotCallMethod {
832                ty,
833                method_name,
834                inference_errors,
835                relevant_traits,
836            } => {
837                if !inference_errors.is_empty() {
838                    return format!(
839                        "Method `{}` could not be called on type `{}`.\n{}",
840                        method_name.long(db),
841                        ty.format(db),
842                        inference_errors.format(db)
843                    );
844                }
845                if !relevant_traits.is_empty() {
846                    let suggestions = relevant_traits
847                        .iter()
848                        .map(|trait_path| format!("`{trait_path}`"))
849                        .collect::<Vec<_>>()
850                        .join(", ");
851
852                    format!(
853                        "Method `{}` not found on type `{}`. Consider importing one of the \
854                         following traits: {}.",
855                        method_name.long(db),
856                        ty.format(db),
857                        suggestions
858                    )
859                } else {
860                    format!(
861                        "Method `{}` not found on type `{}`. Did you import the correct trait and \
862                         impl?",
863                        method_name.long(db),
864                        ty.format(db)
865                    )
866                }
867            }
868            SemanticDiagnosticKind::TailExpressionNotAllowedInLoop => {
869                "Tail expression not allowed in a `loop` block.".into()
870            }
871            SemanticDiagnosticKind::ContinueOnlyAllowedInsideALoop => {
872                "`continue` only allowed inside a `loop`.".into()
873            }
874            SemanticDiagnosticKind::BreakOnlyAllowedInsideALoop => {
875                "`break` only allowed inside a `loop`.".into()
876            }
877            SemanticDiagnosticKind::BreakWithValueOnlyAllowedInsideALoop => {
878                "Can only break with a value inside a `loop`.".into()
879            }
880            SemanticDiagnosticKind::ErrorPropagateNotAllowedInsideALoop => {
881                "`?` not allowed inside a `loop`.".into()
882            }
883            SemanticDiagnosticKind::ConstGenericParamNotSupported => {
884                "Const generic args are not allowed in this context.".into()
885            }
886            SemanticDiagnosticKind::NegativeImplsNotEnabled => {
887                "Negative impls are not enabled in the current crate.".into()
888            }
889            SemanticDiagnosticKind::NegativeImplsOnlyOnImpls => {
890                "Negative impls supported only in impl definitions.".into()
891            }
892            SemanticDiagnosticKind::ImplicitPrecedenceAttrForExternFunctionNotAllowed => {
893                "`implicit_precedence` attribute is not allowed for extern functions.".into()
894            }
895            SemanticDiagnosticKind::RedundantImplicitPrecedenceAttribute => {
896                "Redundant `implicit_precedence` attribute.".into()
897            }
898            SemanticDiagnosticKind::UnsupportedImplicitPrecedenceArguments => {
899                "Unsupported `implicit_precedence` arguments.".into()
900            }
901            SemanticDiagnosticKind::UnsupportedFeatureAttrArguments => {
902                "`feature` attribute argument should be a single string.".into()
903            }
904            SemanticDiagnosticKind::UnsupportedAllowAttrArguments => {
905                // TODO(orizi): Add information about the allowed arguments.
906                "`allow` attribute argument not supported.".into()
907            }
908            SemanticDiagnosticKind::UnsupportedPubArgument => "Unsupported `pub` argument.".into(),
909            SemanticDiagnosticKind::UnknownStatementAttribute => {
910                "Unknown statement attribute.".into()
911            }
912            SemanticDiagnosticKind::InlineMacroNotFound(macro_name) => {
913                format!("Inline macro `{}` not found.", macro_name.long(db))
914            }
915            SemanticDiagnosticKind::InlineMacroFailed(macro_name) => {
916                format!("Inline macro `{}` failed.", macro_name.long(db))
917            }
918            SemanticDiagnosticKind::InlineMacroNoMatchingRule(macro_name) => {
919                format!("No matching rule found in inline macro `{}`.", macro_name.long(db))
920            }
921            SemanticDiagnosticKind::MacroCallToNotAMacro(name) => {
922                format!("Call to `{}` which is not a macro.", name.long(db))
923            }
924            SemanticDiagnosticKind::UnknownGenericParam(name) => {
925                format!("Unknown generic parameter `{}`.", name.long(db))
926            }
927            SemanticDiagnosticKind::PositionalGenericAfterNamed => {
928                "Positional generic parameters must come before named generic parameters.".into()
929            }
930            SemanticDiagnosticKind::GenericArgDuplicate(name) => {
931                format!("Generic argument `{}` is specified more than once.", name.long(db))
932            }
933            SemanticDiagnosticKind::TooManyGenericArguments { expected, actual } => {
934                format!("Expected {expected} generic arguments, found {actual}.")
935            }
936            SemanticDiagnosticKind::GenericArgOutOfOrder(name) => {
937                format!("Generic argument `{}` is out of order.", name.long(db))
938            }
939            SemanticDiagnosticKind::ArgPassedToNegativeImpl => {
940                "Only `_` is valid as a negative impl argument.".into()
941            }
942            SemanticDiagnosticKind::CouponForExternFunctionNotAllowed => {
943                "Coupon cannot be used with extern functions.".into()
944            }
945            SemanticDiagnosticKind::CouponArgumentNoModifiers => {
946                "The __coupon__ argument cannot have modifiers.".into()
947            }
948            SemanticDiagnosticKind::CouponsDisabled => {
949                "Coupons are disabled in the current crate.\nYou can enable them by enabling the \
950                 coupons experimental feature in the crate config."
951                    .into()
952            }
953            SemanticDiagnosticKind::StructBaseStructExpressionNotLast => {
954                "The base struct must always be the last argument.".into()
955            }
956            SemanticDiagnosticKind::StructBaseStructExpressionNoEffect => {
957                "Base struct has no effect, all the fields in the struct have already been \
958                 specified."
959                    .into()
960            }
961            SemanticDiagnosticKind::FixedSizeArrayTypeNonSingleType => {
962                "Fixed size array type must have exactly one type.".into()
963            }
964            SemanticDiagnosticKind::FixedSizeArrayTypeEmptySize => {
965                "Fixed size array type must have a size clause.".into()
966            }
967            SemanticDiagnosticKind::FixedSizeArrayNonNumericSize => {
968                "Fixed size array type must have a positive integer size.".into()
969            }
970            SemanticDiagnosticKind::FixedSizeArrayNonSingleValue => {
971                "Fixed size array with defined size must have exactly one value.".into()
972            }
973            SemanticDiagnosticKind::FixedSizeArraySizeTooBig => {
974                "Fixed size array size must be smaller than 2^15.".into()
975            }
976            SemanticDiagnosticKind::SelfNotSupportedInContext => {
977                "`Self` is not supported in this context.".into()
978            }
979            SemanticDiagnosticKind::SelfMustBeFirst => {
980                "`Self` can only be the first segment of a path.".into()
981            }
982            SemanticDiagnosticKind::DollarNotSupportedInContext => {
983                "`$` is not supported in this context.".into()
984            }
985            SemanticDiagnosticKind::UnknownResolverModifier { modifier } => {
986                format!("`${}` is not supported.", modifier.long(db))
987            }
988            SemanticDiagnosticKind::EmptyPathAfterResolverModifier => {
989                "Expected path after modifier.".into()
990            }
991            SemanticDiagnosticKind::CannotCreateInstancesOfPhantomTypes => {
992                "Can not create instances of phantom types.".into()
993            }
994            SemanticDiagnosticKind::NonPhantomTypeContainingPhantomType => {
995                "Non-phantom type containing phantom type.".into()
996            }
997            SemanticDiagnosticKind::DerefCycle { deref_chain } => {
998                format!("Deref impls cycle detected:\n{deref_chain}")
999            }
1000            SemanticDiagnosticKind::NoImplementationOfTrait {
1001                ty,
1002                trait_name,
1003                inference_errors,
1004            } => {
1005                if inference_errors.is_empty() {
1006                    format!(
1007                        "Implementation of trait `{}` not found on type `{}`. Did you import the \
1008                         correct trait and impl?",
1009                        trait_name.long(db),
1010                        ty.format(db)
1011                    )
1012                } else {
1013                    format!(
1014                        "Could not find implementation of trait `{}` on type `{}`.\n{}",
1015                        trait_name.long(db),
1016                        ty.format(db),
1017                        inference_errors.format(db)
1018                    )
1019                }
1020            }
1021            SemanticDiagnosticKind::CallExpressionRequiresFunction { ty, inference_errors } => {
1022                if inference_errors.is_empty() {
1023                    format!("Call expression requires a function, found `{}`.", ty.format(db))
1024                } else {
1025                    format!(
1026                        "Call expression requires a function, found `{}`.\n{}",
1027                        ty.format(db),
1028                        inference_errors.format(db)
1029                    )
1030                }
1031            }
1032            SemanticDiagnosticKind::CompilerTraitReImplementation { trait_id } => {
1033                format!(
1034                    "Trait `{}` should not be implemented outside of the corelib.",
1035                    trait_id.full_path(db)
1036                )
1037            }
1038            SemanticDiagnosticKind::ClosureInGlobalScope => {
1039                "Closures are not allowed in this context.".into()
1040            }
1041            SemanticDiagnosticKind::MaybeMissingColonColon => "Are you missing a `::`?.".into(),
1042            SemanticDiagnosticKind::CallingShadowedFunction { shadowed_function_name } => {
1043                format!(
1044                    "Function `{}` is shadowed by a local variable.",
1045                    shadowed_function_name.long(db)
1046                )
1047            }
1048            SemanticDiagnosticKind::RefClosureArgument => {
1049                "Arguments to closure functions cannot be references".into()
1050            }
1051            SemanticDiagnosticKind::RefClosureParam => {
1052                "Closure parameters cannot be references".into()
1053            }
1054            SemanticDiagnosticKind::MustBeNextToTypeOrTrait { trait_id } => {
1055                format!(
1056                    "'{}' implementation must be defined in the same module as either the type \
1057                     being dereferenced or the trait itself",
1058                    trait_id.name(db).long(db)
1059                )
1060            }
1061            SemanticDiagnosticKind::MutableCapturedVariable => {
1062                "Capture of mutable variables in a closure is not supported".into()
1063            }
1064            SemanticDiagnosticKind::NonTraitTypeConstrained { identifier, concrete_trait_id } => {
1065                format!(
1066                    "associated type `{}` not found for `{}`",
1067                    identifier.long(db),
1068                    concrete_trait_id.full_path(db)
1069                )
1070            }
1071            SemanticDiagnosticKind::DuplicateTypeConstraint {
1072                concrete_trait_type_id: trait_type_id,
1073            } => {
1074                format!(
1075                    "the value of the associated type `{}` in trait `{}` is already specified",
1076                    trait_type_id.trait_type(db).name(db).long(db),
1077                    trait_type_id.concrete_trait(db).full_path(db)
1078                )
1079            }
1080            SemanticDiagnosticKind::TypeConstraintsSyntaxNotEnabled => {
1081                "Type constraints syntax is not enabled in the current crate.".into()
1082            }
1083            SemanticDiagnosticKind::PatternMissingArgs(path) => {
1084                format!(
1085                    "Pattern missing subpattern for the payload of variant. Consider using `{}(_)`",
1086                    path.segments(db)
1087                        .elements(db)
1088                        .map(|seg| seg.identifier(db).long(db))
1089                        .join("::")
1090                )
1091            }
1092            SemanticDiagnosticKind::UndefinedMacroPlaceholder(name) => {
1093                format!("Undefined macro placeholder: '{}'.", name.long(db))
1094            }
1095            SemanticDiagnosticKind::UserDefinedInlineMacrosDisabled => {
1096                "User defined inline macros are disabled in the current crate.".into()
1097            }
1098            SemanticDiagnosticKind::NonNeverLetElseType => concat!(
1099                "`else` clause of `let...else` must exit the scope. ",
1100                "Consider using `return`, `continue`, ..."
1101            )
1102            .into(),
1103        }
1104    }
1105    fn location(&self, db: &'db dyn Database) -> DiagnosticLocation<'db> {
1106        if let SemanticDiagnosticKind::MacroGeneratedCodeParserDiagnostic(parser_diagnostic) =
1107            &self.kind
1108        {
1109            return DiagnosticLocation {
1110                file_id: parser_diagnostic.file_id,
1111                span: parser_diagnostic.span,
1112            };
1113        };
1114
1115        let mut location = self.stable_location.diagnostic_location(db);
1116        if self.after {
1117            location = location.after();
1118        }
1119        location
1120    }
1121
1122    fn severity(&self) -> Severity {
1123        match &self.kind {
1124            SemanticDiagnosticKind::UnusedVariable
1125            | SemanticDiagnosticKind::UnhandledMustUseType { .. }
1126            | SemanticDiagnosticKind::UnhandledMustUseFunction
1127            | SemanticDiagnosticKind::TraitInTraitMustBeExplicit
1128            | SemanticDiagnosticKind::ImplInImplMustBeExplicit
1129            | SemanticDiagnosticKind::TraitItemForbiddenInTheTrait
1130            | SemanticDiagnosticKind::TraitItemForbiddenInItsImpl
1131            | SemanticDiagnosticKind::ImplItemForbiddenInTheImpl
1132            | SemanticDiagnosticKind::UnstableFeature { .. }
1133            | SemanticDiagnosticKind::DeprecatedFeature { .. }
1134            | SemanticDiagnosticKind::UnusedImport { .. }
1135            | SemanticDiagnosticKind::CallingShadowedFunction { .. }
1136            | SemanticDiagnosticKind::UnusedConstant
1137            | SemanticDiagnosticKind::UnusedUse
1138            | SemanticDiagnosticKind::PatternMissingArgs(_)
1139            | SemanticDiagnosticKind::UnsupportedAllowAttrArguments => Severity::Warning,
1140            SemanticDiagnosticKind::PluginDiagnostic(diag) => diag.severity,
1141            _ => Severity::Error,
1142        }
1143    }
1144
1145    fn notes(&self, _db: &dyn Database) -> &[DiagnosticNote<'_>] {
1146        if let SemanticDiagnosticKind::InnerFailedConstantCalculation(_, notes) = &self.kind {
1147            notes
1148        } else {
1149            &[]
1150        }
1151    }
1152
1153    fn error_code(&self) -> Option<ErrorCode> {
1154        self.kind.error_code()
1155    }
1156
1157    fn is_same_kind(&self, other: &Self) -> bool {
1158        other.kind == self.kind
1159    }
1160}
1161
1162#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
1163pub enum SemanticDiagnosticKind<'db> {
1164    ModuleFileNotFound(String),
1165    Unsupported,
1166    UnknownLiteral,
1167    UnknownBinaryOperator,
1168    UnknownTrait,
1169    UnknownImpl,
1170    UnexpectedElement {
1171        expected: Vec<ElementKind>,
1172        actual: ElementKind,
1173    },
1174    UnknownType,
1175    UnknownEnum,
1176    LiteralError(LiteralError<'db>),
1177    NotAVariant,
1178    NotAStruct,
1179    NotAType,
1180    NotATrait,
1181    NotAnImpl,
1182    ImplItemNotInTrait {
1183        impl_def_id: ImplDefId<'db>,
1184        impl_item_name: SmolStrId<'db>,
1185        trait_id: TraitId<'db>,
1186        item_kind: String,
1187    },
1188    ImplicitImplNotInferred {
1189        trait_impl_id: TraitImplId<'db>,
1190        concrete_trait_id: ConcreteTraitId<'db>,
1191    },
1192    GenericsNotSupportedInItem {
1193        scope: String,
1194        item_kind: String,
1195    },
1196    UnexpectedGenericArgs,
1197    UnknownMember,
1198    CannotCreateInstancesOfPhantomTypes,
1199    NonPhantomTypeContainingPhantomType,
1200    MemberSpecifiedMoreThanOnce,
1201    StructBaseStructExpressionNotLast,
1202    StructBaseStructExpressionNoEffect,
1203    ConstCycle,
1204    UseCycle,
1205    TypeAliasCycle,
1206    ImplAliasCycle,
1207    ImplRequirementCycle,
1208    MissingMember(SmolStrId<'db>),
1209    WrongNumberOfParameters {
1210        impl_def_id: ImplDefId<'db>,
1211        impl_function_id: ImplFunctionId<'db>,
1212        trait_id: TraitId<'db>,
1213        expected: usize,
1214        actual: usize,
1215    },
1216    WrongNumberOfArguments {
1217        expected: usize,
1218        actual: usize,
1219    },
1220    WrongParameterType {
1221        impl_def_id: ImplDefId<'db>,
1222        impl_function_id: ImplFunctionId<'db>,
1223        trait_id: TraitId<'db>,
1224        expected_ty: semantic::TypeId<'db>,
1225        actual_ty: semantic::TypeId<'db>,
1226    },
1227    VariantCtorNotImmutable,
1228    TraitParamMutable {
1229        trait_id: TraitId<'db>,
1230        function_id: TraitFunctionId<'db>,
1231    },
1232    ParameterShouldBeReference {
1233        impl_def_id: ImplDefId<'db>,
1234        impl_function_id: ImplFunctionId<'db>,
1235        trait_id: TraitId<'db>,
1236    },
1237    ParameterShouldNotBeReference {
1238        impl_def_id: ImplDefId<'db>,
1239        impl_function_id: ImplFunctionId<'db>,
1240        trait_id: TraitId<'db>,
1241    },
1242    WrongParameterName {
1243        impl_def_id: ImplDefId<'db>,
1244        impl_function_id: ImplFunctionId<'db>,
1245        trait_id: TraitId<'db>,
1246        expected_name: SmolStrId<'db>,
1247    },
1248    WrongGenericParamTraitForImplFunction {
1249        impl_def_id: ImplDefId<'db>,
1250        impl_function_id: ImplFunctionId<'db>,
1251        trait_id: TraitId<'db>,
1252        expected_trait: ConcreteTraitId<'db>,
1253        actual_trait: ConcreteTraitId<'db>,
1254    },
1255    WrongGenericParamKindForImplFunction {
1256        impl_def_id: ImplDefId<'db>,
1257        impl_function_id: ImplFunctionId<'db>,
1258        trait_id: TraitId<'db>,
1259        expected_kind: GenericKind,
1260        actual_kind: GenericKind,
1261    },
1262    WrongType {
1263        expected_ty: semantic::TypeId<'db>,
1264        actual_ty: semantic::TypeId<'db>,
1265    },
1266    InconsistentBinding,
1267    WrongArgumentType {
1268        expected_ty: semantic::TypeId<'db>,
1269        actual_ty: semantic::TypeId<'db>,
1270    },
1271    WrongReturnType {
1272        expected_ty: semantic::TypeId<'db>,
1273        actual_ty: semantic::TypeId<'db>,
1274    },
1275    WrongExprType {
1276        expected_ty: semantic::TypeId<'db>,
1277        actual_ty: semantic::TypeId<'db>,
1278    },
1279    WrongNumberOfGenericParamsForImplFunction {
1280        expected: usize,
1281        actual: usize,
1282    },
1283    WrongReturnTypeForImpl {
1284        impl_def_id: ImplDefId<'db>,
1285        impl_function_id: ImplFunctionId<'db>,
1286        trait_id: TraitId<'db>,
1287        expected_ty: semantic::TypeId<'db>,
1288        actual_ty: semantic::TypeId<'db>,
1289    },
1290    AmbiguousTrait {
1291        trait_function_id0: TraitFunctionId<'db>,
1292        trait_function_id1: TraitFunctionId<'db>,
1293    },
1294    VariableNotFound(SmolStrId<'db>),
1295    MissingVariableInPattern,
1296    StructMemberRedefinition {
1297        struct_id: StructId<'db>,
1298        member_name: SmolStrId<'db>,
1299    },
1300    EnumVariantRedefinition {
1301        enum_id: EnumId<'db>,
1302        variant_name: SmolStrId<'db>,
1303    },
1304    InfiniteSizeType(semantic::TypeId<'db>),
1305    ArrayOfZeroSizedElements(semantic::TypeId<'db>),
1306    ParamNameRedefinition {
1307        function_title_id: Option<FunctionTitleId<'db>>,
1308        param_name: SmolStrId<'db>,
1309    },
1310    ConditionNotBool(semantic::TypeId<'db>),
1311    IncompatibleArms {
1312        multi_arm_expr_kind: MultiArmExprKind,
1313        pending_ty: semantic::TypeId<'db>,
1314        different_ty: semantic::TypeId<'db>,
1315    },
1316    TypeHasNoMembers {
1317        ty: semantic::TypeId<'db>,
1318        member_name: SmolStrId<'db>,
1319    },
1320    CannotCallMethod {
1321        ty: semantic::TypeId<'db>,
1322        method_name: SmolStrId<'db>,
1323        inference_errors: TraitInferenceErrors<'db>,
1324        relevant_traits: Vec<String>,
1325    },
1326    NoSuchStructMember {
1327        struct_id: StructId<'db>,
1328        member_name: SmolStrId<'db>,
1329    },
1330    NoSuchTypeMember {
1331        ty: semantic::TypeId<'db>,
1332        member_name: SmolStrId<'db>,
1333    },
1334    MemberNotVisible(SmolStrId<'db>),
1335    NoSuchVariant {
1336        enum_id: EnumId<'db>,
1337        variant_name: SmolStrId<'db>,
1338    },
1339    ReturnTypeNotErrorPropagateType,
1340    IncompatibleErrorPropagateType {
1341        return_ty: semantic::TypeId<'db>,
1342        err_ty: semantic::TypeId<'db>,
1343    },
1344    ErrorPropagateOnNonErrorType(semantic::TypeId<'db>),
1345    UnhandledMustUseType(semantic::TypeId<'db>),
1346    UnstableFeature {
1347        feature_name: SmolStrId<'db>,
1348        note: Option<SmolStrId<'db>>,
1349    },
1350    DeprecatedFeature {
1351        feature_name: SmolStrId<'db>,
1352        note: Option<SmolStrId<'db>>,
1353    },
1354    InternalFeature {
1355        feature_name: SmolStrId<'db>,
1356        note: Option<SmolStrId<'db>>,
1357    },
1358    FeatureMarkerDiagnostic(FeatureMarkerDiagnostic),
1359    UnhandledMustUseFunction,
1360    UnusedVariable,
1361    UnusedConstant,
1362    UnusedUse,
1363    MultipleConstantDefinition(SmolStrId<'db>),
1364    MultipleDefinitionforBinding(SmolStrId<'db>),
1365    MultipleGenericItemDefinition(SmolStrId<'db>),
1366    UnsupportedUseItemInStatement,
1367    ConstGenericParamNotSupported,
1368    NegativeImplsNotEnabled,
1369    NegativeImplsOnlyOnImpls,
1370    RefArgNotAVariable,
1371    RefArgNotMutable,
1372    RefArgNotExplicit,
1373    ImmutableArgWithModifiers,
1374    AssignmentToImmutableVar,
1375    InvalidLhsForAssignment,
1376    InvalidMemberExpression,
1377    InvalidPath,
1378    PathNotFound(NotFoundItemType),
1379    AmbiguousPath(Vec<ModuleItemId<'db>>),
1380    UseSelfNonMulti,
1381    UseSelfEmptyPath,
1382    UseStarEmptyPath,
1383    GlobalUsesNotSupportedInEdition(Edition),
1384    TraitInTraitMustBeExplicit,
1385    ImplInImplMustBeExplicit,
1386    TraitItemForbiddenInTheTrait,
1387    TraitItemForbiddenInItsImpl,
1388    ImplItemForbiddenInTheImpl,
1389    SuperUsedInRootModule,
1390    SuperUsedInMacroCallTopLevel,
1391    ItemNotVisible(ModuleItemId<'db>, Vec<ModuleId<'db>>),
1392    UnusedImport(UseId<'db>),
1393    RedundantModifier {
1394        current_modifier: SmolStrId<'db>,
1395        previous_modifier: SmolStrId<'db>,
1396    },
1397    ReferenceLocalVariable,
1398    UnexpectedEnumPattern(semantic::TypeId<'db>),
1399    UnexpectedStructPattern(semantic::TypeId<'db>),
1400    UnexpectedTuplePattern(semantic::TypeId<'db>),
1401    UnexpectedFixedSizeArrayPattern(semantic::TypeId<'db>),
1402    WrongNumberOfTupleElements {
1403        expected: usize,
1404        actual: usize,
1405    },
1406    WrongNumberOfFixedSizeArrayElements {
1407        expected: usize,
1408        actual: usize,
1409    },
1410    WrongEnum {
1411        expected_enum: EnumId<'db>,
1412        actual_enum: EnumId<'db>,
1413    },
1414    InvalidCopyTraitImpl(InferenceError<'db>),
1415    InvalidDropTraitImpl(InferenceError<'db>),
1416    InvalidImplItem(SmolStrId<'db>),
1417    MissingItemsInImpl(Vec<SmolStrId<'db>>),
1418    PassPanicAsNopanic {
1419        impl_function_id: ImplFunctionId<'db>,
1420        trait_id: TraitId<'db>,
1421    },
1422    PassConstAsNonConst {
1423        impl_function_id: ImplFunctionId<'db>,
1424        trait_id: TraitId<'db>,
1425    },
1426    PanicableFromNonPanicable,
1427    PanicableExternFunction,
1428    MacroGeneratedCodeParserDiagnostic(ParserDiagnostic<'db>),
1429    PluginDiagnostic(PluginDiagnostic<'db>),
1430    NameDefinedMultipleTimes(SmolStrId<'db>),
1431    NonPrivateUseStar,
1432    SelfGlobalUse,
1433    NamedArgumentsAreNotSupported,
1434    ArgPassedToNegativeImpl,
1435    UnnamedArgumentFollowsNamed,
1436    NamedArgumentMismatch {
1437        expected: SmolStrId<'db>,
1438        found: SmolStrId<'db>,
1439    },
1440    UnsupportedOutsideOfFunction(UnsupportedOutsideOfFunctionFeatureName),
1441    UnsupportedConstant,
1442    FailedConstantCalculation,
1443    ConstantCalculationDepthExceeded,
1444    InnerFailedConstantCalculation(Box<SemanticDiagnostic<'db>>, Vec<DiagnosticNote<'db>>),
1445    DivisionByZero,
1446    ExternTypeWithImplGenericsNotSupported,
1447    MissingSemicolon,
1448    TraitMismatch {
1449        expected_trt: semantic::ConcreteTraitId<'db>,
1450        actual_trt: semantic::ConcreteTraitId<'db>,
1451    },
1452    DerefNonRef {
1453        ty: semantic::TypeId<'db>,
1454    },
1455    InternalInferenceError(InferenceError<'db>),
1456    NoImplementationOfIndexOperator {
1457        ty: semantic::TypeId<'db>,
1458        inference_errors: TraitInferenceErrors<'db>,
1459    },
1460    NoImplementationOfTrait {
1461        ty: semantic::TypeId<'db>,
1462        trait_name: SmolStrId<'db>,
1463        inference_errors: TraitInferenceErrors<'db>,
1464    },
1465    CallExpressionRequiresFunction {
1466        ty: semantic::TypeId<'db>,
1467        inference_errors: TraitInferenceErrors<'db>,
1468    },
1469    MultipleImplementationOfIndexOperator(semantic::TypeId<'db>),
1470
1471    UnsupportedInlineArguments,
1472    RedundantInlineAttribute,
1473    InlineAttrForExternFunctionNotAllowed,
1474    InlineAlwaysWithImplGenericArgNotAllowed,
1475    TailExpressionNotAllowedInLoop,
1476    ContinueOnlyAllowedInsideALoop,
1477    BreakOnlyAllowedInsideALoop,
1478    BreakWithValueOnlyAllowedInsideALoop,
1479    ErrorPropagateNotAllowedInsideALoop,
1480    ImplicitPrecedenceAttrForExternFunctionNotAllowed,
1481    RedundantImplicitPrecedenceAttribute,
1482    UnsupportedImplicitPrecedenceArguments,
1483    UnsupportedFeatureAttrArguments,
1484    UnsupportedAllowAttrArguments,
1485    UnsupportedPubArgument,
1486    UnknownStatementAttribute,
1487    InlineMacroNotFound(SmolStrId<'db>),
1488    InlineMacroFailed(SmolStrId<'db>),
1489    InlineMacroNoMatchingRule(SmolStrId<'db>),
1490    MacroCallToNotAMacro(SmolStrId<'db>),
1491    UnknownGenericParam(SmolStrId<'db>),
1492    PositionalGenericAfterNamed,
1493    GenericArgDuplicate(SmolStrId<'db>),
1494    TooManyGenericArguments {
1495        expected: usize,
1496        actual: usize,
1497    },
1498    GenericArgOutOfOrder(SmolStrId<'db>),
1499    CouponForExternFunctionNotAllowed,
1500    CouponArgumentNoModifiers,
1501    /// Coupons are disabled in the current crate.
1502    CouponsDisabled,
1503    FixedSizeArrayTypeNonSingleType,
1504    FixedSizeArrayTypeEmptySize,
1505    FixedSizeArrayNonNumericSize,
1506    FixedSizeArrayNonSingleValue,
1507    FixedSizeArraySizeTooBig,
1508    SelfNotSupportedInContext,
1509    SelfMustBeFirst,
1510    DollarNotSupportedInContext,
1511    UnknownResolverModifier {
1512        modifier: SmolStrId<'db>,
1513    },
1514    EmptyPathAfterResolverModifier,
1515    DerefCycle {
1516        deref_chain: String,
1517    },
1518    CompilerTraitReImplementation {
1519        trait_id: TraitId<'db>,
1520    },
1521    ClosureInGlobalScope,
1522    MaybeMissingColonColon,
1523    CallingShadowedFunction {
1524        shadowed_function_name: SmolStrId<'db>,
1525    },
1526    RefClosureArgument,
1527    RefClosureParam,
1528    MustBeNextToTypeOrTrait {
1529        trait_id: TraitId<'db>,
1530    },
1531    MutableCapturedVariable,
1532    NonTraitTypeConstrained {
1533        identifier: SmolStrId<'db>,
1534        concrete_trait_id: ConcreteTraitId<'db>,
1535    },
1536    DuplicateTypeConstraint {
1537        concrete_trait_type_id: ConcreteTraitTypeId<'db>,
1538    },
1539    TypeConstraintsSyntaxNotEnabled,
1540    PatternMissingArgs(ast::ExprPath<'db>),
1541    UndefinedMacroPlaceholder(SmolStrId<'db>),
1542    UserDefinedInlineMacrosDisabled,
1543    NonNeverLetElseType,
1544}
1545
1546/// The kind of an expression with multiple possible return types.
1547#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1548pub enum MultiArmExprKind {
1549    If,
1550    Match,
1551    Loop,
1552}
1553
1554impl<'db> SemanticDiagnosticKind<'db> {
1555    pub fn error_code(&self) -> Option<ErrorCode> {
1556        Some(match &self {
1557            Self::UnusedVariable => error_code!(E0001),
1558            Self::CannotCallMethod { .. } => {
1559                error_code!(E0002)
1560            }
1561            Self::MissingMember(_) => error_code!(E0003),
1562            Self::MissingItemsInImpl(_) => error_code!(E0004),
1563            Self::ModuleFileNotFound(_) => error_code!(E0005),
1564            Self::PathNotFound(_) => error_code!(E0006),
1565            Self::NoSuchTypeMember { .. } => error_code!(E0007),
1566            _ => return None,
1567        })
1568    }
1569}
1570
1571// TODO(Gil): It seems to have the same functionality as ElementKind, maybe we can merge them.
1572#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1573pub enum NotFoundItemType {
1574    Identifier,
1575    Function,
1576    Type,
1577    Trait,
1578    Impl,
1579    Macro,
1580}
1581
1582#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1583pub enum UnsupportedOutsideOfFunctionFeatureName {
1584    ReturnStatement,
1585    ErrorPropagate,
1586}
1587
1588#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Update)]
1589pub enum ElementKind {
1590    Constant,
1591    Variable,
1592    Module,
1593    Function,
1594    Type,
1595    Variant,
1596    Trait,
1597    Impl,
1598    Macro,
1599}
1600impl<'db> From<&ResolvedConcreteItem<'db>> for ElementKind {
1601    fn from(val: &ResolvedConcreteItem<'db>) -> Self {
1602        match val {
1603            ResolvedConcreteItem::Constant(_) => ElementKind::Constant,
1604            ResolvedConcreteItem::Module(_) => ElementKind::Module,
1605            ResolvedConcreteItem::Function(_) => ElementKind::Function,
1606            ResolvedConcreteItem::Type(_) => ElementKind::Type,
1607            ResolvedConcreteItem::Variant(_) => ElementKind::Variant,
1608            ResolvedConcreteItem::Trait(_) | ResolvedConcreteItem::SelfTrait(_) => {
1609                ElementKind::Trait
1610            }
1611            ResolvedConcreteItem::Impl(_) => ElementKind::Impl,
1612            ResolvedConcreteItem::Macro(_) => ElementKind::Macro,
1613        }
1614    }
1615}
1616impl<'db> From<&ResolvedGenericItem<'db>> for ElementKind {
1617    fn from(val: &ResolvedGenericItem<'db>) -> Self {
1618        match val {
1619            ResolvedGenericItem::GenericConstant(_)
1620            | ResolvedGenericItem::TraitItem(TraitItemId::Constant(_)) => ElementKind::Constant,
1621            ResolvedGenericItem::Module(_) => ElementKind::Module,
1622            ResolvedGenericItem::GenericFunction(_)
1623            | ResolvedGenericItem::TraitItem(TraitItemId::Function(_)) => ElementKind::Function,
1624            ResolvedGenericItem::GenericType(_)
1625            | ResolvedGenericItem::GenericTypeAlias(_)
1626            | ResolvedGenericItem::TraitItem(TraitItemId::Type(_)) => ElementKind::Type,
1627            ResolvedGenericItem::Variant(_) => ElementKind::Variant,
1628            ResolvedGenericItem::Trait(_) => ElementKind::Trait,
1629            ResolvedGenericItem::Impl(_)
1630            | ResolvedGenericItem::GenericImplAlias(_)
1631            | ResolvedGenericItem::TraitItem(TraitItemId::Impl(_)) => ElementKind::Impl,
1632            ResolvedGenericItem::Variable(_) => ElementKind::Variable,
1633            ResolvedGenericItem::Macro(_) => ElementKind::Macro,
1634        }
1635    }
1636}
1637impl Display for ElementKind {
1638    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1639        let res = match self {
1640            ElementKind::Constant => "constant",
1641            ElementKind::Variable => "variable",
1642            ElementKind::Module => "module",
1643            ElementKind::Function => "function",
1644            ElementKind::Type => "type",
1645            ElementKind::Variant => "variant",
1646            ElementKind::Trait => "trait",
1647            ElementKind::Impl => "impl",
1648            ElementKind::Macro => "macro",
1649        };
1650        write!(f, "{res}")
1651    }
1652}
1653
1654/// A list of trait functions and the inference errors that occurred while trying to infer them.
1655#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
1656pub struct TraitInferenceErrors<'db> {
1657    pub traits_and_errors: Vec<(TraitFunctionId<'db>, InferenceError<'db>)>,
1658}
1659impl<'db> TraitInferenceErrors<'db> {
1660    /// Is the error list empty.
1661    pub fn is_empty(&self) -> bool {
1662        self.traits_and_errors.is_empty()
1663    }
1664    /// Format the list of errors.
1665    fn format(&self, db: &dyn Database) -> String {
1666        self.traits_and_errors
1667            .iter()
1668            .map(|(trait_function_id, inference_error)| {
1669                format!(
1670                    "Candidate `{}` inference failed with: {}",
1671                    trait_function_id.full_path(db),
1672                    inference_error.format(db)
1673                )
1674            })
1675            .join("\n")
1676    }
1677}