Skip to content

Commit c6f1a85

Browse files
Auto merge of #145463 - jieyouxu:error-suffix, r=<try>
[WIP] Reject invalid literal suffixes in tuple indexing, tuple struct indexing, and struct field name position
2 parents cd7cbe8 + da507c3 commit c6f1a85

File tree

11 files changed

+302
-67
lines changed

11 files changed

+302
-67
lines changed

compiler/rustc_parse/messages.ftl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,9 +473,6 @@ parse_invalid_label =
473473
474474
parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid
475475
.label = invalid suffix `{$suffix}`
476-
.tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
477-
.tuple_exception_line_2 = 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
478-
.tuple_exception_line_3 = see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
479476
480477
parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
481478
.note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators

compiler/rustc_parse/src/errors.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,10 +1016,6 @@ pub(crate) struct InvalidLiteralSuffixOnTupleIndex {
10161016
#[label]
10171017
pub span: Span,
10181018
pub suffix: Symbol,
1019-
#[help(parse_tuple_exception_line_1)]
1020-
#[help(parse_tuple_exception_line_2)]
1021-
#[help(parse_tuple_exception_line_3)]
1022-
pub exception: bool,
10231019
}
10241020

10251021
#[derive(Diagnostic)]

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,21 +2226,7 @@ impl<'a> Parser<'a> {
22262226
}
22272227

22282228
pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) {
2229-
if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) {
2230-
// #59553: warn instead of reject out of hand to allow the fix to percolate
2231-
// through the ecosystem when people fix their macros
2232-
self.dcx().emit_warn(errors::InvalidLiteralSuffixOnTupleIndex {
2233-
span,
2234-
suffix,
2235-
exception: true,
2236-
});
2237-
} else {
2238-
self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
2239-
span,
2240-
suffix,
2241-
exception: false,
2242-
});
2243-
}
2229+
self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex { span, suffix });
22442230
}
22452231

22462232
/// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).

src/tools/tidy/src/issues.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2021,7 +2021,6 @@ ui/parser/issues/issue-5806.rs
20212021
ui/parser/issues/issue-58094-missing-right-square-bracket.rs
20222022
ui/parser/issues/issue-58856-1.rs
20232023
ui/parser/issues/issue-58856-2.rs
2024-
ui/parser/issues/issue-59418.rs
20252024
ui/parser/issues/issue-60075.rs
20262025
ui/parser/issues/issue-61858.rs
20272026
ui/parser/issues/issue-62524.rs
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#![feature(proc_macro_quote, proc_macro_span)]
2+
3+
extern crate proc_macro;
4+
5+
use proc_macro::{Ident, Literal, Span, TokenStream, TokenTree, quote};
6+
7+
#[proc_macro]
8+
pub fn bad_tup_indexing(input: TokenStream) -> TokenStream {
9+
let tt = input.into_iter().next().unwrap();
10+
let TokenTree::Literal(indexing_expr) = tt else {
11+
unreachable!();
12+
};
13+
quote! { (42,).$indexing_expr }
14+
}
15+
16+
// Expects {IDENT, COMMA, LITERAL}
17+
#[proc_macro]
18+
pub fn bad_tup_struct_indexing(input: TokenStream) -> TokenStream {
19+
let mut input = input.into_iter();
20+
21+
let id_tt = input.next().unwrap();
22+
let _comma = input.next().unwrap();
23+
let tt = input.next().unwrap();
24+
25+
let TokenTree::Ident(ident) = id_tt else {
26+
unreachable!("id");
27+
};
28+
let TokenTree::Literal(indexing_expr) = tt else {
29+
unreachable!("lit");
30+
};
31+
32+
quote! { $ident.$indexing_expr }
33+
}

tests/ui/parser/issues/issue-59418.rs

Lines changed: 0 additions & 18 deletions
This file was deleted.

