Skip to content

Commit c094228

Browse files
committed
Tweak "field not found" suggestion when giving struct literal for tuple struct type
``` error[E0560]: struct `S` has no field named `x` --> $DIR/nested-non-tuple-tuple-struct.rs:8:19 | LL | pub struct S(f32, f32); | - `S` defined here ... LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); | ^ field does not exist | help: `S` is a tuple struct, use the appropriate syntax | LL | let _x = (S(/* f32 */, /* f32 */), S { x: 3.0, y: 4.0 }); | ~~~~~~~~~~~~~~~~~~~~~~~ ```
1 parent 952ab57 commit c094228

File tree

6 files changed

+53
-37
lines changed

6 files changed

+53
-37
lines changed

compiler/rustc_hir_typeck/src/expr.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -2218,8 +2218,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22182218
);
22192219

22202220
let variant_ident_span = self.tcx.def_ident_span(variant.def_id).unwrap();
2221-
match variant.ctor_kind() {
2222-
Some(CtorKind::Fn) => match ty.kind() {
2221+
match variant.ctor {
2222+
Some((CtorKind::Fn, def_id)) => match ty.kind() {
22232223
ty::Adt(adt, ..) if adt.is_enum() => {
22242224
err.span_label(
22252225
variant_ident_span,
@@ -2230,28 +2230,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22302230
),
22312231
);
22322232
err.span_label(field.ident.span, "field does not exist");
2233+
let fn_sig = self.tcx.fn_sig(def_id).instantiate_identity();
2234+
let inputs = fn_sig.inputs().skip_binder();
2235+
let fields = format!(
2236+
"({})",
2237+
inputs.iter().map(|i| format!("/* {i} */")).collect::<Vec<_>>().join(", ")
2238+
);
2239+
let (replace_span, sugg) = match expr.kind {
2240+
hir::ExprKind::Struct(qpath, ..) => {
2241+
(qpath.span().shrink_to_hi().with_hi(expr.span.hi()), fields)
2242+
}
2243+
_ => {
2244+
(expr.span, format!("{ty}::{variant}{fields}", variant = variant.name))
2245+
}
2246+
};
22332247
err.span_suggestion_verbose(
2234-
expr.span,
2248+
replace_span,
22352249
format!(
22362250
"`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
22372251
adt = ty,
22382252
variant = variant.name,
22392253
),
2240-
format!(
2241-
"{adt}::{variant}(/* fields */)",
2242-
adt = ty,
2243-
variant = variant.name,
2244-
),
2254+
sugg,
22452255
Applicability::HasPlaceholders,
22462256
);
22472257
}
22482258
_ => {
22492259
err.span_label(variant_ident_span, format!("`{ty}` defined here"));
22502260
err.span_label(field.ident.span, "field does not exist");
2261+
let fn_sig = self.tcx.fn_sig(def_id).instantiate_identity();
2262+
let inputs = fn_sig.inputs().skip_binder();
2263+
let fields = format!(
2264+
"({})",
2265+
inputs.iter().map(|i| format!("/* {i} */")).collect::<Vec<_>>().join(", ")
2266+
);
22512267
err.span_suggestion_verbose(
22522268
expr.span,
22532269
format!("`{ty}` is a tuple {kind_name}, use the appropriate syntax",),
2254-
format!("{ty}(/* fields */)"),
2270+
format!("{ty}{fields}"),
22552271
Applicability::HasPlaceholders,
22562272
);
22572273
}

tests/ui/issues/issue-4736.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ LL | let z = NonCopyable{ p: () };
99
|
1010
help: `NonCopyable` is a tuple struct, use the appropriate syntax
1111
|
12-
LL | let z = NonCopyable(/* fields */);
13-
| ~~~~~~~~~~~~~~~~~~~~~~~~~
12+
LL | let z = NonCopyable(/* () */);
13+
| ~~~~~~~~~~~~~~~~~~~~~
1414

1515
error: aborting due to 1 previous error
1616

tests/ui/issues/issue-80607.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ LL | Enum::V1 { x }
99
|
1010
help: `Enum::V1` is a tuple variant, use the appropriate syntax
1111
|
12-
LL | Enum::V1(/* fields */)
13-
| ~~~~~~~~~~~~~~~~~~~~~~
12+
LL | Enum::V1(/* i32 */)
13+
| ~~~~~~~~~~~
1414

1515
error: aborting due to 1 previous error
1616

tests/ui/numeric/numeric-fields.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ LL | let s = S{0b1: 10, 0: 11};
99
|
1010
help: `S` is a tuple struct, use the appropriate syntax
1111
|
12-
LL | let s = S(/* fields */);
13-
| ~~~~~~~~~~~~~~~
12+
LL | let s = S(/* u8 */, /* u16 */);
13+
| ~~~~~~~~~~~~~~~~~~~~~~
1414

1515
error[E0026]: struct `S` does not have a field named `0x1`
1616
--> $DIR/numeric-fields.rs:7:17

tests/ui/suggestions/incorrect-variant-literal.svg

+6-6
Loading

tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr

+16-16
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
99
|
1010
help: `S` is a tuple struct, use the appropriate syntax
1111
|
12-
LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
13-
| ~~~~~~~~~~~~~~~
12+
LL | let _x = (S(/* f32 */, /* f32 */), S { x: 3.0, y: 4.0 });
13+
| ~~~~~~~~~~~~~~~~~~~~~~~
1414

1515
error[E0560]: struct `S` has no field named `y`
1616
--> $DIR/nested-non-tuple-tuple-struct.rs:8:27
@@ -23,8 +23,8 @@ LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
2323
|
2424
help: `S` is a tuple struct, use the appropriate syntax
2525
|
26-
LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
27-
| ~~~~~~~~~~~~~~~
26+
LL | let _x = (S(/* f32 */, /* f32 */), S { x: 3.0, y: 4.0 });
27+
| ~~~~~~~~~~~~~~~~~~~~~~~
2828

2929
error[E0560]: struct `S` has no field named `x`
3030
--> $DIR/nested-non-tuple-tuple-struct.rs:8:41
@@ -37,8 +37,8 @@ LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
3737
|
3838
help: `S` is a tuple struct, use the appropriate syntax
3939
|
40-
LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
41-
| ~~~~~~~~~~~~~~~
40+
LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* f32 */, /* f32 */));
41+
| ~~~~~~~~~~~~~~~~~~~~~~~
4242

4343
error[E0560]: struct `S` has no field named `y`
4444
--> $DIR/nested-non-tuple-tuple-struct.rs:8:49
@@ -51,8 +51,8 @@ LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
5151
|
5252
help: `S` is a tuple struct, use the appropriate syntax
5353
|
54-
LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
55-
| ~~~~~~~~~~~~~~~
54+
LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* f32 */, /* f32 */));
55+
| ~~~~~~~~~~~~~~~~~~~~~~~
5656

