Skip to content

Commit 4d69cef

Browse files
committed
Expand tuple-index-suffix test coverage
Actually, the accidentally accepted invalid suffixes also include tuple struct indexing positions, struct numeral field name positions. So before changing anything, first expand test coverage, so we can observe the effect of bumping the non-lint pseudo-FCW warning into a hard error.
1 parent 7609ff5 commit 4d69cef

File tree

2 files changed

+234
-19
lines changed

2 files changed

+234
-19
lines changed
Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,89 @@
1+
//! Check that we hard error on invalid suffixes in tuple indexing subexpressions and struct numeral
2+
//! field names, modulo carve-outs for `{i,u}{32,usize}` at warning level to mitigate ecosystem
3+
//! impact.
4+
//!
5+
//! # History of this invalid tuple index suffix situation
6+
//!
7+
//! - Since Rust 1.27, the compiler accidentally accepted `foo.0_u32` and other suffixes when
8+
//! indexing into tuples (only `foo.0` is intended valid syntax). See #59418.
9+
//! - The obviously wrong cases were rejected in #59421.
10+
//! - However, ecosystem procedural macros had accepted literals in tuple indexing expression
11+
//! positions, prompting a carve-out to accept `{i,u}{32,usize}` suffixes as a short-term
12+
//! mitigation. This was implemented in #60186.
13+
//! - The intention was for this to be a short-term warning (pseudo-FCW) to allow the ecosystem to
14+
//! have some time to fix, then make any such suffixes a hard error in future Rust releases.
15+
//! - This is a *pseudo* FCW, because it's implemented as a non-lint warning whose message tries to
16+
//! emulate the wording of proper FCW lints. This is due to not being able to distinguish the span
17+
//! of the valid numeral part vs invalid suffix part when it comes from a proc macro.
18+
119
struct X(i32,i32,i32);
220

