diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 56e69b9df9e04..dcae9b1e9ca7e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1923,7 +1923,15 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], let mut features = Features::new(); let mut edition_enabled_features = FxHashMap(); - for &(name, .., f_edition, set) in ACTIVE_FEATURES.iter() { + for &edition in ALL_EDITIONS { + if edition <= crate_edition { + // The `crate_edition` implies its respective umbrella feature-gate + // (i.e. `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). + edition_enabled_features.insert(Symbol::intern(edition.feature_name()), edition); + } + } + + for &(name, .., f_edition, set) in ACTIVE_FEATURES { if let Some(f_edition) = f_edition { if f_edition <= crate_edition { set(&mut features, DUMMY_SP); @@ -1932,6 +1940,8 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } } + // Process the edition umbrella feature-gates first, to ensure + // `edition_enabled_features` is completed before it's queried. for attr in krate_attrs { if !attr.check_name("feature") { continue @@ -1939,28 +1949,22 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], let list = match attr.meta_item_list() { Some(list) => list, - None => { - span_err!(span_handler, attr.span, E0555, - "malformed feature attribute, expected #![feature(...)]"); - continue - } + None => continue, }; for mi in list { let name = if let Some(word) = mi.word() { word.name() } else { - span_err!(span_handler, mi.span, E0556, - "malformed feature, expected just one word"); continue }; if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) { if *edition <= crate_edition { - continue + continue; } - for &(name, .., f_edition, set) in ACTIVE_FEATURES.iter() { + for &(name, .., f_edition, set) in ACTIVE_FEATURES { if let Some(f_edition) = f_edition { if f_edition <= *edition { // FIXME(Manishearth) there is currently no way to set @@ -1970,24 +1974,53 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } } } + } + } + } + + for attr in krate_attrs { + if !attr.check_name("feature") { + continue + } + + let list = match attr.meta_item_list() { + Some(list) => list, + None => { + span_err!(span_handler, attr.span, E0555, + "malformed feature attribute, expected #![feature(...)]"); + continue + } + }; + for mi in list { + let name = if let Some(word) = mi.word() { + word.name() + } else { + span_err!(span_handler, mi.span, E0556, + "malformed feature, expected just one word"); continue + }; + + if let Some(edition) = edition_enabled_features.get(&name) { + struct_span_warn!( + span_handler, + mi.span, + E0705, + "the feature `{}` is included in the Rust {} edition", + name, + edition, + ).emit(); + continue; + } + + if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) { + // Handled in the separate loop above. + continue; } if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) { - if let Some(edition) = edition_enabled_features.get(&name) { - struct_span_warn!( - span_handler, - mi.span, - E0705, - "the feature `{}` is included in the Rust {} edition", - name, - edition, - ).emit(); - } else { - set(&mut features, mi.span); - features.declared_lang_features.push((name, mi.span, None)); - } + set(&mut features, mi.span); + features.declared_lang_features.push((name, mi.span, None)); continue } diff --git a/src/test/run-pass/macro-at-most-once-rep.rs b/src/test/run-pass/macro-at-most-once-rep.rs index dcf2222ba6dea..61c3e781c0867 100644 --- a/src/test/run-pass/macro-at-most-once-rep.rs +++ b/src/test/run-pass/macro-at-most-once-rep.rs @@ -18,7 +18,7 @@ // // This test focuses on non-error cases and making sure the correct number of repetitions happen. -// compile-flags: --edition=2018 +// edition:2018 #![feature(macro_at_most_once_rep)] diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index 21ad5159946fd..f3d39deef1730 100644 --- a/src/test/rustdoc/async-fn.rs +++ b/src/test/rustdoc/async-fn.rs @@ -13,7 +13,7 @@ // FIXME: once `--edition` is stable in rustdoc, remove that `compile-flags` directive -#![feature(rust_2018_preview, async_await, futures_api)] +#![feature(async_await, futures_api)] // @has async_fn/struct.S.html // @has - '//code' 'pub async fn f()' diff --git a/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed index e5b47c70863e5..b64ebed030588 100644 --- a/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed +++ b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed @@ -9,7 +9,7 @@ // except according to those terms. // aux-build:suggestions-not-always-applicable.rs -// compile-flags: --edition 2015 +// edition:2015 // run-rustfix // rustfix-only-machine-applicable // compile-pass diff --git a/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs index e5b47c70863e5..b64ebed030588 100644 --- a/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs +++ b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs @@ -9,7 +9,7 @@ // except according to those terms. // aux-build:suggestions-not-always-applicable.rs -// compile-flags: --edition 2015 +// edition:2015 // run-rustfix // rustfix-only-machine-applicable // compile-pass diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.rs b/src/test/ui-fulldeps/unnecessary-extern-crate.rs index 0811c79b0a4b9..ea3e0587958b1 100644 --- a/src/test/ui-fulldeps/unnecessary-extern-crate.rs +++ b/src/test/ui-fulldeps/unnecessary-extern-crate.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: --edition 2018 +// edition:2018 #![deny(unused_extern_crates)] #![feature(alloc, test, libc)] diff --git a/src/test/ui/E0705.rs b/src/test/ui/E0705.rs index a0ce95e3e02c1..b5fd3cf35f28b 100644 --- a/src/test/ui/E0705.rs +++ b/src/test/ui/E0705.rs @@ -10,9 +10,9 @@ // compile-pass -#![feature(rust_2018_preview)] #![feature(raw_identifiers)] //~^ WARN the feature `raw_identifiers` is included in the Rust 2018 edition +#![feature(rust_2018_preview)] fn main() { let foo = 0; diff --git a/src/test/ui/E0705.stderr b/src/test/ui/E0705.stderr index ebb8dd4975d6f..2aa3077e48c2d 100644 --- a/src/test/ui/E0705.stderr +++ b/src/test/ui/E0705.stderr @@ -1,5 +1,5 @@ warning[E0705]: the feature `raw_identifiers` is included in the Rust 2018 edition - --> $DIR/E0705.rs:14:12 + --> $DIR/E0705.rs:13:12 | LL | #![feature(raw_identifiers)] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.rs b/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.rs index 72043938f5351..104c0886311d0 100644 --- a/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.rs +++ b/src/test/ui/borrowck/borrowck-feature-nll-overrides-migrate.rs @@ -20,7 +20,7 @@ // revisions: zflag edition // [zflag]compile-flags: -Z borrowck=migrate -// [edition]compile-flags: --edition 2018 +// [edition]edition:2018 #![feature(nll)] diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs index e7f2bfbfedba7..bb6b29072e257 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs @@ -23,7 +23,7 @@ // revisions: zflag edition //[zflag]compile-flags: -Z borrowck=migrate -//[edition]compile-flags: --edition 2018 +//[edition]edition:2018 //[zflag] run-pass //[edition] run-pass diff --git a/src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs b/src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs index c39fff2644dfd..3b53fb9fc4283 100644 --- a/src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs +++ b/src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs @@ -14,7 +14,7 @@ // revisions: ast zflags edition //[zflags]compile-flags: -Z borrowck=migrate -Z two-phase-borrows -//[edition]compile-flags: --edition 2018 +//[edition]edition:2018 // run-pass diff --git a/src/test/ui/editions/edition-extern-crate-allowed.rs b/src/test/ui/editions/edition-extern-crate-allowed.rs index 7368564e250d1..75761a0b5b971 100644 --- a/src/test/ui/editions/edition-extern-crate-allowed.rs +++ b/src/test/ui/editions/edition-extern-crate-allowed.rs @@ -9,7 +9,7 @@ // except according to those terms. // aux-build:edition-extern-crate-allowed.rs -// compile-flags: --edition 2015 +// edition:2015 // compile-pass #![warn(rust_2018_idioms)] diff --git a/src/test/ui/editions/edition-feature-ok.rs b/src/test/ui/editions/edition-feature-ok.rs index 3a3a6ff95f97e..5896e9a071591 100644 --- a/src/test/ui/editions/edition-feature-ok.rs +++ b/src/test/ui/editions/edition-feature-ok.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:--edition 2018 // compile-pass #![feature(rust_2018_preview)] diff --git a/src/test/ui/editions/edition-feature-redundant.rs b/src/test/ui/editions/edition-feature-redundant.rs new file mode 100644 index 0000000000000..d20873f5e1163 --- /dev/null +++ b/src/test/ui/editions/edition-feature-redundant.rs @@ -0,0 +1,17 @@ +// 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. + +// edition:2018 +// compile-pass + +#![feature(rust_2018_preview)] +//~^ WARN the feature `rust_2018_preview` is included in the Rust 2018 edition + +fn main() {} diff --git a/src/test/ui/editions/edition-feature-redundant.stderr b/src/test/ui/editions/edition-feature-redundant.stderr new file mode 100644 index 0000000000000..ccf7b21fbc5c0 --- /dev/null +++ b/src/test/ui/editions/edition-feature-redundant.stderr @@ -0,0 +1,6 @@ +warning[E0705]: the feature `rust_2018_preview` is included in the Rust 2018 edition + --> $DIR/edition-feature-redundant.rs:14:12 + | +LL | #![feature(rust_2018_preview)] + | ^^^^^^^^^^^^^^^^^ + diff --git a/src/test/ui/in-band-lifetimes/elided-lifetimes.fixed b/src/test/ui/in-band-lifetimes/elided-lifetimes.fixed index c9381e6350f2b..153e500374688 100644 --- a/src/test/ui/in-band-lifetimes/elided-lifetimes.fixed +++ b/src/test/ui/in-band-lifetimes/elided-lifetimes.fixed @@ -9,7 +9,7 @@ // except according to those terms. // run-rustfix -// compile-flags: --edition 2018 +// edition:2018 #![allow(unused)] #![deny(elided_lifetimes_in_paths)] diff --git a/src/test/ui/in-band-lifetimes/elided-lifetimes.rs b/src/test/ui/in-band-lifetimes/elided-lifetimes.rs index 8151dd01a98d8..41aa7e1a7b7b9 100644 --- a/src/test/ui/in-band-lifetimes/elided-lifetimes.rs +++ b/src/test/ui/in-band-lifetimes/elided-lifetimes.rs @@ -9,7 +9,7 @@ // except according to those terms. // run-rustfix -// compile-flags: --edition 2018 +// edition:2018 #![allow(unused)] #![deny(elided_lifetimes_in_paths)] diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs index fd7925ea3eeeb..63a4ef16a2581 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs +++ b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs @@ -12,7 +12,7 @@ // with the feature flag. // gate-test-macro_at_most_once_rep -// compile-flags: --edition=2015 +// edition:2015 #![feature(macro_at_most_once_rep)] diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.rs b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.rs index 90bc19739b872..64848d050cb1e 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.rs +++ b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.rs @@ -10,7 +10,7 @@ // Test behavior of `?` macro _kleene op_ under the 2015 edition. Namely, it doesn't exist. -// compile-flags: --edition=2015 +// edition:2015 macro_rules! bar { ($(a)?) => {} //~ERROR expected `*` or `+` diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.rs b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.rs index 2e06b4bd5c240..a7857991079fe 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.rs +++ b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.rs @@ -11,7 +11,7 @@ // Test behavior of `?` macro _separator_ under the 2015 edition. Namely, `?` can be used as a // separator, but you get a migration warning for the edition. -// compile-flags: --edition=2015 +// edition:2015 // compile-pass #![warn(rust_2018_compatibility)] diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs b/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs index f3107d4f1e4f6..ffabf9bcdf685 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs +++ b/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs @@ -11,7 +11,7 @@ // Feature gate test for macro_at_most_once_rep under 2018 edition. // gate-test-macro_at_most_once_rep -// compile-flags: --edition=2018 +// edition:2018 macro_rules! foo { ($(a)?) => {} diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.rs b/src/test/ui/macros/macro-at-most-once-rep-2018.rs index 958a7e0cdf444..5dabe8d952801 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018.rs +++ b/src/test/ui/macros/macro-at-most-once-rep-2018.rs @@ -10,7 +10,7 @@ // Tests that `?` is a Kleene op and not a macro separator in the 2018 edition. -// compile-flags: --edition=2018 +// edition:2018 #![feature(macro_at_most_once_rep)] diff --git a/src/test/ui/removing-extern-crate.fixed b/src/test/ui/removing-extern-crate.fixed index 83b35cec80956..90427b061b652 100644 --- a/src/test/ui/removing-extern-crate.fixed +++ b/src/test/ui/removing-extern-crate.fixed @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: --edition 2018 +// edition:2018 // aux-build:removing-extern-crate.rs // run-rustfix // compile-pass diff --git a/src/test/ui/removing-extern-crate.rs b/src/test/ui/removing-extern-crate.rs index 29479086460e6..3905d285becb5 100644 --- a/src/test/ui/removing-extern-crate.rs +++ b/src/test/ui/removing-extern-crate.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: --edition 2018 +// edition:2018 // aux-build:removing-extern-crate.rs // run-rustfix // compile-pass diff --git a/src/test/ui/rust-2018/async-ident-allowed.rs b/src/test/ui/rust-2018/async-ident-allowed.rs index fd4eae1f9b54c..3bc468483bda2 100644 --- a/src/test/ui/rust-2018/async-ident-allowed.rs +++ b/src/test/ui/rust-2018/async-ident-allowed.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: --edition 2015 +// edition:2015 #![deny(rust_2018_compatibility)] diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed index 4f99c1240f8f4..fc81ab08f624d 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed @@ -10,12 +10,11 @@ // aux-build:edition-lint-paths.rs // run-rustfix -// compile-flags:--edition 2018 +// edition:2018 // The "normal case". Ideally we would remove the `extern crate` here, // but we don't. -#![feature(rust_2018_preview)] #![deny(rust_2018_idioms)] #![allow(dead_code)] diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs index 9c1235a296799..72751f2080cc9 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs @@ -10,12 +10,11 @@ // aux-build:edition-lint-paths.rs // run-rustfix -// compile-flags:--edition 2018 +// edition:2018 // The "normal case". Ideally we would remove the `extern crate` here, // but we don't. -#![feature(rust_2018_preview)] #![deny(rust_2018_idioms)] #![allow(dead_code)] diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr index b3afa2bd1d592..0ecfd4e4a2ca3 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr @@ -1,18 +1,18 @@ error: unused extern crate - --> $DIR/extern-crate-idiomatic-in-2018.rs:22:1 + --> $DIR/extern-crate-idiomatic-in-2018.rs:21:1 | LL | extern crate edition_lint_paths; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it | note: lint level defined here - --> $DIR/extern-crate-idiomatic-in-2018.rs:19:9 + --> $DIR/extern-crate-idiomatic-in-2018.rs:18:9 | LL | #![deny(rust_2018_idioms)] | ^^^^^^^^^^^^^^^^ = note: #[deny(unused_extern_crates)] implied by #[deny(rust_2018_idioms)] error: `extern crate` is not idiomatic in the new edition - --> $DIR/extern-crate-idiomatic-in-2018.rs:25:1 + --> $DIR/extern-crate-idiomatic-in-2018.rs:24:1 | LL | extern crate edition_lint_paths as bar; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use` diff --git a/src/test/ui/rust-2018/issue-52202-use-suggestions.rs b/src/test/ui/rust-2018/issue-52202-use-suggestions.rs index 5acd19c2471e6..deb80411bbf64 100644 --- a/src/test/ui/rust-2018/issue-52202-use-suggestions.rs +++ b/src/test/ui/rust-2018/issue-52202-use-suggestions.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: --edition 2018 +// edition:2018 // The local `use` suggestion should start with `crate::` (but the // standard-library suggestions should not, obviously).