Skip to content

Commit fd0e2e8

Browse files
committed
Lint against cfg(any()) and cfg(all())
1 parent d5525a7 commit fd0e2e8

File tree

85 files changed

+581
-445
lines changed

Some content is hidden

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

85 files changed

+581
-445
lines changed

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_parse::parser::{ForceCollect, Parser};
1212
use rustc_parse::{exp, parse_in};
1313
use rustc_session::Session;
1414
use rustc_session::config::ExpectedValues;
15-
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
15+
use rustc_session::lint::builtin::{EMPTY_CFG_PREDICATE, UNEXPECTED_CFGS};
1616
use rustc_session::parse::{ParseSess, feature_err};
1717
use rustc_span::{ErrorGuaranteed, Span, Symbol, sym};
1818
use thin_vec::ThinVec;
@@ -63,14 +63,42 @@ pub fn parse_cfg_entry<S: Stage>(
6363
};
6464
CfgEntry::Not(Box::new(parse_cfg_entry(cx, single)?), list.span)
6565
}
66-
Some(sym::any) => CfgEntry::Any(
67-
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
68-
list.span,
69-
),
70-
Some(sym::all) => CfgEntry::All(
71-
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
72-
list.span,
73-
),
66+
Some(sym::any) => {
67+
if list.is_empty() && !list.span.from_expansion() {
68+
let span = meta.span();
69+
cx.emit_lint(
70+
EMPTY_CFG_PREDICATE,
71+
AttributeLintKind::EmptyCfgPredictate {
72+
predicate_span: span,
73+
predicate: sym::any,
74+
lit: false,
75+
},
76+
span,
77+
);
78+
}
79+
CfgEntry::Any(
80+
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
81+
list.span,
82+
)
83+
}
84+
Some(sym::all) => {
85+
if list.is_empty() && !list.span.from_expansion() {
86+
let span = meta.span();
87+
cx.emit_lint(
88+
EMPTY_CFG_PREDICATE,
89+
AttributeLintKind::EmptyCfgPredictate {
90+
predicate_span: span,
91+
predicate: sym::all,
92+
lit: true,
93+
},
94+
span,
95+
);
96+
}
97+
CfgEntry::All(
98+
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
99+
list.span,
100+
)
101+
}
74102
Some(sym::target) => parse_cfg_entry_target(cx, list, meta.span())?,
75103
Some(sym::version) => parse_cfg_entry_version(cx, list, meta.span())?,
76104
_ => {

compiler/rustc_lint/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ lint_empty_attribute =
256256
*[other] using `{$attr_path}` with an empty list has no effect
257257
}
258258
259+
lint_empty_cfg_predicate = use of empty `cfg({$predicate}())`
260+
.note = in the past, `false` and `true` were not accepted, so this was a common pattern
261+
.suggestion = consider using a boolean literal
262+
259263
-lint_previously_accepted =
260264
this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
261265
lint_enum_intrinsics_mem_discriminant =

compiler/rustc_lint/src/early/diagnostics.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,5 +367,8 @@ pub fn decorate_attribute_lint(
367367
&AttributeLintKind::UnexpectedCfgValue(name, value) => {
368368
check_cfg::unexpected_cfg_value(sess, tcx, name, value).decorate_lint(diag)
369369
}
370+
&AttributeLintKind::EmptyCfgPredictate { predicate_span, predicate, lit } => {
371+
lints::EmptyCfgPredicate { predicate_span, predicate, lit }.decorate_lint(diag)
372+
}
370373
}
371374
}

compiler/rustc_lint/src/lints.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3137,6 +3137,16 @@ pub(crate) struct EmptyAttributeList {
31373137
pub valid_without_list: bool,
31383138
}
31393139

3140+
#[derive(LintDiagnostic)]
3141+
#[diag(lint_empty_cfg_predicate)]
3142+
#[note]
3143+
pub(crate) struct EmptyCfgPredicate {
3144+
#[suggestion(code = "{lit}", applicability = "machine-applicable", style = "verbose")]
3145+
pub predicate_span: Span,
3146+
pub predicate: Symbol,
3147+
pub lit: bool,
3148+
}
3149+
31403150
#[derive(LintDiagnostic)]
31413151
#[diag(lint_invalid_target)]
31423152
#[warning]

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ declare_lint_pass! {
4040
DUPLICATE_MACRO_ATTRIBUTES,
4141
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
4242
ELIDED_LIFETIMES_IN_PATHS,
43+
EMPTY_CFG_PREDICATE,
4344
EXPLICIT_BUILTIN_CFGS_IN_FLAGS,
4445
EXPORTED_PRIVATE_DEPENDENCIES,
4546
FFI_UNWIND_CALLS,
@@ -5368,3 +5369,29 @@ declare_lint! {
53685369
report_in_deps: false,
53695370
};
53705371
}
5372+
5373+
declare_lint! {
5374+
/// The `empty_cfg_predicate` lint detects the use of empty `cfg` predicate lists.
5375+
///
5376+
/// ### Example
5377+
///
5378+
/// ```rust,compile_fail
5379+
/// #![deny(empty_cfg_predicate)]
5380+
/// #[cfg(any())]
5381+
/// fn foo() {}
5382+
///
5383+
/// #[cfg(all())]
5384+
/// fn bar() {}
5385+
/// ```
5386+
///
5387+
/// {{produces}}
5388+
///
5389+
/// ### Explanation
5390+
///
5391+
/// The meaning of `cfg(any())` and `cfg(all())` is not immediately obvious;
5392+
/// `cfg(false)` and `cfg(true)` respectively may be used instead.
5393+
/// In the past, `false` and `true` were not accepted, so this was a common pattern.
5394+
pub EMPTY_CFG_PREDICATE,
5395+
Warn,
5396+
"detects use of empty `cfg(any())` and `cfg(all())`"
5397+
}

