diff options
| author | Havvy (Ryan Scheel) <ryan.havvy@gmail.com> | 2018-10-04 04:55:47 -0700 |
|---|---|---|
| committer | Havvy (Ryan Scheel) <ryan.havvy@gmail.com> | 2018-10-07 02:08:24 -0700 |
| commit | 35e6c65628a537ad92a38b562a6f9e2de1887b5b (patch) | |
| tree | 6ed810ae66c532fd72490e98594fb39c09f2445a | |
| parent | 1a867dc346a0b9ea5abd8a8504f1908f42ff2dd2 (diff) | |
| download | rust-35e6c65628a537ad92a38b562a6f9e2de1887b5b.tar.gz rust-35e6c65628a537ad92a38b562a6f9e2de1887b5b.zip | |
cfg_attr_multi: Feature gate
16 files changed, 115 insertions, 8 deletions
diff --git a/src/doc/unstable-book/src/language-features/cfg-attr-multi.md b/src/doc/unstable-book/src/language-features/cfg-attr-multi.md new file mode 100644 index 00000000000..759a28c4f5f --- /dev/null +++ b/src/doc/unstable-book/src/language-features/cfg-attr-multi.md @@ -0,0 +1,20 @@ +# `cfg_attr_multi` + +The tracking issue for this feature is: [#555666] +The RFC for this feature is: [#2539] + +[#555666]: https://github.com/rust-lang/rust/issues/555666 +[#2539]: https://github.com/rust-lang/rfcs/pull/2539 + +------------------------ + +This feature flag lets you put multiple attributes into a `cfg_attr` attribute. + +Example: + +```rust,ignore +#[cfg_attr(all(), must_use, optimize)] +``` + +Because `cfg_attr` resolves before procedural macros, this does not affect +macro resolution at all. \ No newline at end of file diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 7a85f628536..e611eb86dc1 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -9,7 +9,14 @@ // except according to those terms. use attr::HasAttrs; -use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features, GateIssue}; +use feature_gate::{ + feature_err, + EXPLAIN_STMT_ATTR_SYNTAX, + Features, + get_features, + GateIssue, + emit_feature_err, +}; use {fold, attr}; use ast; use source_map::Spanned; @@ -97,6 +104,13 @@ impl<'a> StripUnconfigured<'a> { return vec![attr]; } + let gate_cfg_attr_multi = if let Some(ref features) = self.features { + !features.cfg_attr_multi + } else { + false + }; + let cfg_attr_span = attr.span; + let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| { parser.expect(&token::OpenDelim(token::Paren))?; @@ -123,6 +137,26 @@ impl<'a> StripUnconfigured<'a> { } }; + // Check feature gate and lint on zero attributes in source. Even if the feature is gated, + // we still compute as if it wasn't, since the emitted error will stop compilation futher + // along the compilation. + match (expanded_attrs.len(), gate_cfg_attr_multi) { + (0, false) => { + // FIXME: Emit unused attribute lint here. + }, + (1, _) => {}, + (_, true) => { + emit_feature_err( + self.sess, + "cfg_attr_multi", + cfg_attr_span, + GateIssue::Language, + "cfg_attr with zero or more than one attributes is experimental", + ); + }, + (_, false) => {} + } + if attr::cfg_matches(&cfg_predicate, self.sess, self.features) { // We call `process_cfg_attr` recursively in case there's a // `cfg_attr` inside of another `cfg_attr`. E.g. diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index adbe2f9d439..7707bbaa8b0 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -515,6 +515,9 @@ declare_features! ( // Allows `impl Trait` in bindings (`let`, `const`, `static`) (active, impl_trait_in_bindings, "1.30.0", Some(34511), None), + + // #[cfg_attr(predicate, multiple, attributes, here)] + (active, cfg_attr_multi, "1.31.0", Some(555666), None), ); declare_features! ( diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs index ff7a47e0839..84bd33fc0e7 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs @@ -4,6 +4,7 @@ // compile-pass #![warn(unused_must_use)] +#![feature(cfg_attr_multi)] #[cfg_attr(any(), deprecated, must_use)] struct Struct {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs index a9ddbf7d80d..d4c3186a6eb 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs @@ -10,6 +10,7 @@ // // compile-flags: --cfg broken +#![feature(cfg_attr_multi)] #![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental fn main() { } diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr index 344a05a4fec..bf68d92cc0b 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr @@ -1,5 +1,5 @@ error[E0658]: no_core is experimental (see issue #29639) - --> $DIR/cfg-attr-multi-invalid-1.rs:13:21 + --> $DIR/cfg-attr-multi-invalid-1.rs:14:21 | LL | #![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental | ^^^^^^^ diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs index 211eb08f08e..bee6b7d4886 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs @@ -10,6 +10,7 @@ // // compile-flags: --cfg broken +#![feature(cfg_attr_multi)] #![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental fn main() { } diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr index 54854d2e29d..5c72a400e0b 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr @@ -1,5 +1,5 @@ error[E0658]: no_core is experimental (see issue #29639) - --> $DIR/cfg-attr-multi-invalid-2.rs:13:29 + --> $DIR/cfg-attr-multi-invalid-2.rs:14:29 | LL | #![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental | ^^^^^^^ diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs index 4b9a8d46b9b..a31dde00c7c 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs @@ -5,6 +5,7 @@ // compile-pass #![warn(unused_must_use)] +#![feature(cfg_attr_multi)] #[cfg_attr(all(), deprecated, must_use)] struct MustUseDeprecated {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr index 21634ee4f26..37cb3de06c0 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr @@ -1,5 +1,5 @@ warning: use of deprecated item 'MustUseDeprecated' - --> $DIR/cfg-attr-multi-true.rs:12:6 + --> $DIR/cfg-attr-multi-true.rs:13:6 | LL | impl MustUseDeprecated { //~ warning: use of deprecated item | ^^^^^^^^^^^^^^^^^ @@ -7,25 +7,25 @@ LL | impl MustUseDeprecated { //~ warning: use of deprecated item = note: #[warn(deprecated)] on by default warning: use of deprecated item 'MustUseDeprecated' - --> $DIR/cfg-attr-multi-true.rs:19:5 + --> $DIR/cfg-attr-multi-true.rs:20:5 | LL | MustUseDeprecated::new(); //~ warning: use of deprecated item | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'MustUseDeprecated' - --> $DIR/cfg-attr-multi-true.rs:13:17 + --> $DIR/cfg-attr-multi-true.rs:14:17 | LL | fn new() -> MustUseDeprecated { //~ warning: use of deprecated item | ^^^^^^^^^^^^^^^^^ warning: use of deprecated item 'MustUseDeprecated' - --> $DIR/cfg-attr-multi-true.rs:14:9 + --> $DIR/cfg-attr-multi-true.rs:15:9 | LL | MustUseDeprecated {} //~ warning: use of deprecated item | ^^^^^^^^^^^^^^^^^ warning: unused `MustUseDeprecated` which must be used - --> $DIR/cfg-attr-multi-true.rs:19:5 + --> $DIR/cfg-attr-multi-true.rs:20:5 | LL | MustUseDeprecated::new(); //~ warning: use of deprecated item | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.rs new file mode 100644 index 00000000000..9515380bc28 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.rs @@ -0,0 +1,5 @@ +// gate-test-cfg_attr_multi + +#![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))] +//~^ ERROR cfg_attr with zero or more than one attributes is experimental +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.stderr b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.stderr new file mode 100644 index 00000000000..23c09c913f4 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.stderr @@ -0,0 +1,11 @@ +error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #555666) + --> $DIR/feature-gate-cfg-attr-multi-1.rs:3:1 + | +LL | #![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_attr_multi)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.rs new file mode 100644 index 00000000000..cf02432274b --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.rs @@ -0,0 +1,3 @@ +#![cfg_attr(all(),)] +//~^ ERROR cfg_attr with zero or more than one attributes is experimental +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.stderr b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.stderr new file mode 100644 index 00000000000..d8f4acd12d7 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.stderr @@ -0,0 +1,11 @@ +error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #555666) + --> $DIR/feature-gate-cfg-attr-multi-2.rs:1:1 + | +LL | #![cfg_attr(all(),)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_attr_multi)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-1.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-1.rs new file mode 100644 index 00000000000..e4737926e7a --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-1.rs @@ -0,0 +1,7 @@ +// Test that settingt the featute gate while using its functionality doesn't error. + +// compile-pass + +#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")] + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-2.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-2.rs new file mode 100644 index 00000000000..df740541f55 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-2.rs @@ -0,0 +1,9 @@ +// Test that settingt the featute gate while using its functionality doesn't error. +// Specifically, if there's a cfg-attr *before* the feature gate. + +// compile-pass + +#![cfg_attr(all(),)] +#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")] + +fn main() {} |
