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