diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 315ed38ad0770..5cc862a58d35a 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1046,7 +1046,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { self.check_id(id); } - fn visit_mac(&mut self, mac: &'ast ast::Mac) { + fn visit_mac(&mut self, mac: &'a ast::Mac) { run_lints!(self, check_mac, mac); } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 023a97e038fcf..142ec7ef7d7b9 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -45,6 +45,7 @@ use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::ast; use syntax::attr; use syntax::source_map::Spanned; +use syntax::edition::Edition; use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes}; use syntax_pos::{BytePos, Span, SyntaxContext}; use syntax::symbol::keywords; @@ -1875,30 +1876,33 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestFunctions { } declare_lint! { - pub ASYNC_IDENTS, + pub KEYWORD_IDENTS, Allow, - "detects `async` being used as an identifier" + "detects edition keywords being used as an identifier" } -/// Checks for uses of `async` as an identifier +/// Checks for uses of edtion keywords used as an identifier #[derive(Clone)] -pub struct Async2018; +pub struct KeywordIdents; -impl LintPass for Async2018 { +impl LintPass for KeywordIdents { fn get_lints(&self) -> LintArray { - lint_array!(ASYNC_IDENTS) + lint_array!(KEYWORD_IDENTS) } } -impl Async2018 { +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)) if ident.as_str() == "async" => { - self.report(cx, span.substitute_dummy(ident.span)) - }, + Some((ident, false)) => { + self.check_ident(cx, ast::Ident { + span: span.substitute_dummy(ident.span), + ..ident + }); + } _ => {}, } TokenTree::Delimited(_, ref delim) => { @@ -1907,29 +1911,9 @@ impl Async2018 { } } } - 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", - ); - - // Don't suggest about raw identifiers if the feature isn't active - 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 { +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()); } @@ -1937,8 +1921,37 @@ impl EarlyLintPass for Async2018 { 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); + let next_edition = match cx.sess.edition() { + Edition::Edition2015 => { + match &ident.as_str()[..] { + "async" | + "try" => Edition::Edition2018, + _ => return, + } + } + + // no new keywords yet for 2018 edition and beyond + _ => return, + }; + + // don't lint `r#foo` + if cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&ident.span) { + return; } + + let mut lint = cx.struct_span_lint( + KEYWORD_IDENTS, + ident.span, + &format!("`{}` is a keyword in the {} edition", + ident.as_str(), + next_edition), + ); + lint.span_suggestion_with_applicability( + ident.span, + "you can use a raw identifier to stay compatible", + format!("r#{}", ident.as_str()), + Applicability::MachineApplicable, + ); + lint.emit() } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 05b11e3ba3a4c..39abfee5fb9ec 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -110,7 +110,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { } add_pre_expansion_builtin!(sess, - Async2018, + KeywordIdents, ); add_early_builtin!(sess, @@ -240,7 +240,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { edition: Some(Edition::Edition2018), }, FutureIncompatibleInfo { - id: LintId::of(ASYNC_IDENTS), + id: LintId::of(KEYWORD_IDENTS), reference: "issue #49716 ", edition: Some(Edition::Edition2018), }, @@ -349,6 +349,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { store.register_renamed("bare_trait_object", "bare_trait_objects"); store.register_renamed("unstable_name_collision", "unstable_name_collisions"); store.register_renamed("unused_doc_comment", "unused_doc_comments"); + store.register_renamed("async_idents", "keyword_idents"); store.register_removed("unknown_features", "replaced by an error"); store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate"); store.register_removed("negate_unsigned", "cast a signed value instead"); diff --git a/src/test/ui/editions/auxiliary/edition-kw-macro-2015.rs b/src/test/ui/editions/auxiliary/edition-kw-macro-2015.rs index 5b8832ddaf27c..9343312fdd84f 100644 --- a/src/test/ui/editions/auxiliary/edition-kw-macro-2015.rs +++ b/src/test/ui/editions/auxiliary/edition-kw-macro-2015.rs @@ -10,7 +10,7 @@ // edition:2015 -#![allow(async_idents)] +#![allow(keyword_idents)] #[macro_export] macro_rules! produces_async { diff --git a/src/test/ui/editions/auxiliary/edition-kw-macro-2018.rs b/src/test/ui/editions/auxiliary/edition-kw-macro-2018.rs index 85ef15858fe91..19a7b91624fe3 100644 --- a/src/test/ui/editions/auxiliary/edition-kw-macro-2018.rs +++ b/src/test/ui/editions/auxiliary/edition-kw-macro-2018.rs @@ -10,7 +10,7 @@ // edition:2018 -#![allow(async_idents)] +#![allow(keyword_idents)] #[macro_export] macro_rules! produces_async { diff --git a/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs b/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs index a9037a50ecb6b..382c7c1f325a3 100644 --- a/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs +++ b/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs @@ -12,7 +12,7 @@ // aux-build:edition-kw-macro-2015.rs // compile-pass -#![allow(async_idents)] +#![allow(keyword_idents)] #[macro_use] extern crate edition_kw_macro_2015; diff --git a/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs b/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs index 911dcd855aad6..46434daaab924 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs +++ b/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs @@ -12,7 +12,7 @@ // aux-build:edition-kw-macro-2015.rs // compile-pass -#![allow(async_idents)] +#![allow(keyword_idents)] #[macro_use] extern crate edition_kw_macro_2015; diff --git a/src/test/ui/rust-2018/async-ident-allowed.stderr b/src/test/ui/rust-2018/async-ident-allowed.stderr index 741c1c70209bc..68d7930e0434a 100644 --- a/src/test/ui/rust-2018/async-ident-allowed.stderr +++ b/src/test/ui/rust-2018/async-ident-allowed.stderr @@ -9,7 +9,7 @@ note: lint level defined here | LL | #![deny(rust_2018_compatibility)] | ^^^^^^^^^^^^^^^^^^^^^^^ - = note: #[deny(async_idents)] implied by #[deny(rust_2018_compatibility)] + = note: #[deny(keyword_idents)] implied by #[deny(rust_2018_compatibility)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! = note: for more information, see issue #49716 diff --git a/src/test/ui/rust-2018/async-ident.fixed b/src/test/ui/rust-2018/async-ident.fixed index 15b8eec3bea99..ef88f835fc83d 100644 --- a/src/test/ui/rust-2018/async-ident.fixed +++ b/src/test/ui/rust-2018/async-ident.fixed @@ -9,7 +9,7 @@ // except according to those terms. #![allow(dead_code, unused_variables, non_camel_case_types, non_upper_case_globals)] -#![deny(async_idents)] +#![deny(keyword_idents)] // edition:2015 // run-rustfix diff --git a/src/test/ui/rust-2018/async-ident.rs b/src/test/ui/rust-2018/async-ident.rs index 6087d2c16423e..069da7ffcdd4d 100644 --- a/src/test/ui/rust-2018/async-ident.rs +++ b/src/test/ui/rust-2018/async-ident.rs @@ -9,7 +9,7 @@ // except according to those terms. #![allow(dead_code, unused_variables, non_camel_case_types, non_upper_case_globals)] -#![deny(async_idents)] +#![deny(keyword_idents)] // edition:2015 // run-rustfix diff --git a/src/test/ui/rust-2018/async-ident.stderr b/src/test/ui/rust-2018/async-ident.stderr index 06d68a38c5f38..b9bb2e254b44e 100644 --- a/src/test/ui/rust-2018/async-ident.stderr +++ b/src/test/ui/rust-2018/async-ident.stderr @@ -7,8 +7,8 @@ LL | fn async() {} //~ ERROR async note: lint level defined here --> $DIR/async-ident.rs:12:9 | -LL | #![deny(async_idents)] - | ^^^^^^^^^^^^ +LL | #![deny(keyword_idents)] + | ^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! = note: for more information, see issue #49716 diff --git a/src/test/ui/rust-2018/try-ident.fixed b/src/test/ui/rust-2018/try-ident.fixed new file mode 100644 index 0000000000000..96a0cd0f8e95b --- /dev/null +++ b/src/test/ui/rust-2018/try-ident.fixed @@ -0,0 +1,21 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix +// compile-pass + +#![warn(rust_2018_compatibility)] + +fn main() { + r#try(); +} + +fn r#try() { +} diff --git a/src/test/ui/rust-2018/try-ident.rs b/src/test/ui/rust-2018/try-ident.rs new file mode 100644 index 0000000000000..ade2e03ff22ba --- /dev/null +++ b/src/test/ui/rust-2018/try-ident.rs @@ -0,0 +1,21 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix +// compile-pass + +#![warn(rust_2018_compatibility)] + +fn main() { + try(); +} + +fn try() { +} diff --git a/src/test/ui/rust-2018/try-ident.stderr b/src/test/ui/rust-2018/try-ident.stderr new file mode 100644 index 0000000000000..72bd81530df76 --- /dev/null +++ b/src/test/ui/rust-2018/try-ident.stderr @@ -0,0 +1,24 @@ +warning: `try` is a keyword in the 2018 edition + --> $DIR/try-ident.rs:17:5 + | +LL | try(); + | ^^^ help: you can use a raw identifier to stay compatible: `r#try` + | +note: lint level defined here + --> $DIR/try-ident.rs:14:9 + | +LL | #![warn(rust_2018_compatibility)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: #[warn(keyword_idents)] implied by #[warn(rust_2018_compatibility)] + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + +warning: `try` is a keyword in the 2018 edition + --> $DIR/try-ident.rs:20:4 + | +LL | fn try() { + | ^^^ help: you can use a raw identifier to stay compatible: `r#try` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 +