Skip to content

Commit 4248898

Browse files
jamie-osecclubby789
authored andcommitted
Lint against empty cfg(any()/all())
1 parent a774017 commit 4248898

38 files changed

Lines changed: 235 additions & 57 deletions

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_errors::{Applicability, Diagnostic, PResult, msg};
77
use rustc_feature::{Features, GatedCfg, find_gated_cfg};
88
use rustc_hir::attrs::CfgEntry;
99
use rustc_hir::{AttrPath, RustcVersion, Target};
10+
use rustc_lint_defs::builtin::EMPTY_CFG_PREDICATE;
1011
use rustc_parse::parser::{ForceCollect, Parser, Recovery};
1112
use rustc_parse::{exp, parse_in};
1213
use rustc_session::Session;
@@ -19,6 +20,7 @@ use thin_vec::ThinVec;
1920

2021
use crate::attributes::AttributeSafety;
2122
use crate::context::{AcceptContext, ShouldEmit};
23+
use crate::diagnostics::EmptyCfgPredictate;
2224
use crate::parser::{
2325
AllowExprMetavar, ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser,
2426
};
@@ -92,14 +94,42 @@ pub fn parse_cfg_entry(
9294
};
9395
CfgEntry::Not(Box::new(parse_cfg_entry(cx, single)?), list.span)
9496
}
95-
Some(sym::any) => CfgEntry::Any(
96-
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
97-
list.span,
98-
),
99-
Some(sym::all) => CfgEntry::All(
100-
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
101-
list.span,
102-
),
97+
Some(sym::any) => {
98+
if list.is_empty() && !list.span.from_expansion() {
99+
let span = meta.span();
100+
cx.emit_lint(
101+
EMPTY_CFG_PREDICATE,
102+
EmptyCfgPredictate {
103+
predicate_span: span,
104+
predicate: sym::any,
105+
lit: false,
106+
},
107+
span,
108+
);
109+
}
110+
CfgEntry::Any(
111+
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
112+
list.span,
113+
)
114+
}
115+
Some(sym::all) => {
116+
if list.is_empty() && !list.span.from_expansion() {
117+
let span = meta.span();
118+
cx.emit_lint(
119+
EMPTY_CFG_PREDICATE,
120+
EmptyCfgPredictate {
121+
predicate_span: span,
122+
predicate: sym::all,
123+
lit: true,
124+
},
125+
span,
126+
);
127+
}
128+
CfgEntry::All(
129+
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
130+
list.span,
131+
)
132+
}
103133
Some(sym::target) => parse_cfg_entry_target(cx, list, meta.span())?,
104134
Some(sym::version) => parse_cfg_entry_version(cx, list, meta.span())?,
105135
_ => {

compiler/rustc_attr_parsing/src/diagnostics.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,23 @@ pub(crate) mod unexpected_cfg_value {
782782
}
783783
}
784784