5757
error[E0559]: variant `E::V` has no field named `x`
5858
--> $DIR/nested-non-tuple-tuple-struct.rs:13:22
@@ -65,8 +65,8 @@ LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
6565
|
6666
help: `E::V` is a tuple variant, use the appropriate syntax
6767
|
68-
LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
69-
| ~~~~~~~~~~~~~~~~~~
68+
LL | let _y = (E::V(/* f32 */, /* f32 */), E::V { x: 3.0, y: 4.0 });
69+
| ~~~~~~~~~~~~~~~~~~~~~~
7070

7171
error[E0559]: variant `E::V` has no field named `y`
7272
--> $DIR/nested-non-tuple-tuple-struct.rs:13:30
@@ -79,8 +79,8 @@ LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
7979
|
8080
help: `E::V` is a tuple variant, use the appropriate syntax
8181
|
82-
LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
83-
| ~~~~~~~~~~~~~~~~~~
82+
LL | let _y = (E::V(/* f32 */, /* f32 */), E::V { x: 3.0, y: 4.0 });
83+
| ~~~~~~~~~~~~~~~~~~~~~~
8484

8585
error[E0559]: variant `E::V` has no field named `x`
8686
--> $DIR/nested-non-tuple-tuple-struct.rs:13:47
@@ -93,8 +93,8 @@ LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
9393
|
9494
help: `E::V` is a tuple variant, use the appropriate syntax
9595
|
96-
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
97-
| ~~~~~~~~~~~~~~~~~~
96+
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* f32 */, /* f32 */));
97+
| ~~~~~~~~~~~~~~~~~~~~~~
9898

9999
error[E0559]: variant `E::V` has no field named `y`
100100
--> $DIR/nested-non-tuple-tuple-struct.rs:13:55
@@ -107,8 +107,8 @@ LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
107107
|
108108
help: `E::V` is a tuple variant, use the appropriate syntax
109109
|
110-
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
111-
| ~~~~~~~~~~~~~~~~~~
110+
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* f32 */, /* f32 */));
111+
| ~~~~~~~~~~~~~~~~~~~~~~
112112

113113
error: aborting due to 8 previous errors
114114

0 commit comments

Comments
 (0)