--- /dev/null
+# `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
// 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;
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))?;
}
};
+ // 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.
// 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! (
// compile-pass
#![warn(unused_must_use)]
+#![feature(cfg_attr_multi)]
#[cfg_attr(any(), deprecated, must_use)]
struct Struct {}
//
// compile-flags: --cfg broken
+#![feature(cfg_attr_multi)]
#![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental
fn main() { }
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
| ^^^^^^^
//
// compile-flags: --cfg broken
+#![feature(cfg_attr_multi)]
#![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental
fn main() { }
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
| ^^^^^^^
// compile-pass
#![warn(unused_must_use)]
+#![feature(cfg_attr_multi)]
#[cfg_attr(all(), deprecated, must_use)]
struct MustUseDeprecated {}
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
| ^^^^^^^^^^^^^^^^^
= 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
--- /dev/null
+#![cfg_attr(all(),)]
+//~^ ERROR cfg_attr with zero or more than one attributes is experimental
+fn main() {}
--- /dev/null
+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`.
--- /dev/null
+// 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() {}
--- /dev/null
+// 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() {}