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