Skip to content
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Do not lint dyn tokens under macros.
The existing `KeywordIdents` lint blindly scans the token stream for a
macro or macro definition. It does not attempt to parse the input,
which means it cannot distinguish between occurrences of `dyn` that
are truly instances of it as an identifier (e.g. `let dyn = 3;`)
versus occurrences that follow its usage as a contextual keyword (e.g.
the type `Box<dyn Trait>`).

In an ideal world the lint would parse the token stream in order to
distinguish such occurrences; but in general we cannot do this,
because a macro_rules definition does not specify what parsing
contexts the macro being defined is allowed to be used within.

So rather than put a lot of work into attempting to come up with a
more precise but still incomplete solution, I am just taking the short
cut of not linting any instance of `dyn` under a macro. This prevents
`rustfix` from injecting bugs into legal 2015 edition code.
  • Loading branch information
pnkfelix committed Mar 27, 2019
commit 6046f4a673abc39cec5405f51a17e614d5839f26
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