2021-05-22 13:53:47 +00:00
|
|
|
//! Re-export diagnostics such that clients of `hir` don't have to depend on
|
|
|
|
//! low-level crates.
|
|
|
|
//!
|
2022-09-04 17:28:04 +00:00
|
|
|
//! This probably isn't the best way to do this -- ideally, diagnostics should
|
2021-05-22 13:53:47 +00:00
|
|
|
//! be expressed in terms of hir types themselves.
|
2024-11-20 21:05:48 +00:00
|
|
|
use cfg::{CfgExpr, CfgOptions};
|
|
|
|
use either::Either;
|
|
|
|
use hir_def::{
|
|
|
|
hir::ExprOrPatId,
|
|
|
|
path::{hir_segment_to_ast_segment, ModPath},
|
|
|
|
type_ref::TypesSourceMap,
|
|
|
|
AssocItemId, DefWithBodyId, SyntheticSyntax,
|
|
|
|
};
|
|
|
|
use hir_expand::{name::Name, HirFileId, InFile};
|
2024-08-28 15:12:16 +00:00
|
|
|
use hir_ty::{
|
2024-12-04 06:05:23 +00:00
|
|
|
db::HirDatabase,
|
|
|
|
diagnostics::{BodyValidationDiagnostic, UnsafetyReason},
|
2024-11-21 00:21:16 +00:00
|
|
|
CastError, InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringDiagnostic,
|
|
|
|
TyLoweringDiagnosticKind,
|
2024-11-20 21:05:48 +00:00
|
|
|
};
|
|
|
|
use syntax::{
|
|
|
|
ast::{self, HasGenericArgs},
|
|
|
|
AstPtr, SyntaxError, SyntaxNodePtr, TextRange,
|
2024-08-28 15:12:16 +00:00
|
|
|
};
|
2024-05-13 14:56:26 +00:00
|
|
|
use triomphe::Arc;
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
|
2024-07-26 12:36:13 +00:00
|
|
|
use crate::{AssocItem, Field, Local, Trait, Type};
|
2021-07-31 18:00:09 +00:00
|
|
|
|
2024-11-20 21:05:48 +00:00
|
|
|
pub use hir_def::VariantId;
|
|
|
|
pub use hir_ty::{
|
|
|
|
diagnostics::{CaseType, IncorrectCase},
|
|
|
|
GenericArgsProhibitedReason,
|
|
|
|
};
|
|
|
|
|
2021-06-13 11:41:19 +00:00
|
|
|
macro_rules! diagnostics {
|
2021-06-13 14:06:36 +00:00
|
|
|
($($diag:ident,)*) => {
|
2022-07-28 18:08:20 +00:00
|
|
|
#[derive(Debug)]
|
2021-06-13 11:41:19 +00:00
|
|
|
pub enum AnyDiagnostic {$(
|
|
|
|
$diag(Box<$diag>),
|
|
|
|
)*}
|
|
|
|
|
|
|
|
$(
|
|
|
|
impl From<$diag> for AnyDiagnostic {
|
|
|
|
fn from(d: $diag) -> AnyDiagnostic {
|
|
|
|
AnyDiagnostic::$diag(Box::new(d))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)*
|
|
|
|
};
|
|
|
|
}
|
2024-01-30 08:51:28 +00:00
|
|
|
// FIXME Accept something like the following in the macro call instead
|
|
|
|
// diagnostics![
|
|
|
|
// pub struct BreakOutsideOfLoop {
|
|
|
|
// pub expr: InFile<AstPtr<ast::Expr>>,
|
|
|
|
// pub is_break: bool,
|
|
|
|
// pub bad_value_break: bool,
|
|
|
|
// }, ...
|
|
|
|
// or more concisely
|
|
|
|
// BreakOutsideOfLoop {
|
|
|
|
// expr: InFile<AstPtr<ast::Expr>>,
|
|
|
|
// is_break: bool,
|
|
|
|
// bad_value_break: bool,
|
|
|
|
// }, ...
|
|
|
|
// ]
|
2021-06-13 11:41:19 +00:00
|
|
|
|
2021-06-13 14:06:36 +00:00
|
|
|
diagnostics![
|
2024-08-04 18:07:24 +00:00
|
|
|
AwaitOutsideOfAsync,
|
2023-04-06 13:37:53 +00:00
|
|
|
BreakOutsideOfLoop,
|
2024-08-28 15:12:16 +00:00
|
|
|
CastToUnsized,
|
2023-03-03 17:04:24 +00:00
|
|
|
ExpectedFunction,
|
2021-06-13 16:35:30 +00:00
|
|
|
InactiveCode,
|
2024-01-30 08:51:28 +00:00
|
|
|
IncoherentImpl,
|
2021-06-13 18:09:03 +00:00
|
|
|
IncorrectCase,
|
2024-08-28 15:12:16 +00:00
|
|
|
InvalidCast,
|
2021-11-18 21:17:22 +00:00
|
|
|
InvalidDeriveTarget,
|
2023-04-16 12:15:59 +00:00
|
|
|
MacroDefError,
|
2023-04-16 15:22:06 +00:00
|
|
|
MacroError,
|
|
|
|
MacroExpansionParseError,
|
2021-11-19 12:17:35 +00:00
|
|
|
MalformedDerive,
|
2021-06-13 17:06:25 +00:00
|
|
|
MismatchedArgCount,
|
2023-09-08 12:31:26 +00:00
|
|
|
MismatchedTupleStructPatArgCount,
|
2021-06-13 16:35:30 +00:00
|
|
|
MissingFields,
|
2021-06-13 18:44:31 +00:00
|
|
|
MissingMatchArms,
|
2021-06-13 17:00:27 +00:00
|
|
|
MissingUnsafe,
|
2023-05-18 15:47:06 +00:00
|
|
|
MovedOutOfRef,
|
2023-02-21 19:00:38 +00:00
|
|
|
NeedMut,
|
2024-01-05 17:38:29 +00:00
|
|
|
NonExhaustiveLet,
|
2021-06-13 16:45:16 +00:00
|
|
|
NoSuchField,
|
2023-01-01 12:24:48 +00:00
|
|
|
PrivateAssocItem,
|
2022-12-31 13:20:59 +00:00
|
|
|
PrivateField,
|
2024-01-30 16:57:36 +00:00
|
|
|
RemoveTrailingReturn,
|
2024-02-06 13:31:54 +00:00
|
|
|
RemoveUnnecessaryElse,
|
2024-02-08 16:29:27 +00:00
|
|
|
ReplaceFilterMapNextWithFindMap,
|
2023-11-14 19:02:23 +00:00
|
|
|
TraitImplIncorrectSafety,
|
2023-11-14 20:54:36 +00:00
|
|
|
TraitImplMissingAssocItems,
|
2023-11-14 19:02:23 +00:00
|
|
|
TraitImplOrphan,
|
2024-01-30 08:51:28 +00:00
|
|
|
TraitImplRedundantAssocItems,
|
2023-05-28 11:30:34 +00:00
|
|
|
TypedHole,
|
2022-03-20 15:26:48 +00:00
|
|
|
TypeMismatch,
|
2023-04-06 10:50:16 +00:00
|
|
|
UndeclaredLabel,
|
2021-06-13 16:35:30 +00:00
|
|
|
UnimplementedBuiltinMacro,
|
2023-04-06 10:50:16 +00:00
|
|
|
UnreachableLabel,
|
2023-12-31 17:33:36 +00:00
|
|
|
UnresolvedAssocItem,
|
2021-06-13 14:06:36 +00:00
|
|
|
UnresolvedExternCrate,
|
2023-03-03 18:32:18 +00:00
|
|
|
UnresolvedField,
|
2021-06-13 14:06:36 +00:00
|
|
|
UnresolvedImport,
|
|
|
|
UnresolvedMacroCall,
|
2023-03-03 19:41:17 +00:00
|
|
|
UnresolvedMethodCall,
|
2021-06-13 16:35:30 +00:00
|
|
|
UnresolvedModule,
|
2024-02-11 15:34:52 +00:00
|
|
|
UnresolvedIdent,
|
2023-02-21 19:00:38 +00:00
|
|
|
UnusedMut,
|
2023-09-24 17:59:15 +00:00
|
|
|
UnusedVariable,
|
2024-11-20 21:05:48 +00:00
|
|
|
GenericArgsProhibited,
|
2021-06-13 14:06:36 +00:00
|
|
|
];
|
2021-06-13 11:41:19 +00:00
|
|
|
|
2023-04-06 13:37:53 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct BreakOutsideOfLoop {
|
|
|
|
pub expr: InFile<AstPtr<ast::Expr>>,
|
|
|
|
pub is_break: bool,
|
|
|
|
pub bad_value_break: bool,
|
|
|
|
}
|
|
|
|
|
2023-05-28 11:30:34 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct TypedHole {
|
|
|
|
pub expr: InFile<AstPtr<ast::Expr>>,
|
|
|
|
pub expected: Type,
|
|
|
|
}
|
|
|
|
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnresolvedModule {
|
2021-06-13 11:41:19 +00:00
|
|
|
pub decl: InFile<AstPtr<ast::Module>>,
|
2022-03-11 15:49:41 +00:00
|
|
|
pub candidates: Box<[String]>,
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnresolvedExternCrate {
|
2021-06-13 13:05:43 +00:00
|
|
|
pub decl: InFile<AstPtr<ast::ExternCrate>>,
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnresolvedImport {
|
2021-06-13 13:42:34 +00:00
|
|
|
pub decl: InFile<AstPtr<ast::UseTree>>,
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
|
|
pub struct UnresolvedMacroCall {
|
2022-04-27 18:03:57 +00:00
|
|
|
pub macro_call: InFile<SyntaxNodePtr>,
|
2022-06-24 11:03:13 +00:00
|
|
|
pub precise_location: Option<TextRange>,
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
pub path: ModPath,
|
2022-04-27 18:03:57 +00:00
|
|
|
pub is_bang: bool,
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
}
|
2023-04-06 10:50:16 +00:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
|
|
pub struct UnreachableLabel {
|
|
|
|
pub node: InFile<AstPtr<ast::Lifetime>>,
|
|
|
|
pub name: Name,
|
|
|
|
}
|
|
|
|
|
2024-08-04 18:07:24 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct AwaitOutsideOfAsync {
|
|
|
|
pub node: InFile<AstPtr<ast::AwaitExpr>>,
|
|
|
|
pub location: String,
|
|
|
|
}
|
|
|
|
|
2023-04-06 10:50:16 +00:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
|
|
pub struct UndeclaredLabel {
|
|
|
|
pub node: InFile<AstPtr<ast::Lifetime>>,
|
|
|
|
pub name: Name,
|
|
|
|
}
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
|
|
pub struct InactiveCode {
|
2021-06-13 14:29:25 +00:00
|
|
|
pub node: InFile<SyntaxNodePtr>,
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
pub cfg: CfgExpr,
|
|
|
|
pub opts: CfgOptions,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
|
|
pub struct MacroError {
|
2021-06-13 15:41:04 +00:00
|
|
|
pub node: InFile<SyntaxNodePtr>,
|
2022-06-24 11:03:13 +00:00
|
|
|
pub precise_location: Option<TextRange>,
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
pub message: String,
|
2024-07-26 12:36:13 +00:00
|
|
|
pub error: bool,
|
2024-10-27 00:24:15 +00:00
|
|
|
pub kind: &'static str,
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
}
|
|
|
|
|
2023-04-16 15:22:06 +00:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
|
|
pub struct MacroExpansionParseError {
|
|
|
|
pub node: InFile<SyntaxNodePtr>,
|
|
|
|
pub precise_location: Option<TextRange>,
|
2024-05-13 14:56:26 +00:00
|
|
|
pub errors: Arc<[SyntaxError]>,
|
2023-04-16 15:22:06 +00:00
|
|
|
}
|
|
|
|
|
2023-04-16 12:15:59 +00:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
|
|
pub struct MacroDefError {
|
|
|
|
pub node: InFile<AstPtr<ast::Macro>>,
|
|
|
|
pub message: String,
|
|
|
|
pub name: Option<TextRange>,
|
|
|
|
}
|
|
|
|
|
2021-05-30 02:19:47 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnimplementedBuiltinMacro {
|
2021-06-13 16:35:30 +00:00
|
|
|
pub node: InFile<SyntaxNodePtr>,
|
2021-05-30 02:19:47 +00:00
|
|
|
}
|
2021-06-12 14:17:23 +00:00
|
|
|
|
2021-11-18 21:17:22 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct InvalidDeriveTarget {
|
|
|
|
pub node: InFile<SyntaxNodePtr>,
|
|
|
|
}
|
|
|
|
|
2021-11-19 12:17:35 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MalformedDerive {
|
|
|
|
pub node: InFile<SyntaxNodePtr>,
|
|
|
|
}
|
|
|
|
|
2021-06-12 14:17:23 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct NoSuchField {
|
2023-10-06 10:32:37 +00:00
|
|
|
pub field: InFile<AstPtr<Either<ast::RecordExprField, ast::RecordPatField>>>,
|
2023-09-08 21:19:30 +00:00
|
|
|
pub private: bool,
|
2024-04-23 12:53:12 +00:00
|
|
|
pub variant: VariantId,
|
2021-06-12 14:17:23 +00:00
|
|
|
}
|
|
|
|
|
2023-01-01 12:24:48 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct PrivateAssocItem {
|
2024-03-06 14:57:05 +00:00
|
|
|
pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
|
2023-01-01 12:24:48 +00:00
|
|
|
pub item: AssocItem,
|
|
|
|
}
|
|
|
|
|
2023-09-08 12:31:26 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MismatchedTupleStructPatArgCount {
|
2023-10-06 10:32:37 +00:00
|
|
|
pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
|
2023-09-08 12:31:26 +00:00
|
|
|
pub expected: usize,
|
|
|
|
pub found: usize,
|
|
|
|
}
|
|
|
|
|
2023-03-03 17:04:24 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct ExpectedFunction {
|
|
|
|
pub call: InFile<AstPtr<ast::Expr>>,
|
|
|
|
pub found: Type,
|
|
|
|
}
|
|
|
|
|
2023-03-03 18:32:18 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnresolvedField {
|
|
|
|
pub expr: InFile<AstPtr<ast::Expr>>,
|
|
|
|
pub receiver: Type,
|
|
|
|
pub name: Name,
|
|
|
|
pub method_with_same_name_exists: bool,
|
|
|
|
}
|
|
|
|
|
2023-03-03 19:41:17 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnresolvedMethodCall {
|
|
|
|
pub expr: InFile<AstPtr<ast::Expr>>,
|
|
|
|
pub receiver: Type,
|
|
|
|
pub name: Name,
|
|
|
|
pub field_with_same_name: Option<Type>,
|
2023-12-12 12:24:33 +00:00
|
|
|
pub assoc_func_with_same_name: Option<AssocItemId>,
|
2023-03-03 19:41:17 +00:00
|
|
|
}
|
|
|
|
|
2023-12-31 17:33:36 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnresolvedAssocItem {
|
2024-03-06 14:57:05 +00:00
|
|
|
pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
|
2023-12-31 17:33:36 +00:00
|
|
|
}
|
|
|
|
|
2024-02-11 15:34:52 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnresolvedIdent {
|
Handle destructuring assignments uniformly
Instead of lowering them to `<expr> = <expr>`, then hacking on-demand to resolve them, we lower them to `<pat> = <expr>`, and use the pattern infrastructure to handle them. It turns out, destructuring assignments are surprisingly similar to pattern bindings, and so only minor modifications are needed.
This fixes few bugs that arose because of the non-uniform handling (for example, MIR lowering not handling slice and record patterns, and closure capture calculation not handling destructuring assignments at all), and furthermore, guarantees we won't have such bugs in the future, since the programmer will always have to explicitly handle `Expr::Assignment`.
Tests don't pass yet; that's because the generated patterns do not exist in the source map. The next commit will fix that.
2024-10-06 15:14:07 +00:00
|
|
|
pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
|
2024-02-11 15:34:52 +00:00
|
|
|
}
|
|
|
|
|
2022-12-31 13:20:59 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct PrivateField {
|
|
|
|
pub expr: InFile<AstPtr<ast::Expr>>,
|
|
|
|
pub field: Field,
|
|
|
|
}
|
|
|
|
|
2021-06-12 14:39:46 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MissingUnsafe {
|
2024-12-04 06:05:23 +00:00
|
|
|
pub node: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
|
2024-09-18 00:02:12 +00:00
|
|
|
/// If true, the diagnostics is an `unsafe_op_in_unsafe_fn` lint instead of a hard error.
|
|
|
|
pub only_lint: bool,
|
2024-12-04 06:05:23 +00:00
|
|
|
pub reason: UnsafetyReason,
|
2021-06-12 14:39:46 +00:00
|
|
|
}
|
2021-06-12 16:28:19 +00:00
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MissingFields {
|
|
|
|
pub file: HirFileId,
|
2023-10-06 10:32:37 +00:00
|
|
|
pub field_list_parent: AstPtr<Either<ast::RecordExpr, ast::RecordPat>>,
|
2021-06-12 16:28:19 +00:00
|
|
|
pub field_list_parent_path: Option<AstPtr<ast::Path>>,
|
|
|
|
pub missed_fields: Vec<Name>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct ReplaceFilterMapNextWithFindMap {
|
|
|
|
pub file: HirFileId,
|
|
|
|
/// This expression is the whole method chain up to and including `.filter_map(..).next()`.
|
|
|
|
pub next_expr: AstPtr<ast::Expr>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MismatchedArgCount {
|
2021-06-13 17:06:25 +00:00
|
|
|
pub call_expr: InFile<AstPtr<ast::Expr>>,
|
2021-06-12 16:28:19 +00:00
|
|
|
pub expected: usize,
|
|
|
|
pub found: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MissingMatchArms {
|
2023-03-10 13:21:54 +00:00
|
|
|
pub scrutinee_expr: InFile<AstPtr<ast::Expr>>,
|
2022-06-20 10:48:09 +00:00
|
|
|
pub uncovered_patterns: String,
|
2021-06-12 16:28:19 +00:00
|
|
|
}
|
|
|
|
|
2024-01-05 17:38:29 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct NonExhaustiveLet {
|
|
|
|
pub pat: InFile<AstPtr<ast::Pat>>,
|
|
|
|
pub uncovered_patterns: String,
|
|
|
|
}
|
|
|
|
|
2021-08-08 08:12:40 +00:00
|
|
|
#[derive(Debug)]
|
2022-03-20 15:26:48 +00:00
|
|
|
pub struct TypeMismatch {
|
2023-10-06 10:32:37 +00:00
|
|
|
pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
|
2022-03-20 15:26:48 +00:00
|
|
|
pub expected: Type,
|
|
|
|
pub actual: Type,
|
2021-08-08 08:12:40 +00:00
|
|
|
}
|
|
|
|
|
2023-02-21 19:00:38 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct NeedMut {
|
|
|
|
pub local: Local,
|
|
|
|
pub span: InFile<SyntaxNodePtr>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnusedMut {
|
|
|
|
pub local: Local,
|
|
|
|
}
|
2023-05-18 15:47:06 +00:00
|
|
|
|
2023-09-24 17:59:15 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct UnusedVariable {
|
|
|
|
pub local: Local,
|
|
|
|
}
|
|
|
|
|
2023-05-18 15:47:06 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct MovedOutOfRef {
|
|
|
|
pub ty: Type,
|
|
|
|
pub span: InFile<SyntaxNodePtr>,
|
|
|
|
}
|
2023-11-14 17:09:28 +00:00
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
|
|
pub struct IncoherentImpl {
|
|
|
|
pub file_id: HirFileId,
|
|
|
|
pub impl_: AstPtr<ast::Impl>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
|
|
pub struct TraitImplOrphan {
|
|
|
|
pub file_id: HirFileId,
|
|
|
|
pub impl_: AstPtr<ast::Impl>,
|
|
|
|
}
|
2023-11-14 19:02:23 +00:00
|
|
|
|
|
|
|
// FIXME: Split this off into the corresponding 4 rustc errors
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
|
|
pub struct TraitImplIncorrectSafety {
|
|
|
|
pub file_id: HirFileId,
|
|
|
|
pub impl_: AstPtr<ast::Impl>,
|
|
|
|
pub should_be_safe: bool,
|
|
|
|
}
|
2023-11-14 20:54:36 +00:00
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
|
|
pub struct TraitImplMissingAssocItems {
|
|
|
|
pub file_id: HirFileId,
|
|
|
|
pub impl_: AstPtr<ast::Impl>,
|
|
|
|
pub missing: Vec<(Name, AssocItem)>,
|
|
|
|
}
|
2023-11-28 13:15:45 +00:00
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
2023-12-01 11:09:42 +00:00
|
|
|
pub struct TraitImplRedundantAssocItems {
|
2023-11-28 13:15:45 +00:00
|
|
|
pub file_id: HirFileId,
|
2023-12-01 11:09:42 +00:00
|
|
|
pub trait_: Trait,
|
2023-12-07 12:45:42 +00:00
|
|
|
pub impl_: AstPtr<ast::Impl>,
|
2023-12-01 11:09:42 +00:00
|
|
|
pub assoc_item: (Name, AssocItem),
|
|
|
|
}
|
2024-01-30 08:51:28 +00:00
|
|
|
|
2024-01-30 16:57:36 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct RemoveTrailingReturn {
|
2024-01-31 12:04:41 +00:00
|
|
|
pub return_expr: InFile<AstPtr<ast::ReturnExpr>>,
|
2024-01-30 16:57:36 +00:00
|
|
|
}
|
|
|
|
|
2024-02-06 13:31:54 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct RemoveUnnecessaryElse {
|
|
|
|
pub if_expr: InFile<AstPtr<ast::IfExpr>>,
|
|
|
|
}
|
|
|
|
|
2024-08-28 15:12:16 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct CastToUnsized {
|
|
|
|
pub expr: InFile<AstPtr<ast::Expr>>,
|
|
|
|
pub cast_ty: Type,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct InvalidCast {
|
|
|
|
pub expr: InFile<AstPtr<ast::Expr>>,
|
|
|
|
pub error: CastError,
|
|
|
|
pub expr_ty: Type,
|
|
|
|
pub cast_ty: Type,
|
|
|
|
}
|
|
|
|
|
2024-11-20 21:05:48 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct GenericArgsProhibited {
|
2024-11-21 00:21:16 +00:00
|
|
|
pub args: InFile<AstPtr<Either<ast::GenericArgList, ast::ParenthesizedArgList>>>,
|
2024-11-20 21:05:48 +00:00
|
|
|
pub reason: GenericArgsProhibitedReason,
|
|
|
|
}
|
|
|
|
|
2024-01-30 08:51:28 +00:00
|
|
|
impl AnyDiagnostic {
|
|
|
|
pub(crate) fn body_validation_diagnostic(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
diagnostic: BodyValidationDiagnostic,
|
|
|
|
source_map: &hir_def::body::BodySourceMap,
|
|
|
|
) -> Option<AnyDiagnostic> {
|
|
|
|
match diagnostic {
|
|
|
|
BodyValidationDiagnostic::RecordMissingFields { record, variant, missed_fields } => {
|
|
|
|
let variant_data = variant.variant_data(db.upcast());
|
|
|
|
let missed_fields = missed_fields
|
|
|
|
.into_iter()
|
|
|
|
.map(|idx| variant_data.fields()[idx].name.clone())
|
|
|
|
.collect();
|
|
|
|
|
2024-10-06 19:52:56 +00:00
|
|
|
let record = match record {
|
|
|
|
Either::Left(record_expr) => {
|
|
|
|
source_map.expr_syntax(record_expr).ok()?.map(AstPtr::wrap_left)
|
|
|
|
}
|
|
|
|
Either::Right(record_pat) => source_map.pat_syntax(record_pat).ok()?,
|
|
|
|
};
|
|
|
|
let file = record.file_id;
|
|
|
|
let root = record.file_syntax(db.upcast());
|
|
|
|
match record.value.to_node(&root) {
|
|
|
|
Either::Left(ast::Expr::RecordExpr(record_expr)) => {
|
|
|
|
if record_expr.record_expr_field_list().is_some() {
|
|
|
|
let field_list_parent_path =
|
|
|
|
record_expr.path().map(|path| AstPtr::new(&path));
|
|
|
|
return Some(
|
|
|
|
MissingFields {
|
|
|
|
file,
|
|
|
|
field_list_parent: AstPtr::new(&Either::Left(record_expr)),
|
|
|
|
field_list_parent_path,
|
|
|
|
missed_fields,
|
2024-01-30 08:51:28 +00:00
|
|
|
}
|
2024-10-06 19:52:56 +00:00
|
|
|
.into(),
|
|
|
|
);
|
2024-01-30 08:51:28 +00:00
|
|
|
}
|
2024-10-06 19:52:56 +00:00
|
|
|
}
|
|
|
|
Either::Right(ast::Pat::RecordPat(record_pat)) => {
|
|
|
|
if record_pat.record_pat_field_list().is_some() {
|
|
|
|
let field_list_parent_path =
|
|
|
|
record_pat.path().map(|path| AstPtr::new(&path));
|
|
|
|
return Some(
|
|
|
|
MissingFields {
|
|
|
|
file,
|
|
|
|
field_list_parent: AstPtr::new(&Either::Right(record_pat)),
|
|
|
|
field_list_parent_path,
|
|
|
|
missed_fields,
|
2024-01-30 08:51:28 +00:00
|
|
|
}
|
2024-10-06 19:52:56 +00:00
|
|
|
.into(),
|
|
|
|
);
|
2024-01-30 08:51:28 +00:00
|
|
|
}
|
2024-10-06 19:52:56 +00:00
|
|
|
}
|
|
|
|
_ => {}
|
2024-01-30 08:51:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr } => {
|
|
|
|
if let Ok(next_source_ptr) = source_map.expr_syntax(method_call_expr) {
|
|
|
|
return Some(
|
|
|
|
ReplaceFilterMapNextWithFindMap {
|
|
|
|
file: next_source_ptr.file_id,
|
|
|
|
next_expr: next_source_ptr.value,
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BodyValidationDiagnostic::MissingMatchArms { match_expr, uncovered_patterns } => {
|
|
|
|
match source_map.expr_syntax(match_expr) {
|
|
|
|
Ok(source_ptr) => {
|
|
|
|
let root = source_ptr.file_syntax(db.upcast());
|
|
|
|
if let ast::Expr::MatchExpr(match_expr) = &source_ptr.value.to_node(&root) {
|
|
|
|
match match_expr.expr() {
|
|
|
|
Some(scrut_expr) if match_expr.match_arm_list().is_some() => {
|
|
|
|
return Some(
|
|
|
|
MissingMatchArms {
|
|
|
|
scrutinee_expr: InFile::new(
|
|
|
|
source_ptr.file_id,
|
|
|
|
AstPtr::new(&scrut_expr),
|
|
|
|
),
|
|
|
|
uncovered_patterns,
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(SyntheticSyntax) => (),
|
|
|
|
}
|
|
|
|
}
|
2024-01-05 17:38:29 +00:00
|
|
|
BodyValidationDiagnostic::NonExhaustiveLet { pat, uncovered_patterns } => {
|
|
|
|
match source_map.pat_syntax(pat) {
|
|
|
|
Ok(source_ptr) => {
|
|
|
|
if let Some(ast_pat) = source_ptr.value.cast::<ast::Pat>() {
|
|
|
|
return Some(
|
|
|
|
NonExhaustiveLet {
|
|
|
|
pat: InFile::new(source_ptr.file_id, ast_pat),
|
|
|
|
uncovered_patterns,
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(SyntheticSyntax) => {}
|
|
|
|
}
|
|
|
|
}
|
2024-01-30 16:57:36 +00:00
|
|
|
BodyValidationDiagnostic::RemoveTrailingReturn { return_expr } => {
|
|
|
|
if let Ok(source_ptr) = source_map.expr_syntax(return_expr) {
|
2024-01-31 04:04:49 +00:00
|
|
|
// Filters out desugared return expressions (e.g. desugared try operators).
|
2024-01-31 12:04:41 +00:00
|
|
|
if let Some(ptr) = source_ptr.value.cast::<ast::ReturnExpr>() {
|
2024-01-31 04:04:49 +00:00
|
|
|
return Some(
|
|
|
|
RemoveTrailingReturn {
|
2024-01-31 12:04:41 +00:00
|
|
|
return_expr: InFile::new(source_ptr.file_id, ptr),
|
2024-01-31 04:04:49 +00:00
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
2024-01-30 16:57:36 +00:00
|
|
|
}
|
|
|
|
}
|
2024-02-06 13:31:54 +00:00
|
|
|
BodyValidationDiagnostic::RemoveUnnecessaryElse { if_expr } => {
|
|
|
|
if let Ok(source_ptr) = source_map.expr_syntax(if_expr) {
|
|
|
|
if let Some(ptr) = source_ptr.value.cast::<ast::IfExpr>() {
|
|
|
|
return Some(
|
|
|
|
RemoveUnnecessaryElse { if_expr: InFile::new(source_ptr.file_id, ptr) }
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-01-30 08:51:28 +00:00
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn inference_diagnostic(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
def: DefWithBodyId,
|
|
|
|
d: &InferenceDiagnostic,
|
2024-11-20 21:05:48 +00:00
|
|
|
outer_types_source_map: &TypesSourceMap,
|
2024-01-30 08:51:28 +00:00
|
|
|
source_map: &hir_def::body::BodySourceMap,
|
|
|
|
) -> Option<AnyDiagnostic> {
|
2024-02-26 16:46:03 +00:00
|
|
|
let expr_syntax = |expr| {
|
|
|
|
source_map.expr_syntax(expr).inspect_err(|_| tracing::error!("synthetic syntax")).ok()
|
|
|
|
};
|
|
|
|
let pat_syntax = |pat| {
|
|
|
|
source_map.pat_syntax(pat).inspect_err(|_| tracing::error!("synthetic syntax")).ok()
|
|
|
|
};
|
Handle destructuring assignments uniformly
Instead of lowering them to `<expr> = <expr>`, then hacking on-demand to resolve them, we lower them to `<pat> = <expr>`, and use the pattern infrastructure to handle them. It turns out, destructuring assignments are surprisingly similar to pattern bindings, and so only minor modifications are needed.
This fixes few bugs that arose because of the non-uniform handling (for example, MIR lowering not handling slice and record patterns, and closure capture calculation not handling destructuring assignments at all), and furthermore, guarantees we won't have such bugs in the future, since the programmer will always have to explicitly handle `Expr::Assignment`.
Tests don't pass yet; that's because the generated patterns do not exist in the source map. The next commit will fix that.
2024-10-06 15:14:07 +00:00
|
|
|
let expr_or_pat_syntax = |id| match id {
|
|
|
|
ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(|it| it.map(AstPtr::wrap_left)),
|
2024-10-06 19:52:56 +00:00
|
|
|
ExprOrPatId::PatId(pat) => pat_syntax(pat),
|
Handle destructuring assignments uniformly
Instead of lowering them to `<expr> = <expr>`, then hacking on-demand to resolve them, we lower them to `<pat> = <expr>`, and use the pattern infrastructure to handle them. It turns out, destructuring assignments are surprisingly similar to pattern bindings, and so only minor modifications are needed.
This fixes few bugs that arose because of the non-uniform handling (for example, MIR lowering not handling slice and record patterns, and closure capture calculation not handling destructuring assignments at all), and furthermore, guarantees we won't have such bugs in the future, since the programmer will always have to explicitly handle `Expr::Assignment`.
Tests don't pass yet; that's because the generated patterns do not exist in the source map. The next commit will fix that.
2024-10-06 15:14:07 +00:00
|
|
|
};
|
2024-01-30 08:51:28 +00:00
|
|
|
Some(match d {
|
2024-04-23 12:53:12 +00:00
|
|
|
&InferenceDiagnostic::NoSuchField { field: expr, private, variant } => {
|
2024-01-30 08:51:28 +00:00
|
|
|
let expr_or_pat = match expr {
|
|
|
|
ExprOrPatId::ExprId(expr) => {
|
|
|
|
source_map.field_syntax(expr).map(AstPtr::wrap_left)
|
|
|
|
}
|
2024-10-06 19:52:56 +00:00
|
|
|
ExprOrPatId::PatId(pat) => source_map.pat_field_syntax(pat),
|
2024-01-30 08:51:28 +00:00
|
|
|
};
|
2024-04-23 12:53:12 +00:00
|
|
|
NoSuchField { field: expr_or_pat, private, variant }.into()
|
2024-01-30 08:51:28 +00:00
|
|
|
}
|
|
|
|
&InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
|
2024-02-26 16:46:03 +00:00
|
|
|
MismatchedArgCount { call_expr: expr_syntax(call_expr)?, expected, found }.into()
|
2024-01-30 08:51:28 +00:00
|
|
|
}
|
|
|
|
&InferenceDiagnostic::PrivateField { expr, field } => {
|
2024-02-26 16:46:03 +00:00
|
|
|
let expr = expr_syntax(expr)?;
|
2024-01-30 08:51:28 +00:00
|
|
|
let field = field.into();
|
|
|
|
PrivateField { expr, field }.into()
|
|
|
|
}
|
|
|
|
&InferenceDiagnostic::PrivateAssocItem { id, item } => {
|
Handle destructuring assignments uniformly
Instead of lowering them to `<expr> = <expr>`, then hacking on-demand to resolve them, we lower them to `<pat> = <expr>`, and use the pattern infrastructure to handle them. It turns out, destructuring assignments are surprisingly similar to pattern bindings, and so only minor modifications are needed.
This fixes few bugs that arose because of the non-uniform handling (for example, MIR lowering not handling slice and record patterns, and closure capture calculation not handling destructuring assignments at all), and furthermore, guarantees we won't have such bugs in the future, since the programmer will always have to explicitly handle `Expr::Assignment`.
Tests don't pass yet; that's because the generated patterns do not exist in the source map. The next commit will fix that.
2024-10-06 15:14:07 +00:00
|
|
|
let expr_or_pat = expr_or_pat_syntax(id)?;
|
2024-01-30 08:51:28 +00:00
|
|
|
let item = item.into();
|
|
|
|
PrivateAssocItem { expr_or_pat, item }.into()
|
|
|
|
}
|
|
|
|
InferenceDiagnostic::ExpectedFunction { call_expr, found } => {
|
2024-02-26 16:46:03 +00:00
|
|
|
let call_expr = expr_syntax(*call_expr)?;
|
2024-01-30 08:51:28 +00:00
|
|
|
ExpectedFunction { call: call_expr, found: Type::new(db, def, found.clone()) }
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
InferenceDiagnostic::UnresolvedField {
|
|
|
|
expr,
|
|
|
|
receiver,
|
|
|
|
name,
|
|
|
|
method_with_same_name_exists,
|
|
|
|
} => {
|
2024-02-26 16:46:03 +00:00
|
|
|
let expr = expr_syntax(*expr)?;
|
2024-01-30 08:51:28 +00:00
|
|
|
UnresolvedField {
|
|
|
|
expr,
|
|
|
|
name: name.clone(),
|
|
|
|
receiver: Type::new(db, def, receiver.clone()),
|
|
|
|
method_with_same_name_exists: *method_with_same_name_exists,
|
|
|
|
}
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
InferenceDiagnostic::UnresolvedMethodCall {
|
|
|
|
expr,
|
|
|
|
receiver,
|
|
|
|
name,
|
|
|
|
field_with_same_name,
|
|
|
|
assoc_func_with_same_name,
|
|
|
|
} => {
|
2024-02-26 16:46:03 +00:00
|
|
|
let expr = expr_syntax(*expr)?;
|
2024-01-30 08:51:28 +00:00
|
|
|
UnresolvedMethodCall {
|
|
|
|
expr,
|
|
|
|
name: name.clone(),
|
|
|
|
receiver: Type::new(db, def, receiver.clone()),
|
|
|
|
field_with_same_name: field_with_same_name
|
|
|
|
.clone()
|
|
|
|
.map(|ty| Type::new(db, def, ty)),
|
|
|
|
assoc_func_with_same_name: *assoc_func_with_same_name,
|
|
|
|
}
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
&InferenceDiagnostic::UnresolvedAssocItem { id } => {
|
Handle destructuring assignments uniformly
Instead of lowering them to `<expr> = <expr>`, then hacking on-demand to resolve them, we lower them to `<pat> = <expr>`, and use the pattern infrastructure to handle them. It turns out, destructuring assignments are surprisingly similar to pattern bindings, and so only minor modifications are needed.
This fixes few bugs that arose because of the non-uniform handling (for example, MIR lowering not handling slice and record patterns, and closure capture calculation not handling destructuring assignments at all), and furthermore, guarantees we won't have such bugs in the future, since the programmer will always have to explicitly handle `Expr::Assignment`.
Tests don't pass yet; that's because the generated patterns do not exist in the source map. The next commit will fix that.
2024-10-06 15:14:07 +00:00
|
|
|
let expr_or_pat = expr_or_pat_syntax(id)?;
|
2024-01-30 08:51:28 +00:00
|
|
|
UnresolvedAssocItem { expr_or_pat }.into()
|
|
|
|
}
|
Handle destructuring assignments uniformly
Instead of lowering them to `<expr> = <expr>`, then hacking on-demand to resolve them, we lower them to `<pat> = <expr>`, and use the pattern infrastructure to handle them. It turns out, destructuring assignments are surprisingly similar to pattern bindings, and so only minor modifications are needed.
This fixes few bugs that arose because of the non-uniform handling (for example, MIR lowering not handling slice and record patterns, and closure capture calculation not handling destructuring assignments at all), and furthermore, guarantees we won't have such bugs in the future, since the programmer will always have to explicitly handle `Expr::Assignment`.
Tests don't pass yet; that's because the generated patterns do not exist in the source map. The next commit will fix that.
2024-10-06 15:14:07 +00:00
|
|
|
&InferenceDiagnostic::UnresolvedIdent { id } => {
|
|
|
|
let expr_or_pat = expr_or_pat_syntax(id)?;
|
|
|
|
UnresolvedIdent { expr_or_pat }.into()
|
2024-02-11 15:34:52 +00:00
|
|
|
}
|
2024-01-30 08:51:28 +00:00
|
|
|
&InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break, bad_value_break } => {
|
2024-02-26 16:46:03 +00:00
|
|
|
let expr = expr_syntax(expr)?;
|
2024-01-30 08:51:28 +00:00
|
|
|
BreakOutsideOfLoop { expr, is_break, bad_value_break }.into()
|
|
|
|
}
|
|
|
|
InferenceDiagnostic::TypedHole { expr, expected } => {
|
2024-02-26 16:46:03 +00:00
|
|
|
let expr = expr_syntax(*expr)?;
|
2024-01-30 08:51:28 +00:00
|
|
|
TypedHole { expr, expected: Type::new(db, def, expected.clone()) }.into()
|
|
|
|
}
|
|
|
|
&InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => {
|
|
|
|
let expr_or_pat = match pat {
|
2024-02-26 16:46:03 +00:00
|
|
|
ExprOrPatId::ExprId(expr) => expr_syntax(expr)?.map(AstPtr::wrap_left),
|
2024-01-30 08:51:28 +00:00
|
|
|
ExprOrPatId::PatId(pat) => {
|
2024-02-26 16:46:03 +00:00
|
|
|
let InFile { file_id, value } = pat_syntax(pat)?;
|
2024-01-30 08:51:28 +00:00
|
|
|
|
|
|
|
// cast from Either<Pat, SelfParam> -> Either<_, Pat>
|
2024-02-01 15:16:38 +00:00
|
|
|
let ptr = AstPtr::try_from_raw(value.syntax_node_ptr())?;
|
2024-01-30 08:51:28 +00:00
|
|
|
InFile { file_id, value: ptr }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into()
|
|
|
|
}
|
2024-08-28 15:12:16 +00:00
|
|
|
InferenceDiagnostic::CastToUnsized { expr, cast_ty } => {
|
|
|
|
let expr = expr_syntax(*expr)?;
|
|
|
|
CastToUnsized { expr, cast_ty: Type::new(db, def, cast_ty.clone()) }.into()
|
|
|
|
}
|
|
|
|
InferenceDiagnostic::InvalidCast { expr, error, expr_ty, cast_ty } => {
|
|
|
|
let expr = expr_syntax(*expr)?;
|
|
|
|
let expr_ty = Type::new(db, def, expr_ty.clone());
|
|
|
|
let cast_ty = Type::new(db, def, cast_ty.clone());
|
|
|
|
InvalidCast { expr, error: *error, expr_ty, cast_ty }.into()
|
|
|
|
}
|
2024-11-20 21:05:48 +00:00
|
|
|
InferenceDiagnostic::TyDiagnostic { source, diag } => {
|
|
|
|
let source_map = match source {
|
|
|
|
InferenceTyDiagnosticSource::Body => &source_map.types,
|
|
|
|
InferenceTyDiagnosticSource::Signature => outer_types_source_map,
|
|
|
|
};
|
2024-11-21 00:21:16 +00:00
|
|
|
Self::ty_diagnostic(diag, source_map, db)?
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn ty_diagnostic(
|
|
|
|
diag: &TyLoweringDiagnostic,
|
|
|
|
source_map: &TypesSourceMap,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
) -> Option<AnyDiagnostic> {
|
|
|
|
let source = match diag.source {
|
|
|
|
Either::Left(type_ref_id) => {
|
|
|
|
let Ok(source) = source_map.type_syntax(type_ref_id) else {
|
|
|
|
stdx::never!("error on synthetic type syntax");
|
|
|
|
return None;
|
2024-11-20 21:05:48 +00:00
|
|
|
};
|
2024-11-21 00:21:16 +00:00
|
|
|
source
|
|
|
|
}
|
|
|
|
Either::Right(source) => source,
|
|
|
|
};
|
|
|
|
let syntax = || source.value.to_node(&db.parse_or_expand(source.file_id));
|
|
|
|
Some(match diag.kind {
|
|
|
|
TyLoweringDiagnosticKind::GenericArgsProhibited { segment, reason } => {
|
|
|
|
let ast::Type::PathType(syntax) = syntax() else { return None };
|
|
|
|
let segment = hir_segment_to_ast_segment(&syntax.path()?, segment)?;
|
|
|
|
let args = if let Some(generics) = segment.generic_arg_list() {
|
|
|
|
AstPtr::new(&generics).wrap_left()
|
|
|
|
} else {
|
|
|
|
AstPtr::new(&segment.parenthesized_arg_list()?).wrap_right()
|
|
|
|
};
|
|
|
|
let args = source.with_value(args);
|
|
|
|
GenericArgsProhibited { args, reason }.into()
|
2024-11-20 21:05:48 +00:00
|
|
|
}
|
2024-01-30 08:51:28 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|