Skip to content

Commit d19d864

Browse files
committed
Auto merge of rust-lang#88631 - camelid:sugg-span, r=davidtwco
Improve structured tuple struct suggestion Previously, the span was just for the constructor name, which meant it would result in syntactically-invalid code when applied. Now, the span is for the entire expression. I also changed it to use `span_suggestion_verbose`, for two reasons: 1. Now that the suggestion span has been corrected, the output is a bit cluttered and hard to read. Putting the suggestion its own window creates more space. 2. It's easier to see what's being suggested, since now the version after the suggestion is applied is shown. r? `@davidtwco`
2 parents b2d9bcd + 2226977 commit d19d864

File tree

6 files changed

+162
-15
lines changed

6 files changed

+162
-15
lines changed

compiler/rustc_typeck/src/check/expr.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12361236
variant,
12371237
fields,
12381238
base_expr.is_none(),
1239+
expr.span,
12391240
);
12401241
if let Some(base_expr) = base_expr {
12411242
// If check_expr_struct_fields hit an error, do not attempt to populate
@@ -1283,6 +1284,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12831284
variant: &'tcx ty::VariantDef,
12841285
ast_fields: &'tcx [hir::ExprField<'tcx>],
12851286
check_completeness: bool,
1287+
expr_span: Span,
12861288
) -> bool {
12871289
let tcx = self.tcx;
12881290

@@ -1334,7 +1336,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13341336
ident,
13351337
});
13361338
} else {
1337-
self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name, span);
1339+
self.report_unknown_field(
1340+
adt_ty, variant, field, ast_fields, kind_name, expr_span,
1341+
);
13381342
}
13391343

