Skip to content

Commit 12ed235

Browse files
committed
Auto merge of #52375 - oli-obk:the_early_lint_pass_gets_the_worm, r=Manishearth
Lint `async` identifiers in 2018 preparation mode r? @Manishearth fixes #49716
2 parents 29ee654 + 68c93e7 commit 12ed235

14 files changed

+599
-183
lines changed

src/librustc/lint/context.rs

+169-159
Large diffs are not rendered by default.

src/librustc/lint/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ pub trait EarlyLintPass: LintPass {
327327
fn check_lifetime(&mut self, _: &EarlyContext, _: &ast::Lifetime) { }
328328
fn check_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { }
329329
fn check_attribute(&mut self, _: &EarlyContext, _: &ast::Attribute) { }
330+
fn check_mac_def(&mut self, _: &EarlyContext, _: &ast::MacroDef, _id: ast::NodeId) { }
331+
fn check_mac(&mut self, _: &EarlyContext, _: &ast::Mac) { }
330332

331333
/// Called when entering a syntax node that can have lint attributes such
332334
/// as `#[allow(...)]`. Called with *all* the attributes of that node.
@@ -341,6 +343,8 @@ pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync +
341343
pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send
342344
+ sync::Sync + 'static>;
343345

346+
347+
344348
/// Identifies a lint known to the compiler.
345349
#[derive(Clone, Copy, Debug)]
346350
pub struct LintId {

src/librustc_driver/driver.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,10 @@ where
922922
return Err(CompileIncomplete::Stopped);
923923
}
924924

925+
time(sess, "pre ast expansion lint checks", || {
926+
lint::check_ast_crate(sess, &krate, true)
927+
});
928+
925929
let mut resolver = Resolver::new(
926930
sess,
927931
cstore,
@@ -1134,7 +1138,7 @@ where
11341138
});
11351139

11361140
time(sess, "early lint checks", || {
1137-
lint::check_ast_crate(sess, &krate)
1141+
lint::check_ast_crate(sess, &krate, false)
11381142
});
11391143

11401144
// Discard hygiene data, which isn't required after lowering to HIR.

src/librustc_lint/builtin.rs

+68
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext};
4141

4242
use std::collections::HashSet;
4343

44+
use syntax::tokenstream::{TokenTree, TokenStream};
4445
use syntax::ast;
4546
use syntax::attr;
4647
use syntax::codemap::Spanned;
@@ -1784,3 +1785,70 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestFunctions {
17841785
};
17851786
}
17861787
}
1788+
1789+
declare_lint! {
1790+
pub ASYNC_IDENTS,
1791+
Allow,
1792+
"detects `async` being used as an identifier"
1793+
}
1794+
1795+
/// Checks for uses of `async` as an identifier
1796+
#[derive(Clone)]
1797+
pub struct Async2018;
1798+
1799+
impl LintPass for Async2018 {
1800+
fn get_lints(&self) -> LintArray {
1801+
lint_array!(ASYNC_IDENTS)
1802+
}
1803+
}
1804+
1805+
impl Async2018 {
1806+
fn check_tokens(&mut self, cx: &EarlyContext, tokens: TokenStream) {
1807+
for tt in tokens.into_trees() {
1808+
match tt {
1809+
TokenTree::Token(span, tok) => match tok.ident() {
1810+
// only report non-raw idents
1811+
Some((ident, false)) if ident.as_str() == "async" => {
1812+
self.report(cx, span.substitute_dummy(ident.span))
1813+
},
1814+
_ => {},
1815+
}
1816+
TokenTree::Delimited(_, ref delim) => {
1817+
self.check_tokens(cx, delim.tts.clone().into())
1818+
},
1819+
}
1820+
}
1821+
}
1822+
fn report(&mut self, cx: &EarlyContext, span: Span) {
1823+
// don't lint `r#async`
1824+
if cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&span) {
1825+
return;
1826+
}
1827+
let mut lint = cx.struct_span_lint(
1828+
ASYNC_IDENTS,
1829+
span,
1830+
"`async` is a keyword in the 2018 edition",
1831+
);
1832+
lint.span_suggestion_with_applicability(
1833+
span,
1834+
"you can use a raw identifier to stay compatible",
1835+
"r#async".to_string(),
1836+
Applicability::MachineApplicable,
1837+
);
1838+
lint.emit()
1839+
}
1840+
}
1841+
1842+
impl EarlyLintPass for Async2018 {
1843+
fn check_mac_def(&mut self, cx: &EarlyContext, mac_def: &ast::MacroDef, _id: ast::NodeId) {
1844+
self.check_tokens(cx, mac_def.stream());
1845+
}
1846+
fn check_mac(&mut self, cx: &EarlyContext, mac: &ast::Mac) {
1847+
self.check_tokens(cx, mac.node.tts.clone().into());
1848+
}
1849+
fn check_ident(&mut self, cx: &EarlyContext, ident: ast::Ident) {
1850+
if ident.as_str() == "async" {
1851+
self.report(cx, ident.span);
1852+
}
1853+
}
1854+
}

