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.
This commit is contained in:
parent
267fb90b55
commit
6046f4a673
@ -1618,6 +1618,8 @@ impl LintPass for KeywordIdents {
|
||||
}
|
||||
}
|
||||
|
||||
struct UnderMacro(bool);
|
||||
|
||||
impl KeywordIdents {
|
||||
fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: TokenStream) {
|
||||
for tt in tokens.into_trees() {
|
||||
@ -1625,7 +1627,7 @@ impl KeywordIdents {
|
||||
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
|
||||
});
|
||||
@ -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| {
|
||||
@ -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.
|
||||
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user