From 0f009795171c7ea9977110e6aeebe72c67f559c7 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 16 Aug 2018 02:06:26 +0300 Subject: syntax: process all edition features before other features. --- src/libsyntax/feature_gate.rs | 44 +++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 56e69b9df9e..74db42ead7d 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1923,7 +1923,7 @@ 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 &(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 +1932,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 +1941,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,8 +1966,36 @@ 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 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) { -- cgit 1.4.1-3-g733a5 From 2c4402638e5b24179165110eedd11aca55a0a9e4 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 16 Aug 2018 02:09:12 +0300 Subject: syntax: also warn about edition "umbrella" features being implied by --edition. --- src/libsyntax/feature_gate.rs | 35 ++++++++++++++-------- src/test/rustdoc/async-fn.rs | 2 +- src/test/ui/editions/edition-feature-ok.rs | 1 - src/test/ui/editions/edition-feature-redundant.rs | 17 +++++++++++ .../ui/editions/edition-feature-redundant.stderr | 6 ++++ .../rust-2018/extern-crate-idiomatic-in-2018.fixed | 1 - .../ui/rust-2018/extern-crate-idiomatic-in-2018.rs | 1 - .../extern-crate-idiomatic-in-2018.stderr | 6 ++-- 8 files changed, 49 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/editions/edition-feature-redundant.rs create mode 100644 src/test/ui/editions/edition-feature-redundant.stderr (limited to 'src/libsyntax') diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 74db42ead7d..dcae9b1e9ca 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1923,6 +1923,14 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], let mut features = Features::new(); let mut edition_enabled_features = FxHashMap(); + 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 { @@ -1993,25 +2001,26 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], 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/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index 21ad5159946..f3d39deef17 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/editions/edition-feature-ok.rs b/src/test/ui/editions/edition-feature-ok.rs index 3a3a6ff95f9..5896e9a0715 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 00000000000..d20873f5e11 --- /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 00000000000..ccf7b21fbc5 --- /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/rust-2018/extern-crate-idiomatic-in-2018.fixed b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed index 4f99c1240f8..c7c73e90988 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 @@ -15,7 +15,6 @@ // 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 9c1235a2967..ee37a3d766a 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 @@ -15,7 +15,6 @@ // 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 b3afa2bd1d5..0ecfd4e4a2c 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` -- cgit 1.4.1-3-g733a5