Skip to content

Commit

Permalink
Auto merge of #52375 - oli-obk:the_early_lint_pass_gets_the_worm, r=M…
Browse files Browse the repository at this point in the history
…anishearth

Lint `async` identifiers in 2018 preparation mode

r? @Manishearth

fixes #49716
  • Loading branch information
bors committed Jul 18, 2018
2 parents 29ee654 + 68c93e7 commit 12ed235
Show file tree
Hide file tree
Showing 14 changed files with 599 additions and 183 deletions.
328 changes: 169 additions & 159 deletions src/librustc/lint/context.rs

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ pub trait EarlyLintPass: LintPass {
fn check_lifetime(&mut self, _: &EarlyContext, _: &ast::Lifetime) { }
fn check_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { }
fn check_attribute(&mut self, _: &EarlyContext, _: &ast::Attribute) { }
fn check_mac_def(&mut self, _: &EarlyContext, _: &ast::MacroDef, _id: ast::NodeId) { }
fn check_mac(&mut self, _: &EarlyContext, _: &ast::Mac) { }

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



/// Identifies a lint known to the compiler.
#[derive(Clone, Copy, Debug)]
pub struct LintId {
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,10 @@ where
return Err(CompileIncomplete::Stopped);
}

time(sess, "pre ast expansion lint checks", || {
lint::check_ast_crate(sess, &krate, true)
});

let mut resolver = Resolver::new(
sess,
cstore,
Expand Down Expand Up @@ -1134,7 +1138,7 @@ where
});

time(sess, "early lint checks", || {
lint::check_ast_crate(sess, &krate)
lint::check_ast_crate(sess, &krate, false)
});

// Discard hygiene data, which isn't required after lowering to HIR.
Expand Down
68 changes: 68 additions & 0 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext};

use std::collections::HashSet;

use syntax::tokenstream::{TokenTree, TokenStream};
use syntax::ast;
use syntax::attr;
use syntax::codemap::Spanned;
Expand Down Expand Up @@ -1784,3 +1785,70 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestFunctions {
};
}
}

declare_lint! {
pub ASYNC_IDENTS,
Allow,
"detects `async` being used as an identifier"
}

/// Checks for uses of `async` as an identifier
#[derive(Clone)]
pub struct Async2018;

impl LintPass for Async2018 {
fn get_lints(&self) -> LintArray {
lint_array!(ASYNC_IDENTS)
}
}

impl Async2018 {
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)) if ident.as_str() == "async" => {
self.report(cx, span.substitute_dummy(ident.span))
},
_ => {},
}
TokenTree::Delimited(_, ref delim) => {
self.check_tokens(cx, delim.tts.clone().into())
},
}
}
}
fn report(&mut self, cx: &EarlyContext, span: Span) {
// don't lint `r#async`
if cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&span) {
return;
}
let mut lint = cx.struct_span_lint(
ASYNC_IDENTS,
span,
"`async` is a keyword in the 2018 edition",
);
lint.span_suggestion_with_applicability(
span,
"you can use a raw identifier to stay compatible",
"r#async".to_string(),
Applicability::MachineApplicable,
);
lint.emit()
}
}

impl EarlyLintPass for Async2018 {
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) {
if ident.as_str() == "async" {
self.report(cx, ident.span);
}
}
}
17 changes: 17 additions & 0 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
)
}

macro_rules! add_pre_expansion_builtin {
($sess:ident, $($name:ident),*,) => (
{$(
store.register_early_pass($sess, false, box $name);
)*}
)
}

