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

Lint async identifiers in 2018 preparation mode #52375

Merged
merged 4 commits into from
Jul 18, 2018
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
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 @@ -80,6 +80,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 @@ -94,6 +102,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 @@ -211,6 +223,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