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
1059            | SemanticDiagnosticKind::UnsupportedAllowAttrArguments => Severity::Warning,
1060            SemanticDiagnosticKind::PluginDiagnostic(diag) => diag.severity,
1061            _ => Severity::Error,
1062        }
1063    }
1064
1065    fn notes(&self, _db: &Self::DbType) -> &[DiagnosticNote] {
1066        if let SemanticDiagnosticKind::InnerFailedConstantCalculation(_, notes) = &self.kind {
1067            notes
1068        } else {
1069            &[]
1070        }
1071    }
1072
1073    fn error_code(&self) -> Option<ErrorCode> {
1074        self.kind.error_code()
1075    }
1076
1077    fn is_same_kind(&self, other: &Self) -> bool {
1078        other.kind == self.kind
1079    }
1080}
1081
1082#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1083pub enum SemanticDiagnosticKind {
1084    ModuleFileNotFound(String),
1085    Unsupported,
1086    UnknownLiteral,
1087    UnknownBinaryOperator,
1088    UnknownTrait,
1089    UnknownImpl,
1090    UnexpectedElement {
1091        expected: Vec<ElementKind>,
1092        actual: ElementKind,
1093    },
1094    UnknownType,
1095    UnknownEnum,
1096    LiteralError(LiteralError),
1097    NotAVariant,
1098    NotAStruct,
1099    NotAType,
1100    NotATrait,
1101    NotAnImpl,
1102    ImplItemNotInTrait {
1103        impl_def_id: ImplDefId,
1104        impl_item_name: SmolStr,
1105        trait_id: TraitId,
1106        item_kind: String,
1107    },
1108    ImplicitImplNotInferred {
1109        trait_impl_id: TraitImplId,
1110        concrete_trait_id: ConcreteTraitId,
1111    },
1112    GenericsNotSupportedInItem {
1113        scope: String,
1114        item_kind: String,
1115    },
1116    UnexpectedGenericArgs,
1117    UnknownMember,
1118    CannotCreateInstancesOfPhantomTypes,
1119    NonPhantomTypeContainingPhantomType,
1120    MemberSpecifiedMoreThanOnce,
1121    StructBaseStructExpressionNotLast,
1122    StructBaseStructExpressionNoEffect,
1123    ConstCycle,
1124    UseCycle,
1125    TypeAliasCycle,
1126    ImplAliasCycle,
1127    ImplRequirementCycle,
1128    MissingMember(SmolStr),
1129    WrongNumberOfParameters {
1130        impl_def_id: ImplDefId,
1131        impl_function_id: ImplFunctionId,
1132        trait_id: TraitId,
1133        expected: usize,
1134        actual: usize,
1135    },
1136    WrongNumberOfArguments {
1137        expected: usize,
1138        actual: usize,
1139    },
1140    WrongParameterType {
1141        impl_def_id: ImplDefId,
1142        impl_function_id: ImplFunctionId,
1143        trait_id: TraitId,
1144        expected_ty: semantic::TypeId,
1145        actual_ty: semantic::TypeId,
1146    },
1147    VariantCtorNotImmutable,
1148    TraitParamMutable {
1149        trait_id: TraitId,
1150        function_id: TraitFunctionId,
1151    },
1152    ParameterShouldBeReference {
1153        impl_def_id: ImplDefId,
1154        impl_function_id: ImplFunctionId,
1155        trait_id: TraitId,
1156    },
1157    ParameterShouldNotBeReference {
1158        impl_def_id: ImplDefId,
1159        impl_function_id: ImplFunctionId,
1160        trait_id: TraitId,
1161    },
1162    WrongParameterName {
1163        impl_def_id: ImplDefId,
1164        impl_function_id: ImplFunctionId,
1165        trait_id: TraitId,
1166        expected_name: SmolStr,
1167    },
1168    WrongGenericParamTraitForImplFunction {
1169        impl_def_id: ImplDefId,
1170        impl_function_id: ImplFunctionId,
1171        trait_id: TraitId,
1172        expected_trait: ConcreteTraitId,
1173        actual_trait: ConcreteTraitId,
1174    },
1175    WrongGenericParamKindForImplFunction {
1176        impl_def_id: ImplDefId,
1177        impl_function_id: ImplFunctionId,
1178        trait_id: TraitId,
1179        expected_kind: GenericKind,
1180        actual_kind: GenericKind,
1181    },
1182    WrongType {
1183        expected_ty: semantic::TypeId,
1184        actual_ty: semantic::TypeId,
1185    },
1186    InconsistentBinding,
1187    WrongArgumentType {
1188        expected_ty: semantic::TypeId,
1189        actual_ty: semantic::TypeId,
1190    },
1191    WrongReturnType {
1192        expected_ty: semantic::TypeId,
1193        actual_ty: semantic::TypeId,
1194    },
1195    WrongExprType {
1196        expected_ty: semantic::TypeId,
1197        actual_ty: semantic::TypeId,
1198    },
1199    WrongNumberOfGenericParamsForImplFunction {
1200        expected: usize,
1201        actual: usize,
1202    },
1203    WrongReturnTypeForImpl {
1204        impl_def_id: ImplDefId,
1205        impl_function_id: ImplFunctionId,
1206        trait_id: TraitId,
1207        expected_ty: semantic::TypeId,
1208        actual_ty: semantic::TypeId,
1209    },
1210    AmbiguousTrait {
1211        trait_function_id0: TraitFunctionId,
1212        trait_function_id1: TraitFunctionId,
1213    },
1214    VariableNotFound(SmolStr),
1215    MissingVariableInPattern,
1216    StructMemberRedefinition {
1217        struct_id: StructId,
1218        member_name: SmolStr,
1219    },
1220    EnumVariantRedefinition {
1221        enum_id: EnumId,
1222        variant_name: SmolStr,
1223    },
1224    InfiniteSizeType(semantic::TypeId),
1225    ArrayOfZeroSizedElements(semantic::TypeId),
1226    ParamNameRedefinition {
1227        function_title_id: Option<FunctionTitleId>,
1228        param_name: SmolStr,
1229    },
1230    ConditionNotBool(semantic::TypeId),
1231    IncompatibleArms {
1232        multi_arm_expr_kind: MultiArmExprKind,
1233        pending_ty: semantic::TypeId,
1234        different_ty: semantic::TypeId,
1235    },
1236    LogicalOperatorNotAllowedInIfLet,
1237    LogicalOperatorNotAllowedInWhileLet,
1238    TypeHasNoMembers {
1239        ty: semantic::TypeId,
1240        member_name: SmolStr,
1241    },
1242    CannotCallMethod {
1243        ty: semantic::TypeId,
1244        method_name: SmolStr,
1245        inference_errors: TraitInferenceErrors,
1246        relevant_traits: Vec<String>,
1247    },
1248    NoSuchStructMember {
1249        struct_id: StructId,
1250        member_name: SmolStr,
1251    },
1252    NoSuchTypeMember {
1253        ty: semantic::TypeId,
1254        member_name: SmolStr,
1255    },
1256    MemberNotVisible(SmolStr),
1257    NoSuchVariant {
1258        enum_id: EnumId,
1259        variant_name: SmolStr,
1260    },
1261    ReturnTypeNotErrorPropagateType,
1262    IncompatibleErrorPropagateType {
1263        return_ty: semantic::TypeId,
1264        err_ty: semantic::TypeId,
1265    },
1266    ErrorPropagateOnNonErrorType(semantic::TypeId),
1267    UnhandledMustUseType(semantic::TypeId),
1268    UnstableFeature {
1269        feature_name: SmolStr,
1270        note: Option<SmolStr>,
1271    },
1272    DeprecatedFeature {
1273        feature_name: SmolStr,
1274        note: Option<SmolStr>,
1275    },
1276    InternalFeature {
1277        feature_name: SmolStr,
1278        note: Option<SmolStr>,
1279    },
1280    FeatureMarkerDiagnostic(FeatureMarkerDiagnostic),
1281    UnhandledMustUseFunction,
1282    UnusedVariable,
1283    UnusedConstant,
1284    UnusedUse,
1285    MultipleConstantDefinition(SmolStr),
1286    MultipleDefinitionforBinding(SmolStr),
1287    MultipleGenericItemDefinition(SmolStr),
1288    UnsupportedUseItemInStatement,
1289    ConstGenericParamNotSupported,
1290    NegativeImplsNotEnabled,
1291    NegativeImplsOnlyOnImpls,
1292    RefArgNotAVariable,
1293    RefArgNotMutable,
1294    RefArgNotExplicit,
1295    ImmutableArgWithModifiers,
1296    AssignmentToImmutableVar,
1297    InvalidLhsForAssignment,
1298    InvalidMemberExpression,
1299    InvalidPath,
1300    PathNotFound(NotFoundItemType),
1301    AmbiguousPath(Vec<ModuleItemId>),
1302    UseStarEmptyPath,
1303    GlobalUsesNotSupportedInEdition(Edition),
1304    TraitInTraitMustBeExplicit,
1305    ImplInImplMustBeExplicit,
1306    TraitItemForbiddenInTheTrait,
1307    TraitItemForbiddenInItsImpl,
1308    ImplItemForbiddenInTheImpl,
1309    SuperUsedInRootModule,
1310    ItemNotVisible(ModuleItemId, Vec<ModuleId>),
1311    UnusedImport(UseId),
1312    RedundantModifier {
1313        current_modifier: SmolStr,
1314        previous_modifier: SmolStr,
1315    },
1316    ReferenceLocalVariable,
1317    UnexpectedEnumPattern(semantic::TypeId),
1318    UnexpectedStructPattern(semantic::TypeId),
1319    UnexpectedTuplePattern(semantic::TypeId),
1320    UnexpectedFixedSizeArrayPattern(semantic::TypeId),
1321    WrongNumberOfTupleElements {
1322        expected: usize,
1323        actual: usize,
1324    },
1325    WrongNumberOfFixedSizeArrayElements {
1326        expected: usize,
1327        actual: usize,
1328    },
1329    WrongEnum {
1330        expected_enum: EnumId,
1331        actual_enum: EnumId,
1332    },
1333    InvalidCopyTraitImpl(InferenceError),
1334    InvalidDropTraitImpl(InferenceError),
1335    InvalidImplItem(SmolStr),
1336    MissingItemsInImpl(Vec<SmolStr>),
1337    PassPanicAsNopanic {
1338        impl_function_id: ImplFunctionId,
1339        trait_id: TraitId,
1340    },
1341    PassConstAsNonConst {
1342        impl_function_id: ImplFunctionId,
1343        trait_id: TraitId,
1344    },
1345    PanicableFromNonPanicable,
1346    PanicableExternFunction,
1347    PluginDiagnostic(PluginDiagnostic),
1348    NameDefinedMultipleTimes(SmolStr),
1349    NonPrivateUseStar,
1350    NamedArgumentsAreNotSupported,
1351    ArgPassedToNegativeImpl,
1352    UnnamedArgumentFollowsNamed,
1353    NamedArgumentMismatch {
1354        expected: SmolStr,
1355        found: SmolStr,
1356    },
1357    UnsupportedOutsideOfFunction(UnsupportedOutsideOfFunctionFeatureName),
1358    UnsupportedConstant,
1359    FailedConstantCalculation,
1360    ConstantCalculationDepthExceeded,
1361    InnerFailedConstantCalculation(Box<SemanticDiagnostic>, Vec<DiagnosticNote>),
1362    DivisionByZero,
1363    ExternTypeWithImplGenericsNotSupported,
1364    MissingSemicolon,
1365    TraitMismatch {
1366        expected_trt: semantic::ConcreteTraitId,
1367        actual_trt: semantic::ConcreteTraitId,
1368    },
1369    DesnapNonSnapshot,
1370    InternalInferenceError(InferenceError),
1371    NoImplementationOfIndexOperator {
1372        ty: semantic::TypeId,
1373        inference_errors: TraitInferenceErrors,
1374    },
1375    NoImplementationOfTrait {
1376        ty: semantic::TypeId,
1377        trait_name: SmolStr,
1378        inference_errors: TraitInferenceErrors,
1379    },
1380    CallExpressionRequiresFunction {
1381        ty: semantic::TypeId,
1382        inference_errors: TraitInferenceErrors,
1383    },
1384    MultipleImplementationOfIndexOperator(semantic::TypeId),
1385
1386    UnsupportedInlineArguments,
1387    RedundantInlineAttribute,
1388    InlineAttrForExternFunctionNotAllowed,
1389    InlineAlwaysWithImplGenericArgNotAllowed,
1390    TailExpressionNotAllowedInLoop,
1391    ContinueOnlyAllowedInsideALoop,
1392    BreakOnlyAllowedInsideALoop,
1393    BreakWithValueOnlyAllowedInsideALoop,
1394    ErrorPropagateNotAllowedInsideALoop,
1395    ImplicitPrecedenceAttrForExternFunctionNotAllowed,
1396    RedundantImplicitPrecedenceAttribute,
1397    UnsupportedImplicitPrecedenceArguments,
1398    UnsupportedFeatureAttrArguments,
1399    UnsupportedAllowAttrArguments,
1400    UnsupportedPubArgument,
1401    UnknownStatementAttribute,
1402    InlineMacroNotFound(SmolStr),
1403    InlineMacroFailed(SmolStr),
1404    UnknownGenericParam(SmolStr),
1405    PositionalGenericAfterNamed,
1406    GenericArgDuplicate(SmolStr),
1407    TooManyGenericArguments {
1408        expected: usize,
1409        actual: usize,
1410    },
1411    GenericArgOutOfOrder(SmolStr),
1412    CouponForExternFunctionNotAllowed,
1413    CouponArgumentNoModifiers,
1414    /// Coupons are disabled in the current crate.
1415    CouponsDisabled,
1416    FixedSizeArrayTypeNonSingleType,
1417    FixedSizeArrayTypeEmptySize,
1418    FixedSizeArrayNonNumericSize,
1419    FixedSizeArrayNonSingleValue,
1420    FixedSizeArraySizeTooBig,
1421    SelfNotSupportedInContext,
1422    SelfMustBeFirst,
1423    DerefCycle {
1424        deref_chain: String,
1425    },
1426    CompilerTraitReImplementation {
1427        trait_id: TraitId,
1428    },
1429    ClosureInGlobalScope,
1430    MaybeMissingColonColon,
1431    CallingShadowedFunction {
1432        shadowed_function_name: SmolStr,
1433    },
1434    RefClosureArgument,
1435    RefClosureParam,
1436    MustBeNextToTypeOrTrait {
1437        trait_id: TraitId,
1438    },
1439    MutableCapturedVariable,
1440    NonTraitTypeConstrained {
1441        identifier: SmolStr,
1442        concrete_trait_id: ConcreteTraitId,
1443    },
1444    DuplicateTypeConstraint {
1445        concrete_trait_type_id: ConcreteTraitTypeId,
1446    },
1447    TypeConstraintsSyntaxNotEnabled,
1448}
1449
1450/// The kind of an expression with multiple possible return types.
1451#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1452pub enum MultiArmExprKind {
1453    If,
1454    Match,
1455    Loop,
1456}
1457
1458impl SemanticDiagnosticKind {
1459    pub fn error_code(&self) -> Option<ErrorCode> {
1460        Some(match &self {
1461            Self::UnusedVariable => error_code!(E0001),
1462            Self::CannotCallMethod { .. } => {
1463                error_code!(E0002)
1464            }
1465            Self::MissingMember(_) => error_code!(E0003),
1466            Self::MissingItemsInImpl(_) => error_code!(E0004),
1467            Self::ModuleFileNotFound(_) => error_code!(E0005),
1468            Self::PathNotFound(_) => error_code!(E0006),
1469            _ => return None,
1470        })
1471    }
1472}
1473
1474#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1475pub enum NotFoundItemType {
1476    Identifier,
1477    Function,
1478    Type,
1479    Trait,
1480    Impl,
1481}
1482
1483#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1484pub enum UnsupportedOutsideOfFunctionFeatureName {
1485    ReturnStatement,
1486    ErrorPropagate,
1487}
1488
1489#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1490pub enum ElementKind {
1491    Constant,
1492    Variable,
1493    Module,
1494    Function,
1495    Type,
1496    Variant,
1497    Trait,
1498    Impl,
1499}
1500impl From<&ResolvedConcreteItem> for ElementKind {
1501    fn from(val: &ResolvedConcreteItem) -> Self {
1502        match val {
1503            ResolvedConcreteItem::Constant(_) => ElementKind::Constant,
1504            ResolvedConcreteItem::Module(_) => ElementKind::Module,
1505            ResolvedConcreteItem::Function(_) => ElementKind::Function,
1506            ResolvedConcreteItem::Type(_) => ElementKind::Type,
1507            ResolvedConcreteItem::Variant(_) => ElementKind::Variant,
1508            ResolvedConcreteItem::Trait(_) | ResolvedConcreteItem::SelfTrait(_) => {
1509                ElementKind::Trait
1510            }
1511            ResolvedConcreteItem::Impl(_) => ElementKind::Impl,
1512        }
1513    }
1514}
1515impl From<&ResolvedGenericItem> for ElementKind {
1516    fn from(val: &ResolvedGenericItem) -> Self {
1517        match val {
1518            ResolvedGenericItem::GenericConstant(_) => ElementKind::Constant,
1519            ResolvedGenericItem::Module(_) => ElementKind::Module,
1520            ResolvedGenericItem::GenericFunction(_) => ElementKind::Function,
1521            ResolvedGenericItem::GenericType(_) | ResolvedGenericItem::GenericTypeAlias(_) => {
1522                ElementKind::Type
1523            }
1524            ResolvedGenericItem::Variant(_) => ElementKind::Variant,
1525            ResolvedGenericItem::Trait(_) => ElementKind::Trait,
1526            ResolvedGenericItem::Impl(_) | ResolvedGenericItem::GenericImplAlias(_) => {
1527                ElementKind::Impl
1528            }
1529            ResolvedGenericItem::Variable(_) => ElementKind::Variable,
1530        }
1531    }
1532}
1533impl Display for ElementKind {
1534    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1535        let res = match self {
1536            ElementKind::Constant => "constant",
1537            ElementKind::Variable => "variable",
1538            ElementKind::Module => "module",
1539            ElementKind::Function => "function",
1540            ElementKind::Type => "type",
1541            ElementKind::Variant => "variant",
1542            ElementKind::Trait => "trait",
1543            ElementKind::Impl => "impl",
1544        };
1545        write!(f, "{res}")
1546    }
1547}
1548
1549/// A list of trait functions and the inference errors that occurred while trying to infer them.
1550#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1551pub struct TraitInferenceErrors {
1552    pub traits_and_errors: Vec<(TraitFunctionId, InferenceError)>,
1553}
1554impl TraitInferenceErrors {
1555    /// Is the error list empty.
1556    pub fn is_empty(&self) -> bool {
1557        self.traits_and_errors.is_empty()
1558    }
1559    /// Format the list of errors.
1560    fn format(&self, db: &(dyn SemanticGroup + 'static)) -> String {
1561        self.traits_and_errors
1562            .iter()
1563            .map(|(trait_function_id, inference_error)| {
1564                format!(
1565                    "Candidate `{}` inference failed with: {}",
1566                    trait_function_id.full_path(db.upcast()),
1567                    inference_error.format(db)
1568                )
1569            })
1570            .join("\n")
1571    }
1572}