src/librustc_lint/lib.rs

+17
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
8383
)
8484
}
8585

86+
macro_rules! add_pre_expansion_builtin {
87+
($sess:ident, $($name:ident),*,) => (
88+
{$(
89+
store.register_early_pass($sess, false, box $name);
90+
)*}
91+
)
92+
}
93+
8694
macro_rules! add_early_builtin_with_new {
8795
($sess:ident, $($name:ident),*,) => (
8896
{$(
@@ -97,6 +105,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
97105
)
98106
}
99107

108+
add_pre_expansion_builtin!(sess,
109+
Async2018,
110+
);
111+
100112
add_early_builtin!(sess,
101113
UnusedParens,
102114
UnusedImportBraces,
@@ -215,6 +227,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
215227
reference: "issue #35896 <https://github.com/rust-lang/rust/issues/35896>",
216228
edition: Some(Edition::Edition2018),
217229
},
230+
FutureIncompatibleInfo {
231+
id: LintId::of(ASYNC_IDENTS),
232+
reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
233+
edition: Some(Edition::Edition2018),
234+
},
218235
FutureIncompatibleInfo {
219236
id: LintId::of(SAFE_EXTERN_STATICS),
220237
reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
2+
--> $DIR/lint-plugin-forbid-attrs.rs:20:9
3+
|
4+
LL | #![forbid(test_lint)]
5+
| --------- `forbid` level set here
6+
...
7+
LL | #[allow(test_lint)]
8+
| ^^^^^^^^^ overruled by previous forbid
9+
110
error: item is named 'lintme'
211
--> $DIR/lint-plugin-forbid-attrs.rs:18:1
312
|
@@ -10,15 +19,6 @@ note: lint level defined here
1019
LL | #![forbid(test_lint)]
1120
| ^^^^^^^^^
1221

13-
error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
14-
--> $DIR/lint-plugin-forbid-attrs.rs:20:9
15-
|
16-
LL | #![forbid(test_lint)]
17-
| --------- `forbid` level set here
18-
...
19-
LL | #[allow(test_lint)]
20-
| ^^^^^^^^^ overruled by previous forbid
21-
2222
error: aborting due to 2 previous errors
2323

2424
For more information about this error, try `rustc --explain E0453`.

src/test/ui/auxiliary/edition-kw-macro-2015.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// edition:2015
1212

1313
#![feature(raw_identifiers)]
14+
#![allow(async_idents)]
1415

1516
#[macro_export]
1617
macro_rules! produces_async {

src/test/ui/auxiliary/edition-kw-macro-2018.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// edition:2018
1212

1313
#![feature(raw_identifiers)]
14+
#![allow(async_idents)]
1415

1516
#[macro_export]
1617
macro_rules! produces_async {

src/test/ui/edition-keywords-2015-2015-expansion.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// compile-pass
1414

1515
#![feature(raw_identifiers)]
16+
#![allow(async_idents)]
1617

1718
#[macro_use]
1819
extern crate edition_kw_macro_2015;

src/test/ui/edition-keywords-2018-2015-expansion.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// compile-pass
1414

1515
#![feature(raw_identifiers)]
16+
#![allow(async_idents)]
1617

1718
#[macro_use]
1819
extern crate edition_kw_macro_2015;

src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,3 @@
1-
warning: macro_escape is a deprecated synonym for macro_use
2-
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:1
3-
|
4-
LL | #[macro_escape]
5-
| ^^^^^^^^^^^^^^^
6-
7-
warning: macro_escape is a deprecated synonym for macro_use
8-
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:503:17
9-
|
10-
LL | mod inner { #![macro_escape] }
11-
| ^^^^^^^^^^^^^^^^
12-
|
13-
= help: consider an outer attribute, #[macro_use] mod ...
14-
151
warning: unknown lint: `x5400`
162
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:33
173
|
@@ -186,6 +172,20 @@ warning: unknown lint: `x5100`
186172
LL | #[deny(x5100)] impl S { }
187173
| ^^^^^
188174

175+
warning: macro_escape is a deprecated synonym for macro_use
176+
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:1
177+
|
178+
LL | #[macro_escape]
179+
| ^^^^^^^^^^^^^^^
180+
181+
warning: macro_escape is a deprecated synonym for macro_use
182+
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:503:17
183+
|
184+
LL | mod inner { #![macro_escape] }
185+
| ^^^^^^^^^^^^^^^^
186+
|
187+
= help: consider an outer attribute, #[macro_use] mod ...
188+
189189
warning: `repr` attribute isn't configurable with a literal
190190
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:316:17
191191
|
+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(raw_identifiers)]
12+
#![allow(dead_code, unused_variables, non_camel_case_types, non_upper_case_globals)]
13+
#![deny(async_idents)]
14+
15+
// edition:2015
16+
// run-rustfix
17+
18+
fn r#async() {} //~ ERROR async
19+
//~^ WARN hard error in the 2018 edition
20+
21+
macro_rules! foo {
22+
($foo:ident) => {};
23+
($r#async:expr, r#async) => {};
24+
//~^ ERROR async
25+
//~| ERROR async
26+
//~| WARN hard error in the 2018 edition
27+
//~| WARN hard error in the 2018 edition
28+
}
29+
30+
foo!(async);
31+
32+
mod dont_lint_raw {
33+
fn r#async() {}
34+
}
35+
36+
mod async_trait {
37+
trait r#async {}
38+
//~^ ERROR async
39+
//~| WARN hard error in the 2018 edition
40+
struct MyStruct;
41+
impl r#async for MyStruct {}
42+
//~^ ERROR async
43+
//~| WARN hard error in the 2018 edition
44+
}
45+
46+
mod async_static {
47+
static r#async: u32 = 0;
48+
//~^ ERROR async
49+
//~| WARN hard error in the 2018 edition
50+
}
51+
52+
mod async_const {
53+
const r#async: u32 = 0;
54+
//~^ ERROR async
55+
//~| WARN hard error in the 2018 edition
56+
}
57+
58+
struct Foo;
59+
impl Foo { fn r#async() {} }
60+
//~^ ERROR async
61+
//~| WARN hard error in the 2018 edition
62+
63+
fn main() {
64+
struct r#async {}
65+
//~^ ERROR async
66+
//~| WARN hard error in the 2018 edition
67+
let r#async: r#async = r#async {};
68+
//~^ ERROR async
69+
//~| WARN hard error in the 2018 edition
70+
//~| ERROR async
71+
//~| WARN hard error in the 2018 edition
72+
//~| ERROR async
73+
//~| WARN hard error in the 2018 edition
74+
}
75+
76+
#[macro_export]
77+
macro_rules! produces_async {
78+
() => (pub fn r#async() {})
79+
//~^ ERROR async
80+
//~| WARN hard error in the 2018 edition
81+
}
82+
83+
#[macro_export]
84+
macro_rules! consumes_async {
85+
(r#async) => (1)
86+
//~^ ERROR async
87+
//~| WARN hard error in the 2018 edition
88+
}

0 commit comments

Comments
 (0)