Skip to content

Commit c9dca36

Browse files
authored
Rollup merge of #59463 - pnkfelix:issue-56327-skip-dyn-keyword-lint-under-macros, r=matthewjasper
skip dyn keyword lint under macros This PR is following my own intuition that `rustfix` should never inject bugs into working code (even if that comes at the expense of it failing to fix things that will become bugs). Fix #56327
2 parents ae25518 + 528366d commit c9dca36

8 files changed

+490
-11
lines changed

src/librustc_lint/builtin.rs

+36-11
Original file line numberDiff line numberDiff line change
@@ -1619,14 +1619,16 @@ impl LintPass for KeywordIdents {
16191619
}
16201620
}
16211621

1622+
struct UnderMacro(bool);
1623+
16221624
impl KeywordIdents {
16231625
fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: TokenStream) {
16241626
for tt in tokens.into_trees() {
16251627
match tt {
16261628
TokenTree::Token(span, tok) => match tok.ident() {
16271629
// only report non-raw idents
16281630
Some((ident, false)) => {
1629-
self.check_ident(cx, ast::Ident {
1631+
self.check_ident_token(cx, UnderMacro(true), ast::Ident {
16301632
span: span.substitute_dummy(ident.span),
16311633
..ident
16321634
});
@@ -1639,16 +1641,12 @@ impl KeywordIdents {
16391641
}
16401642
}
16411643
}
1642-
}
16431644

1644-
impl EarlyLintPass for KeywordIdents {
1645-
fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef, _id: ast::NodeId) {
1646-
self.check_tokens(cx, mac_def.stream());
1647-
}
1648-
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) {
1649-
self.check_tokens(cx, mac.node.tts.clone().into());
1650-
}
1651-
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
1645+
fn check_ident_token(&mut self,
1646+
cx: &EarlyContext<'_>,
1647+
UnderMacro(under_macro): UnderMacro,
1648+
ident: ast::Ident)
1649+
{
16521650
let ident_str = &ident.as_str()[..];
16531651
let cur_edition = cx.sess.edition();
16541652
let is_raw_ident = |ident: ast::Ident| {
@@ -1657,7 +1655,22 @@ impl EarlyLintPass for KeywordIdents {
16571655
let next_edition = match cur_edition {
16581656
Edition::Edition2015 => {
16591657
match ident_str {
1660-
"async" | "try" | "dyn" => Edition::Edition2018,
1658+
"async" | "try" => Edition::Edition2018,
1659+
1660+
// rust-lang/rust#56327: Conservatively do not
1661+
// attempt to report occurrences of `dyn` within
1662+
// macro definitions or invocations, because `dyn`
1663+
// can legitimately occur as a contextual keyword
1664+
// in 2015 code denoting its 2018 meaning, and we
1665+
// do not want rustfix to inject bugs into working
1666+
// code by rewriting such occurrences.
1667+
//
1668+
// But if we see `dyn` outside of a macro, we know
1669+
// its precise role in the parsed AST and thus are
1670+
// assured this is truly an attempt to use it as
1671+
// an identifier.
1672+
"dyn" if !under_macro => Edition::Edition2018,
1673+
16611674
// Only issue warnings for `await` if the `async_await`
16621675
// feature isn't being used. Otherwise, users need
16631676
// to keep using `await` for the macro exposed by std.
@@ -1715,6 +1728,18 @@ impl EarlyLintPass for KeywordIdents {
17151728
}
17161729
}
17171730

1731+
impl EarlyLintPass for KeywordIdents {
1732+
fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef, _id: ast::NodeId) {
1733+
self.check_tokens(cx, mac_def.stream());
1734+
}
1735+
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) {
1736+
self.check_tokens(cx, mac.node.tts.clone().into());
1737+
}
1738+
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
1739+
self.check_ident_token(cx, UnderMacro(false), ident);
1740+
}
1741+
}
1742+
17181743

17191744
pub struct ExplicitOutlivesRequirements;
17201745

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Under the 2015 edition with the keyword_idents lint, `dyn` is not
2+
// entirely acceptable as an identifier. We currently do not attempt
3+
// to detect or fix uses of `dyn` under a macro. Since we are testing
4+
// this file via `rustfix`, we want the rustfix output to be
5+
// compilable; so the macros here carefully use `dyn` "correctly."
6+
7+
// run-rustfix
8+
9+
#![allow(non_camel_case_types)]
10+
#![deny(keyword_idents)]
11+
12+
mod outer_mod {
13+
pub mod r#dyn {
14+
//~^ ERROR `dyn` is a keyword
15+
//~| WARN was previously accepted
16+
pub struct r#dyn;
17+
//~^ ERROR `dyn` is a keyword
18+
//~| WARN was previously accepted
19+
}
20+
}
21+
use outer_mod::r#dyn::r#dyn;
22+
//~^ ERROR `dyn` is a keyword
23+
//~| WARN was previously accepted
24+
//~| ERROR `dyn` is a keyword
25+
//~| WARN was previously accepted
26+
27+
fn main() {
28+
match r#dyn { r#dyn => {} }
29+
//~^ ERROR `dyn` is a keyword
30+
//~| WARN was previously accepted
31+
//~| ERROR `dyn` is a keyword
32+
//~| WARN was previously accepted
33+
macro_defn::r#dyn();
34+
//~^ ERROR `dyn` is a keyword
35+
//~| WARN was previously accepted
36+
37+
macro_defn::boxed();
38+
}
39+
40+
mod macro_defn {
41+
use super::Trait;
42+
43+
macro_rules! r#dyn {
44+
//~^ ERROR `dyn` is a keyword
45+
//~| WARN was previously accepted
46+
47+
// Note that we do not lint nor fix occurrences under macros
48+
($dyn:tt) => { (Box<dyn Trait>, Box<$dyn Trait>) }
49+
}
50+
51+
pub fn r#dyn() -> ::outer_mod::r#dyn::r#dyn {
52+
//~^ ERROR `dyn` is a keyword
53+
//~| WARN was previously accepted
54+
//~| ERROR `dyn` is a keyword
55+
//~| WARN was previously accepted
56+
//~| ERROR `dyn` is a keyword
57+
//~| WARN was previously accepted
58+
::outer_mod::r#dyn::r#dyn
59+
//~^ ERROR `dyn` is a keyword
60+
//~| WARN was previously accepted
61+
//~| ERROR `dyn` is a keyword
62+
//~| WARN was previously accepted
63+
}
64+
65+
66+
67+
pub fn boxed() -> r#dyn!(
68+
//~^ ERROR `dyn` is a keyword
69+
//~| WARN was previously accepted
70+
71+
// Note that we do not lint nor fix occurrences under macros
72+
dyn
73+
)
74+
{
75+
(Box::new(1), Box::new(2))
76+
}
77+
}
78+
79+
pub trait Trait { }
80+
81+
impl Trait for u32 { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Under the 2015 edition with the keyword_idents lint, `dyn` is not
2+
// entirely acceptable as an identifier. We currently do not attempt
3+
// to detect or fix uses of `dyn` under a macro. Since we are testing
4+
// this file via `rustfix`, we want the rustfix output to be
5+
// compilable; so the macros here carefully use `dyn` "correctly."
6+
7+
// run-rustfix
8+
9+
#![allow(non_camel_case_types)]
10+
#![deny(keyword_idents)]
11+
12+
mod outer_mod {
13+
pub mod dyn {
14+
//~^ ERROR `dyn` is a keyword
15+
//~| WARN was previously accepted
16+
pub struct dyn;
17+
//~^ ERROR `dyn` is a keyword
18+
//~| WARN was previously accepted
19+
}
20+
}
21+
use outer_mod::dyn::dyn;
22+
//~^ ERROR `dyn` is a keyword
23+
//~| WARN was previously accepted
24+
//~| ERROR `dyn` is a keyword
25+
//~| WARN was previously accepted
26+
27+
fn main() {
28+
match dyn { dyn => {} }
29+
//~^ ERROR `dyn` is a keyword
30+
//~| WARN was previously accepted
31+
//~| ERROR `dyn` is a keyword
32+
//~| WARN was previously accepted
33+
macro_defn::dyn();
34+
//~^ ERROR `dyn` is a keyword
35+
//~| WARN was previously accepted
36+
37+
macro_defn::boxed();
38+
}
39+
40+
mod macro_defn {
41+
use super::Trait;
42+
43+
macro_rules! dyn {
44+
//~^ ERROR `dyn` is a keyword
45+
//~| WARN was previously accepted
46+
47+
// Note that we do not lint nor fix occurrences under macros
48+
($dyn:tt) => { (Box<dyn Trait>, Box<$dyn Trait>) }
49+
}
50+
51+
pub fn dyn() -> ::outer_mod::dyn::dyn {
52+
//~^ ERROR `dyn` is a keyword
53+
//~| WARN was previously accepted
54+
//~| ERROR `dyn` is a keyword
55+
//~| WARN was previously accepted
56+
//~| ERROR `dyn` is a keyword
57+
//~| WARN was previously accepted
58+
::outer_mod::dyn::dyn
59+
//~^ ERROR `dyn` is a keyword
60+
//~| WARN was previously accepted
61+
//~| ERROR `dyn` is a keyword
62+
//~| WARN was previously accepted
63+
}
64+
65+
66+
67+
pub fn boxed() -> dyn!(
68+
//~^ ERROR `dyn` is a keyword
69+
//~| WARN was previously accepted
70+
71+
// Note that we do not lint nor fix occurrences under macros
72+
dyn
73+
)
74+
{
75+
(Box::new(1), Box::new(2))
76+
}
77+
}
78+
79+
pub trait Trait { }
80+
81+
impl Trait for u32 { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
error: `dyn` is a keyword in the 2018 edition
2+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:13:13
3+
|
4+
LL | pub mod dyn {
5+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
6+
|
7+
note: lint level defined here
8+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:10:9
9+
|
10+
LL | #![deny(keyword_idents)]
11+
| ^^^^^^^^^^^^^^
12+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
13+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
14+
15+
error: `dyn` is a keyword in the 2018 edition
16+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:16:20
17+
|
18+
LL | pub struct dyn;
19+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
20+
|
21+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
22+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
23+
24+
error: `dyn` is a keyword in the 2018 edition
25+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:21:16
26+
|
27+
LL | use outer_mod::dyn::dyn;
28+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
29+
|
30+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
31+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
32+
33+
error: `dyn` is a keyword in the 2018 edition
34+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:21:21
35+
|
36+
LL | use outer_mod::dyn::dyn;
37+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
38+
|
39+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
40+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
41+
42+
error: `dyn` is a keyword in the 2018 edition
43+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:28:11
44+
|
45+
LL | match dyn { dyn => {} }
46+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
47+
|
48+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
49+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
50+
51+
error: `dyn` is a keyword in the 2018 edition
52+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:28:17
53+
|
54+
LL | match dyn { dyn => {} }
55+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
56+
|
57+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
58+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
59+
60+
error: `dyn` is a keyword in the 2018 edition
61+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:33:17
62+
|
63+
LL | macro_defn::dyn();
64+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
65+
|
66+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
67+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
68+
69+
error: `dyn` is a keyword in the 2018 edition
70+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:43:18
71+
|
72+
LL | macro_rules! dyn {
73+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
74+
|
75+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
76+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
77+
78+
error: `dyn` is a keyword in the 2018 edition
79+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:12
80+
|
81+
LL | pub fn dyn() -> ::outer_mod::dyn::dyn {
82+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
83+
|
84+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
85+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
86+
87+
error: `dyn` is a keyword in the 2018 edition
88+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:34
89+
|
90+
LL | pub fn dyn() -> ::outer_mod::dyn::dyn {
91+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
92+
|
93+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
94+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
95+
96+
error: `dyn` is a keyword in the 2018 edition
97+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:39
98+
|
99+
LL | pub fn dyn() -> ::outer_mod::dyn::dyn {
100+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
101+
|
102+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
103+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
104+
105+
error: `dyn` is a keyword in the 2018 edition
106+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:58:22
107+
|
108+
LL | ::outer_mod::dyn::dyn
109+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
110+
|
111+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
112+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
113+
114+
error: `dyn` is a keyword in the 2018 edition
115+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:58:27
116+
|
117+
LL | ::outer_mod::dyn::dyn
118+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
119+
|
120+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
121+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
122+
123+
error: `dyn` is a keyword in the 2018 edition
124+
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:67:23
125+
|
126+
LL | pub fn boxed() -> dyn!(
127+
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
128+
|
129+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
130+
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
131+
132+
error: aborting due to 14 previous errors
133+

0 commit comments

Comments
 (0)