Skip to content

Commit 853cfd4

Browse files
Rollup merge of #81504 - matsujika:suggestion-field-access, r=estebank
Suggest accessing field when appropriate Fix #81222 r? ``@estebank``
2 parents 9e8753e + f45a993 commit 853cfd4

File tree

4 files changed

+185
-0
lines changed

4 files changed

+185
-0
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+48
Original file line numberDiff line numberDiff line change
@@ -1661,6 +1661,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16611661
debug!("exp_found {:?} terr {:?}", exp_found, terr);
16621662
if let Some(exp_found) = exp_found {
16631663
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
1664+
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
16641665
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
16651666
}
16661667

@@ -1819,6 +1820,53 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
18191820
}
18201821
}
18211822

1823+
fn suggest_accessing_field_where_appropriate(
1824+
&self,
1825+
cause: &ObligationCause<'tcx>,
1826+
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
1827+
diag: &mut DiagnosticBuilder<'tcx>,
1828+
) {
1829+
debug!(
1830+
"suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
1831+
cause, exp_found
1832+
);
1833+
if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() {
1834+
if expected_def.is_enum() {
1835+
return;
1836+
}
1837+
1838+
if let Some((name, ty)) = expected_def
1839+
.non_enum_variant()
1840+
.fields
1841+
.iter()
1842+
.filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
1843+
.map(|field| (field.ident.name, field.ty(self.tcx, expected_substs)))
1844+
.find(|(_, ty)| ty::TyS::same_type(ty, exp_found.found))
1845+
{
1846+
if let ObligationCauseCode::Pattern { span: Some(span), .. } = cause.code {
1847+
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
1848+
let suggestion = if expected_def.is_struct() {
1849+
format!("{}.{}", snippet, name)
1850+
} else if expected_def.is_union() {
1851+
format!("unsafe {{ {}.{} }}", snippet, name)
1852+
} else {
1853+
return;
1854+
};
1855+
diag.span_suggestion(
1856+
span,
1857+
&format!(
1858+
"you might have meant to use field `{}` of type `{}`",
1859+
name, ty
1860+
),
1861+
suggestion,
1862+
Applicability::MaybeIncorrect,
1863+
);
1864+
}
1865+
}
1866+
}
1867+
}
1868+
}
1869+
18221870
/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
18231871
/// suggests it.
18241872
fn suggest_as_ref_where_appropriate(
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
4+
struct A {
5+
b: B,
6+
}
7+
8+
enum B {
9+
Fst,
10+
Snd,
11+
}
12+
13+
union Foo {
14+
bar: u32,
15+
qux: f32,
16+
}
17+
18+
fn main() {
19+
let a = A { b: B::Fst };
20+
if let B::Fst = a.b {}; //~ ERROR mismatched types [E0308]
21+
//~^ HELP you might have meant to use field `b` of type `B`
22+
match a.b {
23+
//~^ HELP you might have meant to use field `b` of type `B`
24+
//~| HELP you might have meant to use field `b` of type `B`
25+
B::Fst => (), //~ ERROR mismatched types [E0308]
26+
B::Snd => (), //~ ERROR mismatched types [E0308]
27+
}
28+
29+
let foo = Foo { bar: 42 };
30+
match unsafe { foo.bar } {
31+
//~^ HELP you might have meant to use field `bar` of type `u32`
32+
1u32 => (), //~ ERROR mismatched types [E0308]
33+
_ => (),
34+
}
35+
}
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
4+
struct A {
5+
b: B,
6+
}
7+
8+
enum B {
9+
Fst,
10+
Snd,
11+
}
12+
13+
union Foo {
14+
bar: u32,
15+
qux: f32,
16+
}
17+
18+
fn main() {
19+
let a = A { b: B::Fst };
20+
if let B::Fst = a {}; //~ ERROR mismatched types [E0308]
21+
//~^ HELP you might have meant to use field `b` of type `B`
22+
match a {
23+
//~^ HELP you might have meant to use field `b` of type `B`
24+
//~| HELP you might have meant to use field `b` of type `B`
25+
B::Fst => (), //~ ERROR mismatched types [E0308]
26+
B::Snd => (), //~ ERROR mismatched types [E0308]
27+
}
28+
29+
let foo = Foo { bar: 42 };
30+
match foo {
31+
//~^ HELP you might have meant to use field `bar` of type `u32`
32+
1u32 => (), //~ ERROR mismatched types [E0308]
33+
_ => (),
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/field-access.rs:20:12
3+
|
4+
LL | Fst,
5+
| --- unit variant defined here
6+
...
7+
LL | if let B::Fst = a {};
8+
| ^^^^^^ - this expression has type `A`
9+
| |
10+
| expected struct `A`, found enum `B`
11+
|
12+
help: you might have meant to use field `b` of type `B`
13+
|
14+
LL | if let B::Fst = a.b {};
15+
| ^^^
16+
17+
error[E0308]: mismatched types
18+
--> $DIR/field-access.rs:25:9
19+
|
20+
LL | Fst,
21+
| --- unit variant defined here
22+
...
23+
LL | match a {
24+
| - this expression has type `A`
25+
...
26+
LL | B::Fst => (),
27+
| ^^^^^^ expected struct `A`, found enum `B`
28+
|
29+
help: you might have meant to use field `b` of type `B`
30+
|
31+
LL | match a.b {
32+
| ^^^
33+
34+
error[E0308]: mismatched types
35+
--> $DIR/field-access.rs:26:9
36+
|
37+
LL | Snd,
38+
| --- unit variant defined here
39+
...
40+
LL | match a {
41+
| - this expression has type `A`
42+
...
43+
LL | B::Snd => (),
44+
| ^^^^^^ expected struct `A`, found enum `B`
45+
|
46+
help: you might have meant to use field `b` of type `B`
47+
|
48+
LL | match a.b {
49+
| ^^^
50+
51+
error[E0308]: mismatched types
52+
--> $DIR/field-access.rs:32:9
53+
|
54+
LL | match foo {
55+
| --- this expression has type `Foo`
56+
LL |
57+
LL | 1u32 => (),
58+
| ^^^^ expected union `Foo`, found `u32`
59+
|
60+
help: you might have meant to use field `bar` of type `u32`
61+
|
62+
LL | match unsafe { foo.bar } {
63+
| ^^^^^^^^^^^^^^^^^^
64+
65+
error: aborting due to 4 previous errors
66+
67+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)