Skip to content

Commit d2b13ba

Browse files
committed
Fix span used for structured tuple struct suggestion
(And same for tuple variants.) 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.
1 parent 50171c3 commit d2b13ba

File tree

6 files changed

+135
-10
lines changed

6 files changed

+135
-10
lines changed

compiler/rustc_typeck/src/check/expr.rs

+8-4
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();
@@ -1511,7 +1515,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15111515
);
15121516
err.span_label(field.ident.span, "field does not exist");
15131517
err.span_suggestion(
1514-
ty_span,
1518+
expr_span,
15151519
&format!(
15161520
"`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
15171521
adt = ty,
@@ -1529,7 +1533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15291533
err.span_label(variant.ident.span, format!("`{adt}` defined here", adt = ty));
15301534
err.span_label(field.ident.span, "field does not exist");
15311535
err.span_suggestion(
1532-
ty_span,
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

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

1213
error: aborting due to previous error

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

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

1213
error: aborting due to previous error

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ 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-
| |
8+
| --^^^------------
9+
| | |
10+
| | field does not exist
1011
| help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)`
1112

1213
error[E0026]: struct `S` does not have a field named `0x1`
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,100 @@
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+
| ----^---------------
9+
| | |
10+
| | field does not exist
11+
| help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)`
12+
13+
error[E0560]: struct `S` has no field named `y`
14+
--> $DIR/nested-non-tuple-tuple-struct.rs:8:27
15+
|
16+
LL | pub struct S(f32, f32);
17+
| - `S` defined here
18+
...
19+
LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
20+
| ------------^-------
21+
| | |
22+
| | field does not exist
23+
| help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)`
24+
25+
error[E0560]: struct `S` has no field named `x`
26+
--> $DIR/nested-non-tuple-tuple-struct.rs:8:41
27+
|
28+
LL | pub struct S(f32, f32);
29+
| - `S` defined here
30+
...
31+
LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
32+
| ----^---------------
33+
| | |
34+
| | field does not exist
35+
| help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)`
36+
37+
error[E0560]: struct `S` has no field named `y`
38+
--> $DIR/nested-non-tuple-tuple-struct.rs:8:49
39+
|
40+
LL | pub struct S(f32, f32);
41+
| - `S` defined here
42+
...
43+
LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
44+
| ------------^-------
45+
| | |
46+
| | field does not exist
47+
| help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)`
48+
49+
error[E0559]: variant `E::V` has no field named `x`
50+
--> $DIR/nested-non-tuple-tuple-struct.rs:13:22
51+
|
52+
LL | V(f32, f32),
53+
| - `E::V` defined here
54+
...
55+
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
56+
| -------^---------------
57+
| | |
58+
| | field does not exist
59+
| help: `E::V` is a tuple variant, use the appropriate syntax: `E::V(/* fields */)`
60+
61+
error[E0559]: variant `E::V` has no field named `y`
62+
--> $DIR/nested-non-tuple-tuple-struct.rs:13:30
63+
|
64+
LL | V(f32, f32),
65+
| - `E::V` defined here
66+
...
67+
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
68+
| ---------------^-------
69+
| | |
70+
| | field does not exist
71+
| help: `E::V` is a tuple variant, use the appropriate syntax: `E::V(/* fields */)`
72+
73+
error[E0559]: variant `E::V` has no field named `x`
74+
--> $DIR/nested-non-tuple-tuple-struct.rs:13:47
75+
|
76+
LL | V(f32, f32),
77+
| - `E::V` defined here
78+
...
79+
LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
80+
| -------^---------------
81+
| | |
82+
| | field does not exist
83+
| help: `E::V` is a tuple variant, use the appropriate syntax: `E::V(/* fields */)`
84+
85+
error[E0559]: variant `E::V` has no field named `y`
86+
--> $DIR/nested-non-tuple-tuple-struct.rs:13:55
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+
| ---------------^-------
93+
| | |
94+
| | field does not exist
95+
| help: `E::V` is a tuple variant, use the appropriate syntax: `E::V(/* fields */)`
96+
97+
error: aborting due to 8 previous errors
98+
99+
Some errors have detailed explanations: E0559, E0560.
100+
For more information about an error, try `rustc --explain E0559`.

0 commit comments

Comments
 (0)