Skip to content

Commit 964a73c

Browse files
authored
Unrolled build for rust-lang#137140
Rollup merge of rust-lang#137140 - Noratrieb:const-move, r=jieyouxu,compiler-errors Fix const items not being allowed to be called `r#move` or `r#static` Because of an ambiguity with const closures, the parser needs to ensure that for a const item, the `const` keyword isn't followed by a `move` or `static` keyword, as that would indicate a const closure: ```rust fn main() { const move // ... } ``` This check did not take raw identifiers into account, therefore being unable to distinguish between `const move` and `const r#move`. The latter is obviously not a const closure, so it should be allowed as a const item. This fixes the check in the parser to only treat `const ...` as a const closure if it's followed by the *proper keyword*, and not a raw identifier. Additionally, this adds a large test that tests for all raw identifiers in all kinds of positions, including `const`, to prevent issues like this one from occurring again. fixes rust-lang#137128
2 parents d5eb31c + 8a02724 commit 964a73c

File tree

3 files changed

+163
-3
lines changed

3 files changed

+163
-3
lines changed

compiler/rustc_parse/src/parser/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -754,9 +754,9 @@ impl<'a> Parser<'a> {
754754
self.is_keyword_ahead(0, &[kw::Const])
755755
&& self.look_ahead(1, |t| match &t.kind {
756756
// async closures do not work with const closures, so we do not parse that here.
757-
token::Ident(kw::Move | kw::Static, _) | token::OrOr | token::BinOp(token::Or) => {
758-
true
759-
}
757+
token::Ident(kw::Move | kw::Static, IdentIsRaw::No)
758+
| token::OrOr
759+
| token::BinOp(token::Or) => true,
760760
_ => false,
761761
})
762762
}

compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ symbols! {
104104
Gen: "gen", // >= 2024 Edition only
105105
Try: "try", // >= 2018 Edition only
106106

107+
// NOTE: When adding new keywords, consider adding them to the ui/parser/raw/raw-idents.rs test.
108+
107109
// "Lifetime keywords": regular keywords with a leading `'`.
108110
// Matching predicates: `is_any_keyword`
109111
UnderscoreLifetime: "'_",

tests/ui/parser/raw/raw-idents.rs

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
//@ check-pass
2+
//@ revisions:e2015 e2018 e2021 e2024
3+
//@[e2015] edition:2015
4+
//@[e2018] edition:2018
5+
//@[e2021] edition:2021
6+
//@[e2024] edition:2024
7+
8+
// Ensure that all (usable as identifier) keywords work as raw identifiers in all positions.
9+
// This was motivated by issue #137128, where `r#move`/`r#static`` did not work as `const` names
10+
// due to a parser check not acounting for raw identifiers.
11+
12+
#![crate_type = "lib"]
13+
#![allow(dead_code, nonstandard_style)]
14+
15+
// NOTE: It is vital to only use a `tt` fragment to avoid confusing
16+
// the parser with nonterminals that can mask bugs.
17+
18+
macro_rules! tests {
19+
($kw:tt) => {
20+
mod $kw {
21+
mod const_item {
22+
const $kw: () = ();
23+
}
24+
mod static_item {
25+
static $kw: () = ();
26+
}
27+
mod fn_item {
28+
fn $kw() {}
29+
}
30+
mod mod_and_use_item {
31+
mod $kw {
32+
use super::$kw;
33+
}
34+
}
35+
mod ty_alias_item {
36+
type $kw = ();
37+
}
38+
mod struct_item {
39+
struct $kw { $kw: () }
40+
}
41+
mod enum_item {
42+
enum $kw { $kw }
43+
}
44+
mod union_item {
45+
union $kw { $kw: () }
46+
}
47+
mod trait_item {
48+
trait $kw {
49+
fn $kw() {}
50+
}
51+
}
52+
mod generics_and_impl {
53+
struct A<$kw>($kw);
54+
enum B<$kw> { A($kw) }
55+
trait Tr<$kw> {
56+
type $kw;
57+
}
58+
59+
impl<$kw> Tr<$kw> for A<$kw> {
60+
type $kw = ();
61+
}
62+
impl<$kw> B<$kw> {}
63+
}
64+
mod extern_crate {
65+
#[cfg(any())]
66+
extern crate $kw;
67+
}
68+
mod body {
69+
fn expr() {
70+
let $kw = 0;
71+
let b = $kw;
72+
assert_eq!($kw, b);
73+
type $kw = ();
74+
let $kw: $kw = ();
75+
let _ = $kw as $kw;
76+
}
77+
fn pat_const() {
78+
const $kw: u8 = 0;
79+
80+
// Ensure that $kw actually matches the constant.
81+
#[forbid(unreachable_patterns)]
82+
match 1 {
83+
$kw => {}
84+
_ => {}
85+
}
86+
}
87+
fn pat_binding() {
88+
match 1 {
89+
$kw => {}
90+
_ => {}
91+
}
92+
}
93+
}
94+
}
95+
};
96+
}
97+
98+
tests!(r#break);
99+
tests!(r#const);
100+
tests!(r#continue);
101+
tests!(r#else);
102+
tests!(r#enum);
103+
tests!(r#extern);
104+
tests!(r#false);
105+
tests!(r#fn);
106+
tests!(r#for);
107+
tests!(r#if);
108+
tests!(r#impl);
109+
tests!(r#in);
110+
tests!(r#let);
111+
tests!(r#loop);
112+
tests!(r#match);
113+
tests!(r#mod);
114+
tests!(r#move);
115+
tests!(r#mut);
116+
tests!(r#pub);
117+
tests!(r#ref);
118+
tests!(r#return);
119+
tests!(r#static);
120+
tests!(r#struct);
121+
tests!(r#trait);
122+
tests!(r#true);
123+
tests!(r#type);
124+
tests!(r#unsafe);
125+
tests!(r#use);
126+
tests!(r#where);
127+
tests!(r#while);
128+
tests!(r#abstract);
129+
tests!(r#become);
130+
tests!(r#box);
131+
tests!(r#do);
132+
tests!(r#final);
133+
tests!(r#macro);
134+
tests!(r#override);
135+
tests!(r#priv);
136+
tests!(r#typeof);
137+
tests!(r#unsized);
138+
tests!(r#virtual);
139+
tests!(r#yield);
140+
tests!(r#async);
141+
tests!(r#await);
142+
tests!(r#dyn);
143+
tests!(r#gen);
144+
tests!(r#try);
145+
146+
// Weak keywords:
147+
tests!(auto);
148+
tests!(builtin);
149+
tests!(catch);
150+
tests!(default);
151+
tests!(macro_rules);
152+
tests!(raw);
153+
tests!(reuse);
154+
tests!(contract_ensures);
155+
tests!(contract_requires);
156+
tests!(safe);
157+
tests!(union);
158+
tests!(yeet);

0 commit comments

Comments
 (0)