@@ -292,6 +292,30 @@ declare_clippy_lint! {
292
292
"ensures that all `allow` and `expect` attributes have a reason"
293
293
}
294
294
295
+ declare_clippy_lint ! {
296
+ /// ### What it does
297
+ /// Checks for `any` and `all` combinators in `cfg` with only one condition.
298
+ ///
299
+ /// ### Why is this bad?
300
+ /// If there is only one condition, no need to wrap it into `any` or `all` combinators.
301
+ ///
302
+ /// ### Example
303
+ /// ```rust
304
+ /// #[cfg(any(unix))]
305
+ /// pub struct Bar;
306
+ /// ```
307
+ ///
308
+ /// Use instead:
309
+ /// ```rust
310
+ /// #[cfg(unix)]
311
+ /// pub struct Bar;
312
+ /// ```
313
+ #[ clippy:: version = "1.71.0" ]
314
+ pub UNIQUE_CFG_CONDITION ,
315
+ style,
316
+ "ensure that all `cfg(any())` and `cfg(all())` have more than one condition"
317
+ }
318
+
295
319
declare_lint_pass ! ( Attributes => [
296
320
ALLOW_ATTRIBUTES_WITHOUT_REASON ,
297
321
INLINE_ALWAYS ,
@@ -604,6 +628,7 @@ impl_lint_pass!(EarlyAttributes => [
604
628
DEPRECATED_CFG_ATTR ,
605
629
MISMATCHED_TARGET_OS ,
606
630
EMPTY_LINE_AFTER_OUTER_ATTR ,
631
+ UNIQUE_CFG_CONDITION ,
607
632
] ) ;
608
633
609
634
impl EarlyLintPass for EarlyAttributes {
@@ -614,6 +639,7 @@ impl EarlyLintPass for EarlyAttributes {
614
639
fn check_attribute ( & mut self , cx : & EarlyContext < ' _ > , attr : & Attribute ) {
615
640
check_deprecated_cfg_attr ( cx, attr, & self . msrv ) ;
616
641
check_mismatched_target_os ( cx, attr) ;
642
+ check_unique_cfg_condition ( cx, attr) ;
617
643
}
618
644
619
645
extract_msrv_attr ! ( EarlyContext ) ;
@@ -690,6 +716,40 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr
690
716
}
691
717
}
692
718
719
+ fn check_nested_cfg ( cx : & EarlyContext < ' _ > , items : & [ NestedMetaItem ] ) {
720
+ for item in items. iter ( ) {
721
+ if let NestedMetaItem :: MetaItem ( meta) = item {
722
+ if !meta. has_name ( sym:: any) && !meta. has_name ( sym:: all) {
723
+ continue ;
724
+ }
725
+ if let MetaItemKind :: List ( list) = & meta. kind {
726
+ check_nested_cfg ( cx, list) ;
727
+ if list. len ( ) == 1 {
728
+ span_lint_and_then (
729
+ cx,
730
+ UNIQUE_CFG_CONDITION ,
731
+ meta. span ,
732
+ "unneeded sub `cfg` when there is only one condition" ,
733
+ |diag| {
734
+ if let Some ( snippet) = snippet_opt ( cx, list[ 0 ] . span ( ) ) {
735
+ diag. span_suggestion ( meta. span , "try" , snippet, Applicability :: MaybeIncorrect ) ;
736
+ }
737
+ } ,
738
+ ) ;
739
+ }
740
+ }
741
+ }
742
+ }
743
+ }
744
+
745
+ fn check_unique_cfg_condition ( cx : & EarlyContext < ' _ > , attr : & Attribute ) {
746
+ if attr. has_name ( sym:: cfg) &&
747
+ let Some ( items) = attr. meta_item_list ( )
748
+ {
749
+ check_nested_cfg ( cx, & items) ;
750
+ }
751
+ }
752
+
693
753
fn check_mismatched_target_os ( cx : & EarlyContext < ' _ > , attr : & Attribute ) {
694
754
fn find_os ( name : & str ) -> Option < & ' static str > {
695
755
UNIX_SYSTEMS
0 commit comments