13401344
tcx.ty_error()
@@ -1467,7 +1471,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14671471
field: &hir::ExprField<'_>,
14681472
skip_fields: &[hir::ExprField<'_>],
14691473
kind_name: &str,
1470-
ty_span: Span,
1474+
expr_span: Span,
14711475
) {
14721476
if variant.is_recovered() {
14731477
self.set_tainted_by_errors();
@@ -1510,8 +1514,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15101514
),
15111515
);
15121516
err.span_label(field.ident.span, "field does not exist");
1513-
err.span_suggestion(
1514-
ty_span,
1517+
err.span_suggestion_verbose(
1518+
expr_span,
15151519
&format!(
15161520
"`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
15171521
adt = ty,
@@ -1528,8 +1532,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15281532
_ => {
15291533
err.span_label(variant.ident.span, format!("`{adt}` defined here", adt = ty));
15301534
err.span_label(field.ident.span, "field does not exist");
1531-
err.span_suggestion(
1532-
ty_span,
1535+
err.span_suggestion_verbose(
1536+
expr_span,
15331537
&format!(
15341538
"`{adt}` is a tuple {kind_name}, use the appropriate syntax",
15351539
adt = ty,

src/test/ui/issues/issue-4736.stderr

+6-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ LL | struct NonCopyable(());
55
| ----------- `NonCopyable` defined here
66
...
77
LL | let z = NonCopyable{ p: () };
8-
| ----------- ^ field does not exist
9-
| |
10-
| help: `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)`
8+
| ^ field does not exist
9+
|
10+
help: `NonCopyable` is a tuple struct, use the appropriate syntax
11+
|
12+
LL | let z = NonCopyable(/* fields */);
13+
| ~~~~~~~~~~~~~~~~~~~~~~~~~
1114

1215
error: aborting due to previous error
1316

src/test/ui/issues/issue-80607.stderr

+6-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ LL | V1(i32),
55
| -- `Enum::V1` defined here
66
...
77
LL | Enum::V1 { x }
8-
| -------- ^ field does not exist
9-
| |
10-
| help: `Enum::V1` is a tuple variant, use the appropriate syntax: `Enum::V1(/* fields */)`
8+
| ^ field does not exist
9+
|
10+
help: `Enum::V1` is a tuple variant, use the appropriate syntax
11+
|
12+
LL | Enum::V1(/* fields */)
13+
| ~~~~~~~~~~~~~~~~~~~~~~
1114

1215
error: aborting due to previous error
1316

src/test/ui/numeric/numeric-fields.stderr

+6-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ LL | struct S(u8, u16);
55
| - `S` defined here
66
...
77
LL | let s = S{0b1: 10, 0: 11};
8-
| - ^^^ field does not exist
9-
| |
10-
| help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)`
8+
| ^^^ field does not exist
9+
|
10+
help: `S` is a tuple struct, use the appropriate syntax
11+
|
12+
LL | let s = S(/* fields */);
13+
| ~~~~~~~~~~~~~~~
1114

1215
error[E0026]: struct `S` does not have a field named `0x1`
1316
--> $DIR/numeric-fields.rs:7:17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
pub struct S(f32, f32);
2+
3+
pub enum E {
4+
V(f32, f32),
5+
}
6+
7+
fn main() {
8+
let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
9+
//~^ ERROR struct `S` has no field named `x`
10+
//~| ERROR struct `S` has no field named `y`
11+
//~| ERROR struct `S` has no field named `x`
12+
//~| ERROR struct `S` has no field named `y`
13+
let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
14+
//~^ ERROR variant `E::V` has no field named `x`
15+
//~| ERROR variant `E::V` has no field named `y`
16+
//~| ERROR variant `E::V` has no field named `x`
17+
//~| ERROR variant `E::V` has no field named `y`
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
error[E0560]: struct `S` has no field named `x`
2+
--> $DIR/nested-non-tuple-tuple-struct.rs:8:19
3+
|
4+
LL | pub struct S(f32, f32);
5+
| - `S` defined here
6+
...
7+
LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
8+
| ^ field does not exist
9+
|
10+
help: `S` is a tuple struct, use the appropriate syntax
11+
|
12+
LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
13+
| ~~~~~~~~~~~~~~~
14+
15+
error[E0560]: struct `S` has no field named `y`
16+
--> $DIR/nested-non-tuple-tuple-struct.rs:8:27
17+
|
18+
LL | pub struct S(f32, f32);
19+
| - `S` defined here
20+
...
21+
LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
22+
| ^ field does not exist
23+
|
24+
help: `S` is a tuple struct, use the appropriate syntax
25+
|
26+
LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
27+
| ~~~~~~~~~~~~~~~
28+
29+
error[E0560]: struct `S` has no field named `x`
30+
--> $DIR/nested-non-tuple-tuple-struct.rs:8:41
31+
|
32+
LL | pub struct S(f32, f32);
33+
| - `S` defined here
34+
...
35+
LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
36+
| ^ field does not exist
37+
|
38+
help: `S` is a tuple struct, use the appropriate syntax
39+
|
40+
LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
41+
| ~~~~~~~~~~~~~~~
42+
43+
error[E0560]: struct `S` has no field named `y`
44+
--> $DIR/nested-non-tuple-tuple-struct.rs:8:49
45+
|
46+
LL | pub struct S(f32, f32);
47+
| - `S` defined here
48+
...
49+
LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
50+
| ^ field does not exist
51+
|
52+
help: `S` is a tuple struct, use the appropriate syntax
53+
|
54+
LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
55+
| ~~~~~~~~~~~~~~~
56+
57+
error[E0559]: variant `E::V` has no field named `x`
58+
--> $DIR/nested-non-tuple-tuple-struct.rs:13:22
59+
|
60+
LL | V(f32, f32),
61+
| - `E::V` defined here
62+
...
63+
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
64+
| ^ field does not exist
65+
|
66+
help: `E::V` is a tuple variant, use the appropriate syntax
67+
|
68+
LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
69+
| ~~~~~~~~~~~~~~~~~~
70+
71+
error[E0559]: variant `E::V` has no field named `y`
72+
--> $DIR/nested-non-tuple-tuple-struct.rs:13:30
73+
|
74+
LL | V(f32, f32),
75+
| - `E::V` defined here
76+
...
77+
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
78+
| ^ field does not exist
79+
|
80+
help: `E::V` is a tuple variant, use the appropriate syntax
81+
|
82+
LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
83+
| ~~~~~~~~~~~~~~~~~~
84+
85+
error[E0559]: variant `E::V` has no field named `x`
86+
--> $DIR/nested-non-tuple-tuple-struct.rs:13:47
87+
|
88+
LL | V(f32, f32),
89+
| - `E::V` defined here
90+
...
91+
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
92+
| ^ field does not exist
93+
|
94+
help: `E::V` is a tuple variant, use the appropriate syntax
95+
|
96+
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
97+
| ~~~~~~~~~~~~~~~~~~
98+
99+
error[E0559]: variant `E::V` has no field named `y`
100+
--> $DIR/nested-non-tuple-tuple-struct.rs:13:55
101+
|
102+
LL | V(f32, f32),
103+
| - `E::V` defined here
104+
...
105+
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
106+
| ^ field does not exist
107+
|
108+
help: `E::V` is a tuple variant, use the appropriate syntax
109+
|
110+
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
111+
| ~~~~~~~~~~~~~~~~~~
112+
113+
error: aborting due to 8 previous errors
114+
115+
Some errors have detailed explanations: E0559, E0560.
116+
For more information about an error, try `rustc --explain E0559`.

0 commit comments

Comments
 (0)