tests/ui/parser/issues/issue-59418.stderr

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//! See #59418.
2+
//!
3+
//! Like `tuple-index-suffix.rs`, but exercises the proc-macro interaction.
4+
5+
//@ proc-macro: tuple-index-suffix-proc-macro-aux.rs
6+
7+
extern crate tuple_index_suffix_proc_macro_aux;
8+
use tuple_index_suffix_proc_macro_aux as aux;
9+
10+
fn main() {
11+
struct TupStruct(i32);
12+
let tup_struct = TupStruct(42);
13+
14+
// Previously, #60186 had carve outs for `{i,u}{32,usize}` as non-lint pseudo-FCW warnings. Now,
15+
// they all hard error.
16+
17+
aux::bad_tup_indexing!(0usize);
18+
//~^ ERROR suffixes on a tuple index are invalid
19+
aux::bad_tup_struct_indexing!(tup_struct, 0isize);
20+
//~^ ERROR suffixes on a tuple index are invalid
21+
22+
// Not part of the #60186 carve outs.
23+
24+
aux::bad_tup_indexing!(0u8);
25+
//~^ ERROR suffixes on a tuple index are invalid
26+
aux::bad_tup_struct_indexing!(tup_struct, 0u64);
27+
//~^ ERROR suffixes on a tuple index are invalid
28+
29+
// NOTE: didn't bother with trying to figure out how to generate `struct P { 0u32: u32 }` using
30+
// *only* `proc_macro` without help with `syn`/`quote`, looks like you can't with just
31+
// `proc_macro::quote`?
32+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: suffixes on a tuple index are invalid
2+
--> $DIR/tuple-index-suffix-proc-macro.rs:17:28
3+
|
4+
LL | aux::bad_tup_indexing!(0usize);
5+
| ^^^^^^ invalid suffix `usize`
6+
7+
error: suffixes on a tuple index are invalid
8+
--> $DIR/tuple-index-suffix-proc-macro.rs:19:47
9+
|
10+
LL | aux::bad_tup_struct_indexing!(tup_struct, 0isize);
11+
| ^^^^^^ invalid suffix `isize`
12+
13+
error: suffixes on a tuple index are invalid
14+
--> $DIR/tuple-index-suffix-proc-macro.rs:24:28
15+
|
16+
LL | aux::bad_tup_indexing!(0u8);
17+
| ^^^ invalid suffix `u8`
18+
19+
error: suffixes on a tuple index are invalid
20+
--> $DIR/tuple-index-suffix-proc-macro.rs:26:47
21+
|
22+
LL | aux::bad_tup_struct_indexing!(tup_struct, 0u64);
23+
| ^^^^ invalid suffix `u64`
24+
25+
error: aborting due to 4 previous errors
26+

tests/ui/parser/tuple-index-suffix.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//! See #60210.
2+
//!
3+
//! Check that we hard error on invalid suffixes in tuple indexing subexpressions and struct numeral
4+
//! field names.
5+
6+
struct X(i32,i32,i32);
7+
8+
fn main() {
9+
let tup_struct = X(1, 2, 3);
10+
let invalid_tup_struct_suffix = tup_struct.0suffix;
11+
//~^ ERROR suffixes on a tuple index are invalid
12+
let previous_carve_out_tup_struct_suffix = tup_struct.0i32;
13+
//~^ ERROR suffixes on a tuple index are invalid
14+
15+
let tup = (1, 2, 3);
16+
let invalid_tup_suffix = tup.0suffix;
17+
//~^ ERROR suffixes on a tuple index are invalid
18+
let previous_carve_out_tup_suffix = tup.0u32;
19+
//~^ ERROR suffixes on a tuple index are invalid
20+
21+
numeral_struct_field_name_suffix_invalid();
22+
numeral_struct_field_name_suffix_previous_carve_out();
23+
}
24+
25+
// Previously, there were very limited carve outs as a ecosystem impact mitigation implemented in
26+
// #60186. *Only* `{i,u}{32,usize}` suffixes were temporarily accepted. Now, they all hard error.
27+
fn previous_carve_outs() {
28+
// Previously temporarily accepted by a pseudo-FCW, now hard error.
29+
30+
let previous_carve_out_i32 = (42,).0i32; //~ ERROR suffixes on a tuple index are invalid
31+
let previous_carve_out_i32 = (42,).0u32; //~ ERROR suffixes on a tuple index are invalid
32+
let previous_carve_out_isize = (42,).0isize; //~ ERROR suffixes on a tuple index are invalid
33+
let previous_carve_out_usize = (42,).0usize; //~ ERROR suffixes on a tuple index are invalid
34+
35+
// Not part of the carve outs!
36+
let error_i8 = (42,).0i8; //~ ERROR suffixes on a tuple index are invalid
37+
let error_u8 = (42,).0u8; //~ ERROR suffixes on a tuple index are invalid
38+
let error_i16 = (42,).0i16; //~ ERROR suffixes on a tuple index are invalid
39+
let error_u16 = (42,).0u16; //~ ERROR suffixes on a tuple index are invalid
40+
let error_i64 = (42,).0i64; //~ ERROR suffixes on a tuple index are invalid
41+
let error_u64 = (42,).0u64; //~ ERROR suffixes on a tuple index are invalid
42+
let error_i128 = (42,).0i128; //~ ERROR suffixes on a tuple index are invalid
43+
let error_u128 = (42,).0u128; //~ ERROR suffixes on a tuple index are invalid
44+
}
45+
46+
fn numeral_struct_field_name_suffix_invalid() {
47+
let invalid_struct_name = X { 0suffix: 0, 1: 1, 2: 2 };
48+
//~^ ERROR suffixes on a tuple index are invalid
49+
match invalid_struct_name {
50+
X { 0suffix: _, .. } => {}
51+
//~^ ERROR suffixes on a tuple index are invalid
52+
}
53+
}
54+
55+
fn numeral_struct_field_name_suffix_previous_carve_out() {
56+
let carve_out_struct_name = X { 0u32: 0, 1: 1, 2: 2 };
57+
//~^ ERROR suffixes on a tuple index are invalid
58+
match carve_out_struct_name {
59+
X { 0u32: _, .. } => {}
60+
//~^ ERROR suffixes on a tuple index are invalid
61+
}
62+
}
63+
64+
// Unfortunately, it turns out `std::mem::offset_of!` uses the same expect suffix code path.
65+
fn offset_of_suffix() {
66+
#[repr(C)]
67+
pub struct Struct<T>(u8, T);
68+
69+
// Previous pseudo-FCW carve outs
70+
assert_eq!(std::mem::offset_of!(Struct<u32>, 0usize), 0);
71+
//~^ ERROR suffixes on a tuple index are invalid
72+
73+
// Not part of carve outs
74+
assert_eq!(std::mem::offset_of!(Struct<u32>, 0u8), 0);
75+
//~^ ERROR suffixes on a tuple index are invalid
76+
}

0 commit comments

Comments
 (0)