macro_rules! add_early_builtin_with_new {
($sess:ident, $($name:ident),*,) => (
{$(
Expand All @@ -97,6 +105,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
)
}

add_pre_expansion_builtin!(sess,
Async2018,
);

add_early_builtin!(sess,
UnusedParens,
UnusedImportBraces,
Expand Down Expand Up @@ -215,6 +227,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
reference: "issue #35896 <https://github.com/rust-lang/rust/issues/35896>",
edition: Some(Edition::Edition2018),
},
FutureIncompatibleInfo {
id: LintId::of(ASYNC_IDENTS),
reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
edition: Some(Edition::Edition2018),
},
FutureIncompatibleInfo {
id: LintId::of(SAFE_EXTERN_STATICS),
reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
Expand Down
18 changes: 9 additions & 9 deletions src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
--> $DIR/lint-plugin-forbid-attrs.rs:20:9
|
LL | #![forbid(test_lint)]
| --------- `forbid` level set here
...
LL | #[allow(test_lint)]
| ^^^^^^^^^ overruled by previous forbid

error: item is named 'lintme'
--> $DIR/lint-plugin-forbid-attrs.rs:18:1
|
Expand All @@ -10,15 +19,6 @@ note: lint level defined here
LL | #![forbid(test_lint)]
| ^^^^^^^^^

error[E0453]: allow(test_lint) overruled by outer forbid(test_lint)
--> $DIR/lint-plugin-forbid-attrs.rs:20:9
|
LL | #![forbid(test_lint)]
| --------- `forbid` level set here
...
LL | #[allow(test_lint)]
| ^^^^^^^^^ overruled by previous forbid

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0453`.
1 change: 1 addition & 0 deletions src/test/ui/auxiliary/edition-kw-macro-2015.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// edition:2015

#![feature(raw_identifiers)]
#![allow(async_idents)]

#[macro_export]
macro_rules! produces_async {
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/auxiliary/edition-kw-macro-2018.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// edition:2018

#![feature(raw_identifiers)]
#![allow(async_idents)]

#[macro_export]
macro_rules! produces_async {
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/edition-keywords-2015-2015-expansion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// compile-pass

#![feature(raw_identifiers)]
#![allow(async_idents)]

#[macro_use]
extern crate edition_kw_macro_2015;
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/edition-keywords-2018-2015-expansion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// compile-pass

#![feature(raw_identifiers)]
#![allow(async_idents)]

#[macro_use]
extern crate edition_kw_macro_2015;
Expand Down
28 changes: 14 additions & 14 deletions src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
Original file line number Diff line number Diff line change
@@ -1,17 +1,3 @@
warning: macro_escape is a deprecated synonym for macro_use
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:1
|
LL | #[macro_escape]
| ^^^^^^^^^^^^^^^

warning: macro_escape is a deprecated synonym for macro_use
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:503:17
|
LL | mod inner { #![macro_escape] }
| ^^^^^^^^^^^^^^^^
|
= help: consider an outer attribute, #[macro_use] mod ...

warning: unknown lint: `x5400`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:33
|
Expand Down Expand Up @@ -186,6 +172,20 @@ warning: unknown lint: `x5100`
LL | #[deny(x5100)] impl S { }
| ^^^^^

warning: macro_escape is a deprecated synonym for macro_use
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:1
|
LL | #[macro_escape]
| ^^^^^^^^^^^^^^^

warning: macro_escape is a deprecated synonym for macro_use
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:503:17
|
LL | mod inner { #![macro_escape] }
| ^^^^^^^^^^^^^^^^
|
= help: consider an outer attribute, #[macro_use] mod ...

warning: `repr` attribute isn't configurable with a literal
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:316:17
|
Expand Down
88 changes: 88 additions & 0 deletions src/test/ui/rust-2018/async-ident.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(raw_identifiers)]
#![allow(dead_code, unused_variables, non_camel_case_types, non_upper_case_globals)]
#![deny(async_idents)]

// edition:2015
// run-rustfix

fn r#async() {} //~ ERROR async
//~^ WARN hard error in the 2018 edition

macro_rules! foo {
($foo:ident) => {};
($r#async:expr, r#async) => {};
//~^ ERROR async
//~| ERROR async
//~| WARN hard error in the 2018 edition
//~| WARN hard error in the 2018 edition
}

foo!(async);

mod dont_lint_raw {
fn r#async() {}
}

mod async_trait {
trait r#async {}
//~^ ERROR async
//~| WARN hard error in the 2018 edition
struct MyStruct;
impl r#async for MyStruct {}
//~^ ERROR async
//~| WARN hard error in the 2018 edition
}

mod async_static {
static r#async: u32 = 0;
//~^ ERROR async
//~| WARN hard error in the 2018 edition
}

mod async_const {
const r#async: u32 = 0;
//~^ ERROR async
//~| WARN hard error in the 2018 edition
}

struct Foo;
impl Foo { fn r#async() {} }
//~^ ERROR async
//~| WARN hard error in the 2018 edition

fn main() {
struct r#async {}
//~^ ERROR async
//~| WARN hard error in the 2018 edition
let r#async: r#async = r#async {};
//~^ ERROR async
//~| WARN hard error in the 2018 edition
//~| ERROR async
//~| WARN hard error in the 2018 edition
//~| ERROR async
//~| WARN hard error in the 2018 edition
}

#[macro_export]
macro_rules! produces_async {
() => (pub fn r#async() {})
//~^ ERROR async
//~| WARN hard error in the 2018 edition
}

#[macro_export]
macro_rules! consumes_async {
(r#async) => (1)
//~^ ERROR async
//~| WARN hard error in the 2018 edition
}
Loading

0 comments on commit 12ed235

Please sign in to comment.