compiler/rustc_lint_defs/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,14 @@ pub enum AttributeLintKind {
733733
},
734734
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
735735
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
736+
EmptyCfgPredictate {
737+
/// Span of `any()`/`all()`
738+
predicate_span: Span,
739+
/// Either `any` or `all`
740+
predicate: Symbol,
741+
/// The boolean literal to replace with
742+
lit: bool,
743+
},
736744
}
737745

738746
pub type RegisteredTools = FxIndexSet<Ident>;

src/tools/clippy/tests/ui/empty_line_after/doc_comments.1.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ pub struct EmptyInBlockComment;
125125
pub struct BlockComment;
126126

127127
/// Ignore the empty line inside a cfg_attr'd out attribute
128-
#[cfg_attr(any(), multiline(
128+
#[cfg_attr(false, multiline(
129129
foo = 1
130130

131131
bar = 2

src/tools/clippy/tests/ui/empty_line_after/doc_comments.2.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ pub struct EmptyInBlockComment;
134134
pub struct BlockComment;
135135

136136
/// Ignore the empty line inside a cfg_attr'd out attribute
137-
#[cfg_attr(any(), multiline(
137+
#[cfg_attr(false, multiline(
138138
foo = 1
139139

140140
bar = 2

src/tools/clippy/tests/ui/empty_line_after/doc_comments.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ pub struct EmptyInBlockComment;
137137
pub struct BlockComment;
138138

139139
/// Ignore the empty line inside a cfg_attr'd out attribute
140-
#[cfg_attr(any(), multiline(
140+
#[cfg_attr(false, multiline(
141141
foo = 1
142142
143143
bar = 2

src/tools/clippy/tests/ui/let_and_return.edition2021.fixed

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ use std::cell::RefCell;
99

1010
fn test() -> i32 {
1111
let _y = 0; // no warning
12-
12+
1313
5
1414
//~^ let_and_return
1515
}
1616

1717
fn test_inner() -> i32 {
1818
if true {
19-
19+
2020
5
2121
//~^ let_and_return
2222
} else {
@@ -79,7 +79,7 @@ fn issue_3792() -> String {
7979
let stdin = io::stdin();
8080
// `Stdin::lock` returns `StdinLock<'static>` so `line` doesn't borrow from `stdin`
8181
// https://github.com/rust-lang/rust/pull/93965
82-
82+
8383
stdin.lock().lines().next().unwrap().unwrap()
8484
//~^ let_and_return
8585
}
@@ -174,7 +174,7 @@ mod issue_5729 {
174174

175175
impl<T: Foo + 'static> FooStorage for FooStorageImpl<T> {
176176
fn foo_cloned(&self) -> Arc<dyn Foo> {
177-
177+
178178
(Arc::clone(&self.foo)) as _
179179
//~^ let_and_return
180180
}
@@ -189,7 +189,7 @@ mod issue_11335 {
189189

190190
impl<T> E<T> {
191191
pub fn inner(&self) -> &T {
192-
192+
193193

194194
(match self {
195195
E::A(x) => x,
@@ -212,39 +212,39 @@ fn_in_macro!({
212212

213213
fn issue9150() -> usize {
214214
let x = 1;
215-
#[cfg(any())]
215+
#[cfg(false)]
216216
panic!("can't see me");
217217
x
218218
}
219219

220220
fn issue12801() {
221221
fn left_is_if() -> String {
222-
222+
223223
(if true { "a".to_string() } else { "b".to_string() } + "c")
224224
//~^ let_and_return
225225
}
226226

227227
fn no_par_needed() -> String {
228-
228+
229229
"c".to_string() + if true { "a" } else { "b" }
230230
//~^ let_and_return
231231
}
232232

233233
fn conjunctive_blocks() -> String {
234-
234+
235235
({ "a".to_string() } + "b" + { "c" } + "d")
236236
//~^ let_and_return
237237
}
238238

239239
#[allow(clippy::overly_complex_bool_expr)]
240240
fn other_ops() {
241241
let _ = || {
242-
242+
243243
(if true { 2 } else { 3 } << 4)
244244
//~^ let_and_return
245245
};
246246
let _ = || {
247-
247+
248248
({ true } || { false } && { 2 <= 3 })
249249
//~^ let_and_return
250250
};

0 commit comments

Comments
 (0)