321
fn main() {
4-
let a = X(1, 2, 3);
5-
let b = a.1suffix;
22+
let tup_struct = X(1, 2, 3);
23+
let invalid_tup_struct_suffix = tup_struct.0suffix;
624
//~^ ERROR suffixes on a tuple index are invalid
7-
println!("{}", b);
8-
let c = (1, 2, 3);
9-
let d = c.1suffix;
25+
let carve_out_tup_struct_suffix = tup_struct.0i32;
26+
//~^ WARN suffixes on a tuple index are invalid
27+
28+
let tup = (1, 2, 3);
29+
let invalid_tup_suffix = tup.0suffix;
1030
//~^ ERROR suffixes on a tuple index are invalid
11-
println!("{}", d);
12-
let s = X { 0suffix: 0, 1: 1, 2: 2 };
31+
let carve_out_tup_suffix = tup.0u32;
32+
//~^ WARN suffixes on a tuple index are invalid
33+
34+
numeral_struct_field_name_suffix_invalid();
35+
numeral_struct_field_name_suffix_carve_out();
36+
}
37+
38+
// Very limited carve outs as a ecosystem impact mitigation implemented in #60186. *Only*
39+
// `{i,u}{32,usize}` suffixes are temporarily accepted.
40+
fn carve_outs() {
41+
// Ok, only pseudo-FCW warnings.
42+
43+
let carve_out_i32 = (42,).0i32; //~ WARN suffixes on a tuple index are invalid
44+
let carve_out_i32 = (42,).0u32; //~ WARN suffixes on a tuple index are invalid
45+
let carve_out_isize = (42,).0isize; //~ WARN suffixes on a tuple index are invalid
46+
let carve_out_usize = (42,).0usize; //~ WARN suffixes on a tuple index are invalid
47+
48+
// Not part of the carve outs!
49+
let error_i8 = (42,).0i8; //~ ERROR suffixes on a tuple index are invalid
50+
let error_u8 = (42,).0u8; //~ ERROR suffixes on a tuple index are invalid
51+
let error_i16 = (42,).0i16; //~ ERROR suffixes on a tuple index are invalid
52+
let error_u16 = (42,).0u16; //~ ERROR suffixes on a tuple index are invalid
53+
let error_i64 = (42,).0i64; //~ ERROR suffixes on a tuple index are invalid
54+
let error_u64 = (42,).0u64; //~ ERROR suffixes on a tuple index are invalid
55+
let error_i128 = (42,).0i128; //~ ERROR suffixes on a tuple index are invalid
56+
let error_u128 = (42,).0u128; //~ ERROR suffixes on a tuple index are invalid
57+
}
58+
59+
fn numeral_struct_field_name_suffix_invalid() {
60+
let invalid_struct_name = X { 0suffix: 0, 1: 1, 2: 2 };
1361
//~^ ERROR suffixes on a tuple index are invalid
14-
match s {
62+
match invalid_struct_name {
1563
X { 0suffix: _, .. } => {}
1664
//~^ ERROR suffixes on a tuple index are invalid
1765
}
1866
}
67+
68+
fn numeral_struct_field_name_suffix_carve_out() {
69+
let carve_out_struct_name = X { 0u32: 0, 1: 1, 2: 2 };
70+
//~^ WARN suffixes on a tuple index are invalid
71+
match carve_out_struct_name {
72+
X { 0u32: _, .. } => {}
73+
//~^ WARN suffixes on a tuple index are invalid
74+
}
75+
}
76+
77+
// Unfortunately, it turns out `std::mem::offset_of!` uses the same expect suffix code path.
78+
fn offset_of_suffix() {
79+
#[repr(C)]
80+
pub struct Struct<T>(u8, T);
81+
82+
// Carve outs
83+
assert_eq!(std::mem::offset_of!(Struct<u32>, 0usize), 0);
84+
//~^ WARN suffixes on a tuple index are invalid
85+
86+
// Not part of carve outs
87+
assert_eq!(std::mem::offset_of!(Struct<u32>, 0u8), 0);
88+
//~^ ERROR suffixes on a tuple index are invalid
89+
}
Lines changed: 155 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,170 @@
11
error: suffixes on a tuple index are invalid
2-
--> $DIR/issue-59418.rs:5:15
2+
--> $DIR/tuple-index-suffix.rs:23:48
33
|
4-
LL | let b = a.1suffix;
5-
| ^^^^^^^ invalid suffix `suffix`
4+
LL | let invalid_tup_struct_suffix = tup_struct.0suffix;
5+
| ^^^^^^^ invalid suffix `suffix`
6+
7+
warning: suffixes on a tuple index are invalid
8+
--> $DIR/tuple-index-suffix.rs:25:50
9+
|
10+
LL | let carve_out_tup_struct_suffix = tup_struct.0i32;
11+
| ^^^^ invalid suffix `i32`
12+
|
13+
= help: `i32` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
14+
= help: on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
15+
= help: see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
16+
17+
error: suffixes on a tuple index are invalid
18+
--> $DIR/tuple-index-suffix.rs:29:34
19+
|
20+
LL | let invalid_tup_suffix = tup.0suffix;
21+
| ^^^^^^^ invalid suffix `suffix`
22+
23+
warning: suffixes on a tuple index are invalid
24+
--> $DIR/tuple-index-suffix.rs:31:36
25+
|
26+
LL | let carve_out_tup_suffix = tup.0u32;
27+
| ^^^^ invalid suffix `u32`
28+
|
29+
= help: `u32` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
30+
= help: on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
31+
= help: see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
32+
33+
warning: suffixes on a tuple index are invalid
34+
--> $DIR/tuple-index-suffix.rs:43:31
35+
|
36+
LL | let carve_out_i32 = (42,).0i32;
37+
| ^^^^ invalid suffix `i32`
38+
|
39+
= help: `i32` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
40+
= help: on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
41+
= help: see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
42+
43+
warning: suffixes on a tuple index are invalid
44+
--> $DIR/tuple-index-suffix.rs:44:31
45+
|
46+
LL | let carve_out_i32 = (42,).0u32;
47+
| ^^^^ invalid suffix `u32`
48+
|
49+
= help: `u32` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
50+
= help: on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
51+
= help: see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
52+
53+
warning: suffixes on a tuple index are invalid
54+
--> $DIR/tuple-index-suffix.rs:45:33
55+
|
56+
LL | let carve_out_isize = (42,).0isize;
57+
| ^^^^^^ invalid suffix `isize`
58+
|
59+
= help: `isize` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
60+
= help: on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
61+
= help: see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
62+
63+
warning: suffixes on a tuple index are invalid
64+
--> $DIR/tuple-index-suffix.rs:46:33
65+
|
66+
LL | let carve_out_usize = (42,).0usize;
67+
| ^^^^^^ invalid suffix `usize`
68+
|
69+
= help: `usize` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
70+
= help: on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
71+
= help: see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
72+
73+
error: suffixes on a tuple index are invalid
74+
--> $DIR/tuple-index-suffix.rs:49:26
75+
|
76+
LL | let error_i8 = (42,).0i8;
77+
| ^^^ invalid suffix `i8`
78+
79+
error: suffixes on a tuple index are invalid
80+
--> $DIR/tuple-index-suffix.rs:50:26
81+
|
82+
LL | let error_u8 = (42,).0u8;
83+
| ^^^ invalid suffix `u8`
684

785
error: suffixes on a tuple index are invalid
8-
--> $DIR/issue-59418.rs:9:15
86+
--> $DIR/tuple-index-suffix.rs:51:27
987
|
10-
LL | let d = c.1suffix;
11-
| ^^^^^^^ invalid suffix `suffix`
88+
LL | let error_i16 = (42,).0i16;
89+
| ^^^^ invalid suffix `i16`
1290

1391
error: suffixes on a tuple index are invalid
14-
--> $DIR/issue-59418.rs:12:17
92+
--> $DIR/tuple-index-suffix.rs:52:27
1593
|
16-
LL | let s = X { 0suffix: 0, 1: 1, 2: 2 };
17-
| ^^^^^^^ invalid suffix `suffix`
94+
LL | let error_u16 = (42,).0u16;
95+
| ^^^^ invalid suffix `u16`
1896

1997
error: suffixes on a tuple index are invalid
20-
--> $DIR/issue-59418.rs:15:13
98+
--> $DIR/tuple-index-suffix.rs:53:27
99+
|
100+
LL | let error_i64 = (42,).0i64;
101+
| ^^^^ invalid suffix `i64`
102+
103+
error: suffixes on a tuple index are invalid
104+
--> $DIR/tuple-index-suffix.rs:54:27
105+
|
106+
LL | let error_u64 = (42,).0u64;
107+
| ^^^^ invalid suffix `u64`
108+
109+
error: suffixes on a tuple index are invalid
110+
--> $DIR/tuple-index-suffix.rs:55:28
111+
|
112+
LL | let error_i128 = (42,).0i128;
113+
| ^^^^^ invalid suffix `i128`
114+
115+
error: suffixes on a tuple index are invalid
116+
--> $DIR/tuple-index-suffix.rs:56:28
117+
|
118+
LL | let error_u128 = (42,).0u128;
119+
| ^^^^^ invalid suffix `u128`
120+
121+
error: suffixes on a tuple index are invalid
122+
--> $DIR/tuple-index-suffix.rs:60:35
123+
|
124+
LL | let invalid_struct_name = X { 0suffix: 0, 1: 1, 2: 2 };
125+
| ^^^^^^^ invalid suffix `suffix`
126+
127+
error: suffixes on a tuple index are invalid
128+
--> $DIR/tuple-index-suffix.rs:63:13
21129
|
22130
LL | X { 0suffix: _, .. } => {}
23131
| ^^^^^^^ invalid suffix `suffix`
24132

25-
error: aborting due to 4 previous errors
133+
warning: suffixes on a tuple index are invalid
134+
--> $DIR/tuple-index-suffix.rs:69:37
135+
|
136+
LL | let carve_out_struct_name = X { 0u32: 0, 1: 1, 2: 2 };
137+
| ^^^^ invalid suffix `u32`
138+
|
139+
= help: `u32` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
140+
= help: on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
141+
= help: see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
142+
143+
warning: suffixes on a tuple index are invalid
144+
--> $DIR/tuple-index-suffix.rs:72:13
145+
|
146+
LL | X { 0u32: _, .. } => {}
147+
| ^^^^ invalid suffix `u32`
148+
|
149+
= help: `u32` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
150+
= help: on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
151+
= help: see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
152+
153+
warning: suffixes on a tuple index are invalid
154+
--> $DIR/tuple-index-suffix.rs:83:50
155+
|
156+
LL | assert_eq!(std::mem::offset_of!(Struct<u32>, 0usize), 0);
157+
| ^^^^^^ invalid suffix `usize`
158+
|
159+
= help: `usize` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
160+
= help: on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
161+
= help: see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
162+
163+
error: suffixes on a tuple index are invalid
164+
--> $DIR/tuple-index-suffix.rs:87:50
165+
|
166+
LL | assert_eq!(std::mem::offset_of!(Struct<u32>, 0u8), 0);
167+
| ^^^ invalid suffix `u8`
168+
169+
error: aborting due to 13 previous errors; 9 warnings emitted
26170

0 commit comments

Comments
 (0)