785+
#[derive(Diagnostic)]
786+
#[diag("use of empty `cfg({$predicate}())`")]
787+
#[note(
788+
"this used to be a common pattern before `cfg(true)` and `cfg(false)` were added to the language in Rust 1.88"
789+
)]
790+
pub(crate) struct EmptyCfgPredictate {
791+
#[suggestion(
792+
"consider using a boolean literal",
793+
code = "{lit}",
794+
applicability = "machine-applicable",
795+
style = "verbose"
796+
)]
797+
pub predicate_span: Span,
798+
pub predicate: Symbol,
799+
pub lit: bool,
800+
}
801+
785802
#[derive(Diagnostic)]
786803
pub(crate) enum InvalidOnClause {
787804
#[diag("empty `on`-clause in `#[rustc_on_unimplemented]`", code = E0232)]

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pub mod hardwired {
4646
DUPLICATE_MACRO_ATTRIBUTES,
4747
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
4848
ELIDED_LIFETIMES_IN_PATHS,
49+
EMPTY_CFG_PREDICATE,
4950
EXPLICIT_BUILTIN_CFGS_IN_FLAGS,
5051
EXPORTED_PRIVATE_DEPENDENCIES,
5152
FFI_UNWIND_CALLS,
@@ -5578,3 +5579,31 @@ declare_lint! {
55785579
"usage of `unsafe` code and other potentially unsound constructs",
55795580
@eval_always = true
55805581
}
5582+
5583+
declare_lint! {
5584+
/// The `empty_cfg_predicate` lint detects the use of empty `cfg` predicate lists.
5585+
///
5586+
/// ### Example
5587+
///
5588+
/// ```rust,compile_fail
5589+
/// #![deny(empty_cfg_predicate)]
5590+
/// #[cfg(any())]
5591+
/// fn foo() {}
5592+
///
5593+
/// #[cfg(all())]
5594+
/// fn bar() {}
5595+
/// ```
5596+
///
5597+
/// {{produces}}
5598+
///
5599+
/// ### Explanation
5600+
///
5601+
/// The meaning of `cfg(any())` and `cfg(all())` is not immediately obvious;
5602+
/// `cfg(false)` and `cfg(true)` respectively may be used instead.
5603+
/// This used to be a common pattern before `cfg(true)` and `cfg(false)`
5604+
/// were added to the language in Rust 1.88
5605+
pub EMPTY_CFG_PREDICATE,
5606+
Warn,
5607+
"detects use of empty `cfg(any())` and `cfg(all())`",
5608+
@msrv = "1.88.0";
5609+
}

library/std/src/os/raw/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ macro_rules! alias_core_ffi {
99
($($t:ident)*) => {$(
1010
#[stable(feature = "raw_os", since = "1.1.0")]
1111
#[doc = include_str!(concat!("../../../../core/src/ffi/", stringify!($t), ".md"))]
12-
#[doc(cfg(all()))]
12+
#[doc(cfg(true))]
1313
pub type $t = core::ffi::$t;
1414
)*}
1515
}

library/std/src/os/windows/raw.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ use crate::os::raw::c_void;
77
#[stable(feature = "raw_ext", since = "1.1.0")]
88
pub type HANDLE = *mut c_void;
99
#[cfg(target_pointer_width = "32")]
10-
#[doc(cfg(all()))]
10+
#[doc(cfg(true))]
1111
#[stable(feature = "raw_ext", since = "1.1.0")]
1212
pub type SOCKET = u32;
1313
#[cfg(target_pointer_width = "64")]
14-
#[doc(cfg(all()))]
14+
#[doc(cfg(true))]
1515
#[stable(feature = "raw_ext", since = "1.1.0")]
1616
pub type SOCKET = u64;

src/tools/clippy/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.fixed

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ mod field_attributes {
4444
// https://github.com/rust-lang/rust-clippy/pull/13737#discussion_r1874539800
4545
mod cfgs_between_fields {
4646
#[allow(clippy::non_minimal_cfg)]
47+
#[allow(empty_cfg_predicate)]
4748
fn cfg_all() {
4849
struct S {
4950
a: i32,
@@ -62,6 +63,7 @@ mod cfgs_between_fields {
6263
};
6364
}
6465

66+
#[allow(empty_cfg_predicate)]
6567
fn cfg_any() {
6668
struct S {
6769
a: i32,

src/tools/clippy/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ mod field_attributes {
4444
// https://github.com/rust-lang/rust-clippy/pull/13737#discussion_r1874539800
4545
mod cfgs_between_fields {
4646
#[allow(clippy::non_minimal_cfg)]
47+
#[allow(empty_cfg_predicate)]
4748
fn cfg_all() {
4849
struct S {
4950
a: i32,
@@ -62,6 +63,7 @@ mod cfgs_between_fields {
6263
};
6364
}
6465

66+
#[allow(empty_cfg_predicate)]
6567
fn cfg_any() {
6668
struct S {
6769
a: i32,

src/tools/clippy/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ LL ~ expn_depth: if condition { 1 } else { 0 },
4040
|
4141

4242
error: struct constructor field order is inconsistent with struct definition field order
43-
--> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:56:13
43+
--> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:57:13
4444
|
4545
LL | / d: 0,
4646
LL | |
@@ -61,7 +61,7 @@ LL ~ d: 0,
6161
|
6262

6363
error: struct constructor field order is inconsistent with struct definition field order
64-
--> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:74:13
64+
--> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:76:13
6565
|
6666
LL | / d: 0,
6767
LL | |

src/tools/clippy/tests/ui/double_must_use_unfixable.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
#![expect(clippy::result_unit_err)]
33
#![feature(never_type)]
44

5-
#[cfg_attr(all(), must_use, deprecated)]
5+
#[cfg_attr(true, must_use, deprecated)]
66
pub fn issue_12320() -> Result<(), ()> {
77
//~^ double_must_use
88
unimplemented!();
99
}
1010

11-
#[cfg_attr(all(), deprecated, must_use)]
11+
#[cfg_attr(true, deprecated, must_use)]
1212
pub fn issue_12320_2() -> Result<(), ()> {
1313
//~^ double_must_use
1414
unimplemented!();

src/tools/clippy/tests/ui/double_must_use_unfixable.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ LL | pub fn issue_12320() -> Result<(), ()> {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
help: remove `must_use`
8-
--> tests/ui/double_must_use_unfixable.rs:5:19
8+
--> tests/ui/double_must_use_unfixable.rs:5:18
99
|
10-
LL | #[cfg_attr(all(), must_use, deprecated)]
11-
| ^^^^^^^^
10+
LL | #[cfg_attr(true, must_use, deprecated)]
11+
| ^^^^^^^^
1212
= note: alternatively, you may add an explicit reason to the `must_use` attribute
1313
= note: `-D clippy::double-must-use` implied by `-D warnings`
1414
= help: to override `-D warnings` add `#[allow(clippy::double_must_use)]`
@@ -20,10 +20,10 @@ LL | pub fn issue_12320_2() -> Result<(), ()> {
2020
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2121
|
2222
help: remove `must_use`
23-
--> tests/ui/double_must_use_unfixable.rs:11:31
23+
--> tests/ui/double_must_use_unfixable.rs:11:30
2424
|
25-
LL | #[cfg_attr(all(), deprecated, must_use)]
26-
| ^^^^^^^^
25+
LL | #[cfg_attr(true, deprecated, must_use)]
26+
| ^^^^^^^^
2727
= note: alternatively, you may add an explicit reason to the `must_use` attribute
2828

2929
error: aborting due to 2 previous errors

0 commit comments

Comments
 (0)