Skip to content

Commit 35e6c65

Browse files
committed
cfg_attr_multi: Feature gate
1 parent 1a867dc commit 35e6c65

16 files changed

+115
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# `cfg_attr_multi`
2+
3+
The tracking issue for this feature is: [#555666]
4+
The RFC for this feature is: [#2539]
5+
6+
[#555666]: https://github.com/rust-lang/rust/issues/555666
7+
[#2539]: https://github.com/rust-lang/rfcs/pull/2539
8+
9+
------------------------
10+
11+
This feature flag lets you put multiple attributes into a `cfg_attr` attribute.
12+
13+
Example:
14+
15+
```rust,ignore
16+
#[cfg_attr(all(), must_use, optimize)]
17+
```
18+
19+
Because `cfg_attr` resolves before procedural macros, this does not affect
20+
macro resolution at all.

src/libsyntax/config.rs

+35-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@
99
// except according to those terms.
1010

1111
use attr::HasAttrs;
12-
use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features, GateIssue};
12+
use feature_gate::{
13+
feature_err,
14+
EXPLAIN_STMT_ATTR_SYNTAX,
15+
Features,
16+
get_features,
17+
GateIssue,
18+
emit_feature_err,
19+
};
1320
use {fold, attr};
1421
use ast;
1522
use source_map::Spanned;
@@ -97,6 +104,13 @@ impl<'a> StripUnconfigured<'a> {
97104
return vec![attr];
98105
}
99106

107+
let gate_cfg_attr_multi = if let Some(ref features) = self.features {
108+
!features.cfg_attr_multi
109+
} else {
110+
false
111+
};
112+
let cfg_attr_span = attr.span;
113+
100114
let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| {
101115
parser.expect(&token::OpenDelim(token::Paren))?;
102116

@@ -123,6 +137,26 @@ impl<'a> StripUnconfigured<'a> {
123137
}
124138
};
125139

140+
// Check feature gate and lint on zero attributes in source. Even if the feature is gated,
141+
// we still compute as if it wasn't, since the emitted error will stop compilation futher
142+
// along the compilation.
143+
match (expanded_attrs.len(), gate_cfg_attr_multi) {
144+
(0, false) => {
145+
// FIXME: Emit unused attribute lint here.
146+
},
147+
(1, _) => {},
148+
(_, true) => {
149+
emit_feature_err(
150+
self.sess,
151+
"cfg_attr_multi",
152+
cfg_attr_span,
153+
GateIssue::Language,
154+
"cfg_attr with zero or more than one attributes is experimental",
155+
);
156+
},
157+
(_, false) => {}
158+
}
159+
126160
if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
127161
// We call `process_cfg_attr` recursively in case there's a
128162
// `cfg_attr` inside of another `cfg_attr`. E.g.

src/libsyntax/feature_gate.rs

+3
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,9 @@ declare_features! (
515515

516516
// Allows `impl Trait` in bindings (`let`, `const`, `static`)
517517
(active, impl_trait_in_bindings, "1.30.0", Some(34511), None),
518+
519+
// #[cfg_attr(predicate, multiple, attributes, here)]
520+
(active, cfg_attr_multi, "1.31.0", Some(555666), None),
518521
);
519522

520523
declare_features! (

src/test/ui/conditional-compilation/cfg-attr-multi-false.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// compile-pass
55

66
#![warn(unused_must_use)]
7+
#![feature(cfg_attr_multi)]
78

89
#[cfg_attr(any(), deprecated, must_use)]
910
struct Struct {}

src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
// compile-flags: --cfg broken
1212

13+
#![feature(cfg_attr_multi)]
1314
#![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental
1415

1516
fn main() { }

src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0658]: no_core is experimental (see issue #29639)
2-
--> $DIR/cfg-attr-multi-invalid-1.rs:13:21
2+
--> $DIR/cfg-attr-multi-invalid-1.rs:14:21
33
|
44
LL | #![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental
55
| ^^^^^^^

src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
// compile-flags: --cfg broken
1212

13+
#![feature(cfg_attr_multi)]
1314
#![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental
1415

1516
fn main() { }

src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0658]: no_core is experimental (see issue #29639)
2-
--> $DIR/cfg-attr-multi-invalid-2.rs:13:29
2+
--> $DIR/cfg-attr-multi-invalid-2.rs:14:29
33
|
44
LL | #![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental
55
| ^^^^^^^

src/test/ui/conditional-compilation/cfg-attr-multi-true.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// compile-pass
66

77
#![warn(unused_must_use)]
8+
#![feature(cfg_attr_multi)]
89

910
#[cfg_attr(all(), deprecated, must_use)]
1011
struct MustUseDeprecated {}

src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
warning: use of deprecated item 'MustUseDeprecated'
2-
--> $DIR/cfg-attr-multi-true.rs:12:6
2+
--> $DIR/cfg-attr-multi-true.rs:13:6
33
|
44
LL | impl MustUseDeprecated { //~ warning: use of deprecated item
55
| ^^^^^^^^^^^^^^^^^
66
|
77
= note: #[warn(deprecated)] on by default
88

99
warning: use of deprecated item 'MustUseDeprecated'
10-
--> $DIR/cfg-attr-multi-true.rs:19:5
10+
--> $DIR/cfg-attr-multi-true.rs:20:5
1111
|
1212
LL | MustUseDeprecated::new(); //~ warning: use of deprecated item
1313
| ^^^^^^^^^^^^^^^^^^^^^^
1414

1515
warning: use of deprecated item 'MustUseDeprecated'
16-
--> $DIR/cfg-attr-multi-true.rs:13:17
16+
--> $DIR/cfg-attr-multi-true.rs:14:17
1717
|
1818
LL | fn new() -> MustUseDeprecated { //~ warning: use of deprecated item
1919
| ^^^^^^^^^^^^^^^^^
2020

2121
warning: use of deprecated item 'MustUseDeprecated'
22-
--> $DIR/cfg-attr-multi-true.rs:14:9
22+
--> $DIR/cfg-attr-multi-true.rs:15:9
2323
|
2424
LL | MustUseDeprecated {} //~ warning: use of deprecated item
2525
| ^^^^^^^^^^^^^^^^^
2626

2727
warning: unused `MustUseDeprecated` which must be used
28-
--> $DIR/cfg-attr-multi-true.rs:19:5
28+
--> $DIR/cfg-attr-multi-true.rs:20:5
2929
|
3030
LL | MustUseDeprecated::new(); //~ warning: use of deprecated item
3131
| ^^^^^^^^^^^^^^^^^^^^^^^^^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// gate-test-cfg_attr_multi
2+
3+
#![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))]
4+
//~^ ERROR cfg_attr with zero or more than one attributes is experimental
5+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #555666)
2+
--> $DIR/feature-gate-cfg-attr-multi-1.rs:3:1
3+
|
4+
LL | #![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: add #![feature(cfg_attr_multi)] to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#![cfg_attr(all(),)]
2+
//~^ ERROR cfg_attr with zero or more than one attributes is experimental
3+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #555666)
2+
--> $DIR/feature-gate-cfg-attr-multi-2.rs:1:1
3+
|
4+
LL | #![cfg_attr(all(),)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: add #![feature(cfg_attr_multi)] to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Test that settingt the featute gate while using its functionality doesn't error.
2+
3+
// compile-pass
4+
5+
#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")]
6+
7+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Test that settingt the featute gate while using its functionality doesn't error.
2+
// Specifically, if there's a cfg-attr *before* the feature gate.
3+
4+
// compile-pass
5+
6+
#![cfg_attr(all(),)]
7+
#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")]
8+
9+
fn main() {}

0 commit comments

Comments
 (0)