Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

skip dyn keyword lint under macros #59463

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 36 additions & 11 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1618,14 +1618,16 @@ impl LintPass for KeywordIdents {
}
}

struct UnderMacro(bool);

impl KeywordIdents {
fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: TokenStream) {
for tt in tokens.into_trees() {
match tt {
TokenTree::Token(span, tok) => match tok.ident() {
// only report non-raw idents
Some((ident, false)) => {
self.check_ident(cx, ast::Ident {
self.check_ident_token(cx, UnderMacro(true), ast::Ident {
span: span.substitute_dummy(ident.span),
..ident
});
Expand All @@ -1638,16 +1640,12 @@ impl KeywordIdents {
}
}
}
}

impl EarlyLintPass for KeywordIdents {
fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef, _id: ast::NodeId) {
self.check_tokens(cx, mac_def.stream());
}
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) {
self.check_tokens(cx, mac.node.tts.clone().into());
}
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
fn check_ident_token(&mut self,
cx: &EarlyContext<'_>,
UnderMacro(under_macro): UnderMacro,
ident: ast::Ident)
{
let ident_str = &ident.as_str()[..];
let cur_edition = cx.sess.edition();
let is_raw_ident = |ident: ast::Ident| {
Expand All @@ -1656,7 +1654,22 @@ impl EarlyLintPass for KeywordIdents {
let next_edition = match cur_edition {
Edition::Edition2015 => {
match ident_str {
"async" | "try" | "dyn" => Edition::Edition2018,
"async" | "try" => Edition::Edition2018,

// rust-lang/rust#56327: Conservatively do not
// attempt to report occurrences of `dyn` within
// macro definitions or invocations, because `dyn`
// can legitimately occur as a contextual keyword
// in 2015 code denoting its 2018 meaning, and we
// do not want rustfix to inject bugs into working
// code by rewriting such occurrences.
//
// But if we see `dyn` outside of a macro, we know
// its precise role in the parsed AST and thus are
// assured this is truly an attempt to use it as
// an identifier.
"dyn" if !under_macro => Edition::Edition2018,

// Only issue warnings for `await` if the `async_await`
// feature isn't being used. Otherwise, users need
// to keep using `await` for the macro exposed by std.
Expand Down Expand Up @@ -1714,6 +1727,18 @@ impl EarlyLintPass for KeywordIdents {
}
}

impl EarlyLintPass for KeywordIdents {
fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef, _id: ast::NodeId) {
self.check_tokens(cx, mac_def.stream());
}
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) {
self.check_tokens(cx, mac.node.tts.clone().into());
}
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
self.check_ident_token(cx, UnderMacro(false), ident);
}
}


pub struct ExplicitOutlivesRequirements;

Expand Down
81 changes: 81 additions & 0 deletions src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Under the 2015 edition with the keyword_idents lint, `dyn` is not
// entirely acceptable as an identifier. We currently do not attempt
// to detect or fix uses of `dyn` under a macro. Since we are testing
// this file via `rustfix`, we want the rustfix output to be
// compilable; so the macros here carefully use `dyn` "correctly."

// run-rustfix

#![allow(non_camel_case_types)]
#![deny(keyword_idents)]

mod outer_mod {
pub mod r#dyn {
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
pub struct r#dyn;
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
}
}
use outer_mod::r#dyn::r#dyn;
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
//~| ERROR `dyn` is a keyword
//~| WARN was previously accepted

fn main() {
match r#dyn { r#dyn => {} }
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
//~| ERROR `dyn` is a keyword
//~| WARN was previously accepted
macro_defn::r#dyn();
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted

macro_defn::boxed();
}

mod macro_defn {
use super::Trait;

macro_rules! r#dyn {
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted

// Note that we do not lint nor fix occurrences under macros
($dyn:tt) => { (Box<dyn Trait>, Box<$dyn Trait>) }
}

pub fn r#dyn() -> ::outer_mod::r#dyn::r#dyn {
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
//~| ERROR `dyn` is a keyword
//~| WARN was previously accepted
//~| ERROR `dyn` is a keyword
//~| WARN was previously accepted
::outer_mod::r#dyn::r#dyn
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
//~| ERROR `dyn` is a keyword
//~| WARN was previously accepted
}



pub fn boxed() -> r#dyn!(
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted

// Note that we do not lint nor fix occurrences under macros
dyn
)
{
(Box::new(1), Box::new(2))
}
}

pub trait Trait { }

impl Trait for u32 { }
81 changes: 81 additions & 0 deletions src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Under the 2015 edition with the keyword_idents lint, `dyn` is not
// entirely acceptable as an identifier. We currently do not attempt
// to detect or fix uses of `dyn` under a macro. Since we are testing
// this file via `rustfix`, we want the rustfix output to be
// compilable; so the macros here carefully use `dyn` "correctly."

// run-rustfix

#![allow(non_camel_case_types)]
#![deny(keyword_idents)]

mod outer_mod {
pub mod dyn {
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
pub struct dyn;
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
}
}
use outer_mod::dyn::dyn;
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
//~| ERROR `dyn` is a keyword
//~| WARN was previously accepted

fn main() {
match dyn { dyn => {} }
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
//~| ERROR `dyn` is a keyword
//~| WARN was previously accepted
macro_defn::dyn();
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted

macro_defn::boxed();
}

mod macro_defn {
use super::Trait;

macro_rules! dyn {
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted

// Note that we do not lint nor fix occurrences under macros
($dyn:tt) => { (Box<dyn Trait>, Box<$dyn Trait>) }
}

pub fn dyn() -> ::outer_mod::dyn::dyn {
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
//~| ERROR `dyn` is a keyword
//~| WARN was previously accepted
//~| ERROR `dyn` is a keyword
//~| WARN was previously accepted
::outer_mod::dyn::dyn
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted
//~| ERROR `dyn` is a keyword
//~| WARN was previously accepted
}



pub fn boxed() -> dyn!(
//~^ ERROR `dyn` is a keyword
//~| WARN was previously accepted

// Note that we do not lint nor fix occurrences under macros
dyn
)
{
(Box::new(1), Box::new(2))
}
}

pub trait Trait { }

impl Trait for u32 { }
133 changes: 133 additions & 0 deletions src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:13:13
|
LL | pub mod dyn {
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
note: lint level defined here
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:10:9
|
LL | #![deny(keyword_idents)]
| ^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:16:20
|
LL | pub struct dyn;
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:21:16
|
LL | use outer_mod::dyn::dyn;
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:21:21
|
LL | use outer_mod::dyn::dyn;
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:28:11
|
LL | match dyn { dyn => {} }
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:28:17
|
LL | match dyn { dyn => {} }
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:33:17
|
LL | macro_defn::dyn();
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:43:18
|
LL | macro_rules! dyn {
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:12
|
LL | pub fn dyn() -> ::outer_mod::dyn::dyn {
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:34
|
LL | pub fn dyn() -> ::outer_mod::dyn::dyn {
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:39
|
LL | pub fn dyn() -> ::outer_mod::dyn::dyn {
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:58:22
|
LL | ::outer_mod::dyn::dyn
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:58:27
|
LL | ::outer_mod::dyn::dyn
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:67:23
|
LL | pub fn boxed() -> dyn!(
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>

error: aborting due to 14 previous errors

Loading