Skip to content

Commit 06d836b

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

File tree

86 files changed

+567
-436
lines changed

Some content is hidden

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

86 files changed

+567
-436
lines changed

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 10 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
}

compiler/rustc_lint/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ 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+
.suggestion = consider using a boolean literal
261+
259262
-lint_previously_accepted =
260263
this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
261264
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
suggestion: lints::UnsafeAttrOutsideUnsafeSuggestion { left, right },
368368
}
369369
.decorate_lint(diag),
370+
&AttributeLintKind::EmptyCfgPredictate { predicate_span, predicate, lit } => {
371+
lints::EmptyCfgPredicate { predicate_span, predicate, lit }.decorate_lint(diag)
372+
}
370373
}
371374
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use rustc_ast::{Attribute, MetaItemInner, MetaItemKind};
2+
use rustc_session::{declare_lint, declare_lint_pass};
3+
use rustc_span::sym;
4+
5+
use crate::{EarlyContext, EarlyLintPass, LintContext, lints};
6+
7+
declare_lint! {
8+
/// The `empty_cfg_predicate` lint detects the use of empty `cfg` predicate lists.
9+
///
10+
/// ### Example
11+
///
12+
/// ```rust,compile_fail
13+
/// #![deny(empty_cfg_predicate)]
14+
/// #[cfg(any())]
15+
/// fn foo() {}
16+
///
17+
/// #[cfg(all())]
18+
/// fn bar() {}
19+
/// ```
20+
///
21+
/// {{produces}}
22+
///
23+
/// ### Explanation
24+
///
25+
/// The meaning of `cfg(any())` and `cfg(all())` is not immediately obvious;
26+
/// `cfg(false)` and `cfg(true)` respectively may be used instead.
27+
pub EMPTY_CFG_PREDICATE,
28+
Warn,
29+
"detects use of empty `cfg(any())` and `cfg(all())`"
30+
}
31+
32+
declare_lint_pass!(EmptyCfgPredicate => [EMPTY_CFG_PREDICATE]);
33+
34+
impl EarlyLintPass for EmptyCfgPredicate {
35+
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
36+
if attr.has_any_name(&[sym::cfg, sym::cfg_attr])
37+
&& let Some(items) = attr.meta_item_list()
38+
&& let Some(predicate) = items.get(0)
39+
{
40+
check_predicate(cx, predicate);
41+
}
42+
}
43+
}
44+
45+
fn check_predicate(cx: &EarlyContext<'_>, predicate: &MetaItemInner) {
46+
if let MetaItemInner::MetaItem(predicate) = predicate
47+
&& let MetaItemKind::List(mis) = &predicate.kind
48+
{
49+
match predicate.name() {
50+
Some(predicate_name @ (sym::any | sym::all)) => {
51+
if mis.is_empty() {
52+
let span = predicate.span;
53+
cx.emit_span_lint(
54+
EMPTY_CFG_PREDICATE,
55+
span,
56+
lints::EmptyCfgPredicate {
57+
predicate_span: span,
58+
predicate: predicate_name,
59+
lit: predicate_name == sym::all,
60+
},
61+
);
62+
} else {
63+
for item in mis {
64+
check_predicate(cx, item);
65+
}
66+
}
67+
}
68+
Some(sym::not) => {
69+
for item in mis {
70+
check_predicate(cx, item);
71+
}
72+
}
73+
_ => (),
74+
}
75+
}
76+
}

compiler/rustc_lint/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ mod default_could_be_derived;
4040
mod deref_into_dyn_supertrait;
4141
mod drop_forget_useless;
4242
mod early;
43+
mod empty_cfg_predicate;
4344
mod enum_intrinsics_non_enums;
4445
mod errors;
4546
mod expect;
@@ -89,6 +90,7 @@ use dangling::*;
8990
use default_could_be_derived::DefaultCouldBeDerived;
9091
use deref_into_dyn_supertrait::*;
9192
use drop_forget_useless::*;
93+
use empty_cfg_predicate::*;
9294
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
9395
use for_loops_over_fallibles::*;
9496
use function_cast_as_integer::*;
@@ -157,6 +159,7 @@ early_lint_methods!(
157159
pub BuiltinCombinedPreExpansionLintPass,
158160
[
159161
KeywordIdents: KeywordIdents,
162+
EmptyCfgPredicate: EmptyCfgPredicate,
160163
]
161164
]
162165
);

compiler/rustc_lint/src/lints.rs

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

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

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
attribute_name_span: Span,
734734
sugg_spans: (Span, Span),
735735
},
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

0 commit comments

Comments
 (0)