Skip to content

Commit cf79ee7

Browse files
committed
Warn against cfg(any()) and cfg(all())
1 parent 5bc3450 commit cf79ee7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+255
-181
lines changed

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,5 +233,8 @@ attr_parsing_unused_multiple =
233233
.suggestion = remove this attribute
234234
.note = attribute also specified here
235235
236+
attr_parsing_use_cfg_boolean_lit = use of empty `cfg({$pred}())`
237+
.suggestion = consider using a boolean literal
238+
236239
attr_parsing_whole_archive_needs_static =
237240
linking modifier `whole-archive` is only compatible with `static` linking kind

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,32 @@ pub fn parse_cfg_entry<S: Stage>(
6666
};
6767
CfgEntry::Not(Box::new(parse_cfg_entry(cx, single)?), list.span)
6868
}
69-
Some(sym::any) => CfgEntry::Any(
70-
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
71-
list.span,
72-
),
73-
Some(sym::all) => CfgEntry::All(
74-
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
75-
list.span,
76-
),
69+
Some(sym::any) => {
70+
if list.is_empty() {
71+
cx.emit_warn(session_diagnostics::UseCfgBooleanLit {
72+
span: meta.span(),
73+
lit: false,
74+
pred: sym::any,
75+
});
76+
}
77+
CfgEntry::Any(
78+
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
79+
list.span,
80+
)
81+
}
82+
Some(sym::all) => {
83+
if list.is_empty() {
84+
cx.emit_warn(session_diagnostics::UseCfgBooleanLit {
85+
span: meta.span(),
86+
lit: true,
87+
pred: sym::all,
88+
});
89+
}
90+
CfgEntry::All(
91+
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
92+
list.span,
93+
)
94+
}
7795
Some(sym::target) => parse_cfg_entry_target(cx, list, meta.span())?,
7896
Some(sym::version) => parse_cfg_entry_version(cx, list, meta.span())?,
7997
_ => {

compiler/rustc_attr_parsing/src/attributes/cfg_old.rs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -165,16 +165,32 @@ pub fn eval_condition(
165165
// The unwraps below may look dangerous, but we've already asserted
166166
// that they won't fail with the loop above.
167167
match cfg.name() {
168-
Some(sym::any) => mis
169-
.iter()
170-
// We don't use any() here, because we want to evaluate all cfg condition
171-
// as eval_condition can (and does) extra checks
172-
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
173-
Some(sym::all) => mis
174-
.iter()
175-
// We don't use all() here, because we want to evaluate all cfg condition
176-
// as eval_condition can (and does) extra checks
177-
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
168+
Some(sym::any) => {
169+
if mis.is_empty() {
170+
dcx.emit_warn(session_diagnostics::UseCfgBooleanLit {
171+
span: cfg.span,
172+
lit: false,
173+
pred: sym::any,
174+
});
175+
}
176+
mis.iter()
177+
// We don't use any() here, because we want to evaluate all cfg condition
178+
// as eval_condition can (and does) extra checks
179+
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval))
180+
}
181+
Some(sym::all) => {
182+
if mis.is_empty() {
183+
dcx.emit_warn(session_diagnostics::UseCfgBooleanLit {
184+
span: cfg.span,
185+
lit: true,
186+
pred: sym::all,
187+
});
188+
}
189+
mis.iter()
190+
// We don't use all() here, because we want to evaluate all cfg condition
191+
// as eval_condition can (and does) extra checks
192+
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval))
193+
}
178194
Some(sym::not) => {
179195
let [mi] = mis.as_slice() else {
180196
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ pub trait Stage: Sized + 'static + Sealed {
271271

272272
fn parsers() -> &'static GroupType<Self>;
273273

274+
fn emit_warn<'sess>(&self, sess: &'sess Session, diag: impl for<'x> Diagnostic<'x, ()>);
275+
274276
fn emit_err<'sess>(
275277
&self,
276278
sess: &'sess Session,
@@ -298,6 +300,10 @@ impl Stage for Early {
298300
self.should_emit().emit_err(sess.dcx().create_err(diag))
299301
}
300302

303+
fn emit_warn<'sess>(&self, sess: &'sess Session, diag: impl for<'x> Diagnostic<'x, ()>) {
304+
sess.dcx().emit_warn(diag);
305+
}
306+
301307
fn should_emit(&self) -> ShouldEmit {
302308
self.emit_errors
303309
}
@@ -323,6 +329,10 @@ impl Stage for Late {
323329
tcx.dcx().emit_err(diag)
324330
}
325331

332+
fn emit_warn<'sess>(&self, tcx: &'sess Session, diag: impl for<'x> Diagnostic<'x, ()>) {
333+
tcx.dcx().emit_warn(diag);
334+
}
335+
326336
fn should_emit(&self) -> ShouldEmit {
327337
ShouldEmit::ErrorsAndLints
328338
}
@@ -375,6 +385,10 @@ pub struct AcceptContext<'f, 'sess, S: Stage> {
375385
}
376386

377387
impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
388+
pub(crate) fn emit_warn(&self, diag: impl for<'x> Diagnostic<'x, ()>) {
389+
self.stage.emit_warn(&self.sess, diag)
390+
}
391+
378392
pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
379393
self.stage.emit_err(&self.sess, diag)
380394
}

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,16 @@ pub(crate) struct NakedFunctionIncompatibleAttribute {
538538
pub attr: String,
539539
}
540540

541+
#[derive(Diagnostic)]
542+
#[diag(attr_parsing_use_cfg_boolean_lit)]
543+
pub(crate) struct UseCfgBooleanLit {
544+
#[primary_span]
545+
#[suggestion(code = "{lit}")]
546+
pub span: Span,
547+
pub lit: bool,
548+
pub pred: Symbol,
549+
}
550+
541551
#[derive(Diagnostic)]
542552
#[diag(attr_parsing_link_ordinal_out_of_range)]
543553
#[note]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@ build-pass
22

3-
#[cfg_attr(all(), unsafe(no_mangle))]
3+
#[cfg_attr(true, unsafe(no_mangle))]
44
fn a() {}
55

66
fn main() {}

tests/ui/cfg/conditional-compilation-struct-11085.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ struct Foo {
1111
}
1212

1313
struct Foo2 {
14-
#[cfg(all())]
14+
#[cfg(true)]
1515
foo: isize,
1616
}
1717

tests/ui/cfg/conditional-compile.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,5 @@ mod test_methods {
151151
}
152152
}
153153

154-
#[cfg(any())]
154+
#[cfg(false)]
155155
mod nonexistent_file; // Check that unconfigured non-inline modules are not loaded or parsed.

tests/ui/cfg/empty-any-all.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//! Check that we suggest `cfg(any())` -> `false` and `cfg(all())` -> true
2+
//@ check-pass
3+
4+
#[cfg(any())] //~ WARN: use of empty `cfg(any())`
5+
struct A;
6+
#[cfg(all())] //~ WARN: use of empty `cfg(all())`
7+
struct B;
8+
9+
fn main() {}

tests/ui/cfg/empty-any-all.stderr

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
warning: use of empty `cfg(any())`
2+
--> $DIR/empty-any-all.rs:4:7
3+
|
4+
LL | #[cfg(any())]
5+
| ^^^^^ help: consider using a boolean literal: `false`
6+
7+
warning: use of empty `cfg(all())`
8+
--> $DIR/empty-any-all.rs:6:7
9+
|
10+
LL | #[cfg(all())]
11+
| ^^^^^ help: consider using a boolean literal: `true`
12+
13+
warning: 2 warnings emitted
14+

0 commit comments

Comments
 (0)