mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-29 03:27:44 +00:00
Rollup merge of #81504 - matsujika:suggestion-field-access, r=estebank
Suggest accessing field when appropriate Fix #81222 r? ``@estebank``
This commit is contained in:
commit
853cfd462f
@ -1661,6 +1661,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
debug!("exp_found {:?} terr {:?}", exp_found, terr);
|
debug!("exp_found {:?} terr {:?}", exp_found, terr);
|
||||||
if let Some(exp_found) = exp_found {
|
if let Some(exp_found) = exp_found {
|
||||||
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
|
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
|
||||||
|
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
|
||||||
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
|
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1819,6 +1820,53 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn suggest_accessing_field_where_appropriate(
|
||||||
|
&self,
|
||||||
|
cause: &ObligationCause<'tcx>,
|
||||||
|
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
|
||||||
|
diag: &mut DiagnosticBuilder<'tcx>,
|
||||||
|
) {
|
||||||
|
debug!(
|
||||||
|
"suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
|
||||||
|
cause, exp_found
|
||||||
|
);
|
||||||
|
if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() {
|
||||||
|
if expected_def.is_enum() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((name, ty)) = expected_def
|
||||||
|
.non_enum_variant()
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
|
||||||
|
.map(|field| (field.ident.name, field.ty(self.tcx, expected_substs)))
|
||||||
|
.find(|(_, ty)| ty::TyS::same_type(ty, exp_found.found))
|
||||||
|
{
|
||||||
|
if let ObligationCauseCode::Pattern { span: Some(span), .. } = cause.code {
|
||||||
|
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||||
|
let suggestion = if expected_def.is_struct() {
|
||||||
|
format!("{}.{}", snippet, name)
|
||||||
|
} else if expected_def.is_union() {
|
||||||
|
format!("unsafe {{ {}.{} }}", snippet, name)
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
diag.span_suggestion(
|
||||||
|
span,
|
||||||
|
&format!(
|
||||||
|
"you might have meant to use field `{}` of type `{}`",
|
||||||
|
name, ty
|
||||||
|
),
|
||||||
|
suggestion,
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
|
/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
|
||||||
/// suggests it.
|
/// suggests it.
|
||||||
fn suggest_as_ref_where_appropriate(
|
fn suggest_as_ref_where_appropriate(
|
||||||
|
35
src/test/ui/suggestions/field-access.fixed
Normal file
35
src/test/ui/suggestions/field-access.fixed
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// run-rustfix
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
b: B,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum B {
|
||||||
|
Fst,
|
||||||
|
Snd,
|
||||||
|
}
|
||||||
|
|
||||||
|
union Foo {
|
||||||
|
bar: u32,
|
||||||
|
qux: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = A { b: B::Fst };
|
||||||
|
if let B::Fst = a.b {}; //~ ERROR mismatched types [E0308]
|
||||||
|
//~^ HELP you might have meant to use field `b` of type `B`
|
||||||
|
match a.b {
|
||||||
|
//~^ HELP you might have meant to use field `b` of type `B`
|
||||||
|
//~| HELP you might have meant to use field `b` of type `B`
|
||||||
|
B::Fst => (), //~ ERROR mismatched types [E0308]
|
||||||
|
B::Snd => (), //~ ERROR mismatched types [E0308]
|
||||||
|
}
|
||||||
|
|
||||||
|
let foo = Foo { bar: 42 };
|
||||||
|
match unsafe { foo.bar } {
|
||||||
|
//~^ HELP you might have meant to use field `bar` of type `u32`
|
||||||
|
1u32 => (), //~ ERROR mismatched types [E0308]
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
35
src/test/ui/suggestions/field-access.rs
Normal file
35
src/test/ui/suggestions/field-access.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// run-rustfix
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
b: B,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum B {
|
||||||
|
Fst,
|
||||||
|
Snd,
|
||||||
|
}
|
||||||
|
|
||||||
|
union Foo {
|
||||||
|
bar: u32,
|
||||||
|
qux: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = A { b: B::Fst };
|
||||||
|
if let B::Fst = a {}; //~ ERROR mismatched types [E0308]
|
||||||
|
//~^ HELP you might have meant to use field `b` of type `B`
|
||||||
|
match a {
|
||||||
|
//~^ HELP you might have meant to use field `b` of type `B`
|
||||||
|
//~| HELP you might have meant to use field `b` of type `B`
|
||||||
|
B::Fst => (), //~ ERROR mismatched types [E0308]
|
||||||
|
B::Snd => (), //~ ERROR mismatched types [E0308]
|
||||||
|
}
|
||||||
|
|
||||||
|
let foo = Foo { bar: 42 };
|
||||||
|
match foo {
|
||||||
|
//~^ HELP you might have meant to use field `bar` of type `u32`
|
||||||
|
1u32 => (), //~ ERROR mismatched types [E0308]
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
67
src/test/ui/suggestions/field-access.stderr
Normal file
67
src/test/ui/suggestions/field-access.stderr
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/field-access.rs:20:12
|
||||||
|
|
|
||||||
|
LL | Fst,
|
||||||
|
| --- unit variant defined here
|
||||||
|
...
|
||||||
|
LL | if let B::Fst = a {};
|
||||||
|
| ^^^^^^ - this expression has type `A`
|
||||||
|
| |
|
||||||
|
| expected struct `A`, found enum `B`
|
||||||
|
|
|
||||||
|
help: you might have meant to use field `b` of type `B`
|
||||||
|
|
|
||||||
|
LL | if let B::Fst = a.b {};
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/field-access.rs:25:9
|
||||||
|
|
|
||||||
|
LL | Fst,
|
||||||
|
| --- unit variant defined here
|
||||||
|
...
|
||||||
|
LL | match a {
|
||||||
|
| - this expression has type `A`
|
||||||
|
...
|
||||||
|
LL | B::Fst => (),
|
||||||
|
| ^^^^^^ expected struct `A`, found enum `B`
|
||||||
|
|
|
||||||
|
help: you might have meant to use field `b` of type `B`
|
||||||
|
|
|
||||||
|
LL | match a.b {
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/field-access.rs:26:9
|
||||||
|
|
|
||||||
|
LL | Snd,
|
||||||
|
| --- unit variant defined here
|
||||||
|
...
|
||||||
|
LL | match a {
|
||||||
|
| - this expression has type `A`
|
||||||
|
...
|
||||||
|
LL | B::Snd => (),
|
||||||
|
| ^^^^^^ expected struct `A`, found enum `B`
|
||||||
|
|
|
||||||
|
help: you might have meant to use field `b` of type `B`
|
||||||
|
|
|
||||||
|
LL | match a.b {
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/field-access.rs:32:9
|
||||||
|
|
|
||||||
|
LL | match foo {
|
||||||
|
| --- this expression has type `Foo`
|
||||||
|
LL |
|
||||||
|
LL | 1u32 => (),
|
||||||
|
| ^^^^ expected union `Foo`, found `u32`
|
||||||
|
|
|
||||||
|
help: you might have meant to use field `bar` of type `u32`
|
||||||
|
|
|
||||||
|
LL | match unsafe { foo.bar } {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user