Auto merge of #17131 - bzy-debug:issue-17107, r=lnicola

different error code of "no such field" error based on variant type

fix #17107

Pass variant information down to diagnostic, so that we can get different error code based on variant type.

After fix:

- structure

  <img width="868" alt="Screenshot 2024-04-23 at 21 03 27" src="https://github.com/rust-lang/rust-analyzer/assets/71200607/c2d1e389-5b62-4e9a-a133-9ae41f80615f">

- enum's structure variant

  <img width="937" alt="Screenshot 2024-04-23 at 21 04 41" src="https://github.com/rust-lang/rust-analyzer/assets/71200607/ad8558a7-d809-4968-b290-2f6bbb8d6b8c">
This commit is contained in:
bors 2024-04-24 07:46:09 +00:00
commit 5a315da949
5 changed files with 14 additions and 4 deletions

View File

@ -198,6 +198,7 @@ pub enum InferenceDiagnostic {
NoSuchField { NoSuchField {
field: ExprOrPatId, field: ExprOrPatId,
private: bool, private: bool,
variant: VariantId,
}, },
PrivateField { PrivateField {
expr: ExprId, expr: ExprId,

View File

@ -563,6 +563,7 @@ impl InferenceContext<'_> {
InferenceDiagnostic::NoSuchField { InferenceDiagnostic::NoSuchField {
field: field.expr.into(), field: field.expr.into(),
private: true, private: true,
variant: def,
}, },
); );
} }
@ -572,6 +573,7 @@ impl InferenceContext<'_> {
self.push_diagnostic(InferenceDiagnostic::NoSuchField { self.push_diagnostic(InferenceDiagnostic::NoSuchField {
field: field.expr.into(), field: field.expr.into(),
private: false, private: false,
variant: def,
}); });
None None
} }

View File

@ -177,6 +177,7 @@ impl InferenceContext<'_> {
self.push_diagnostic(InferenceDiagnostic::NoSuchField { self.push_diagnostic(InferenceDiagnostic::NoSuchField {
field: inner.into(), field: inner.into(),
private: true, private: true,
variant: def,
}); });
} }
let f = field_types[local_id].clone(); let f = field_types[local_id].clone();
@ -190,6 +191,7 @@ impl InferenceContext<'_> {
self.push_diagnostic(InferenceDiagnostic::NoSuchField { self.push_diagnostic(InferenceDiagnostic::NoSuchField {
field: inner.into(), field: inner.into(),
private: false, private: false,
variant: def,
}); });
self.err_ty() self.err_ty()
} }

View File

@ -9,6 +9,7 @@ use hir_ty::{db::HirDatabase, diagnostics::BodyValidationDiagnostic, InferenceDi
use base_db::CrateId; use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
use either::Either; use either::Either;
pub use hir_def::VariantId;
use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId}; use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId};
use hir_expand::{name::Name, HirFileId, InFile}; use hir_expand::{name::Name, HirFileId, InFile};
use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange}; use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
@ -200,6 +201,7 @@ pub struct MalformedDerive {
pub struct NoSuchField { pub struct NoSuchField {
pub field: InFile<AstPtr<Either<ast::RecordExprField, ast::RecordPatField>>>, pub field: InFile<AstPtr<Either<ast::RecordExprField, ast::RecordPatField>>>,
pub private: bool, pub private: bool,
pub variant: VariantId,
} }
#[derive(Debug)] #[derive(Debug)]
@ -525,7 +527,7 @@ impl AnyDiagnostic {
source_map.pat_syntax(pat).inspect_err(|_| tracing::error!("synthetic syntax")).ok() source_map.pat_syntax(pat).inspect_err(|_| tracing::error!("synthetic syntax")).ok()
}; };
Some(match d { Some(match d {
&InferenceDiagnostic::NoSuchField { field: expr, private } => { &InferenceDiagnostic::NoSuchField { field: expr, private, variant } => {
let expr_or_pat = match expr { let expr_or_pat = match expr {
ExprOrPatId::ExprId(expr) => { ExprOrPatId::ExprId(expr) => {
source_map.field_syntax(expr).map(AstPtr::wrap_left) source_map.field_syntax(expr).map(AstPtr::wrap_left)
@ -534,7 +536,7 @@ impl AnyDiagnostic {
source_map.pat_field_syntax(pat).map(AstPtr::wrap_right) source_map.pat_field_syntax(pat).map(AstPtr::wrap_right)
} }
}; };
NoSuchField { field: expr_or_pat, private }.into() NoSuchField { field: expr_or_pat, private, variant }.into()
} }
&InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { &InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
MismatchedArgCount { call_expr: expr_syntax(call_expr)?, expected, found }.into() MismatchedArgCount { call_expr: expr_syntax(call_expr)?, expected, found }.into()

View File

@ -1,5 +1,5 @@
use either::Either; use either::Either;
use hir::{db::ExpandDatabase, HasSource, HirDisplay, HirFileIdExt, Semantics}; use hir::{db::ExpandDatabase, HasSource, HirDisplay, HirFileIdExt, Semantics, VariantId};
use ide_db::{base_db::FileId, source_change::SourceChange, RootDatabase}; use ide_db::{base_db::FileId, source_change::SourceChange, RootDatabase};
use syntax::{ use syntax::{
ast::{self, edit::IndentLevel, make}, ast::{self, edit::IndentLevel, make},
@ -25,7 +25,10 @@ pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField)
} else { } else {
Diagnostic::new_with_syntax_node_ptr( Diagnostic::new_with_syntax_node_ptr(
ctx, ctx,
DiagnosticCode::RustcHardError("E0559"), match d.variant {
VariantId::EnumVariantId(_) => DiagnosticCode::RustcHardError("E0559"),
_ => DiagnosticCode::RustcHardError("E0560"),
},
"no such field", "no such field",
node, node,
) )