@@ -338,6 +338,30 @@ declare_clippy_lint! {
338
338
"ensures that all `allow` and `expect` attributes have a reason"
339
339
}
340
340
341
+ declare_clippy_lint ! {
342
+ /// ### What it does
343
+ /// Checks for `any` and `all` combinators in `cfg` with only one condition.
344
+ ///
345
+ /// ### Why is this bad?
346
+ /// If there is only one condition, no need to wrap it into `any` or `all` combinators.
347
+ ///
348
+ /// ### Example
349
+ /// ```rust
350
+ /// #[cfg(any(unix))]
351
+ /// pub struct Bar;
352
+ /// ```
353
+ ///
354
+ /// Use instead:
355
+ /// ```rust
356
+ /// #[cfg(unix)]
357
+ /// pub struct Bar;
358
+ /// ```
359
+ #[ clippy:: version = "1.71.0" ]
360
+ pub NON_MINIMAL_CFG ,
361
+ style,
362
+ "ensure that all `cfg(any())` and `cfg(all())` have more than one condition"
363
+ }
364
+
341
365
declare_lint_pass ! ( Attributes => [
342
366
ALLOW_ATTRIBUTES_WITHOUT_REASON ,
343
367
INLINE_ALWAYS ,
@@ -651,6 +675,7 @@ impl_lint_pass!(EarlyAttributes => [
651
675
MISMATCHED_TARGET_OS ,
652
676
EMPTY_LINE_AFTER_OUTER_ATTR ,
653
677
EMPTY_LINE_AFTER_DOC_COMMENTS ,
678
+ NON_MINIMAL_CFG ,
654
679
] ) ;
655
680
656
681
impl EarlyLintPass for EarlyAttributes {
@@ -661,6 +686,7 @@ impl EarlyLintPass for EarlyAttributes {
661
686
fn check_attribute ( & mut self , cx : & EarlyContext < ' _ > , attr : & Attribute ) {
662
687
check_deprecated_cfg_attr ( cx, attr, & self . msrv ) ;
663
688
check_mismatched_target_os ( cx, attr) ;
689
+ check_minimal_cfg_condition ( cx, attr) ;
664
690
}
665
691
666
692
extract_msrv_attr ! ( EarlyContext ) ;
@@ -750,6 +776,40 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr
750
776
}
751
777
}
752
778
779
+ fn check_nested_cfg ( cx : & EarlyContext < ' _ > , items : & [ NestedMetaItem ] ) {
780
+ for item in items. iter ( ) {
781
+ if let NestedMetaItem :: MetaItem ( meta) = item {
782
+ if !meta. has_name ( sym:: any) && !meta. has_name ( sym:: all) {
783
+ continue ;
784
+ }
785
+ if let MetaItemKind :: List ( list) = & meta. kind {
786
+ check_nested_cfg ( cx, list) ;
787
+ if list. len ( ) == 1 {
788
+ span_lint_and_then (
789
+ cx,
790
+ NON_MINIMAL_CFG ,
791
+ meta. span ,
792
+ "unneeded sub `cfg` when there is only one condition" ,
793
+ |diag| {
794
+ if let Some ( snippet) = snippet_opt ( cx, list[ 0 ] . span ( ) ) {
795
+ diag. span_suggestion ( meta. span , "try" , snippet, Applicability :: MaybeIncorrect ) ;
796
+ }
797
+ } ,
798
+ ) ;
799
+ }
800
+ }
801
+ }
802
+ }
803
+ }
804
+
805
+ fn check_minimal_cfg_condition ( cx : & EarlyContext < ' _ > , attr : & Attribute ) {
806
+ if attr. has_name ( sym:: cfg) &&
807
+ let Some ( items) = attr. meta_item_list ( )
808
+ {
809
+ check_nested_cfg ( cx, & items) ;
810
+ }
811
+ }
812
+
753
813
fn check_mismatched_target_os ( cx : & EarlyContext < ' _ > , attr : & Attribute ) {
754
814
fn find_os ( name : & str ) -> Option < & ' static str > {
755
815
UNIX_SYSTEMS
0 commit comments