@@ -223,6 +223,26 @@ declare_clippy_lint! {
223
223
"a wildcard enum match arm using `_`"
224
224
}
225
225
226
+ declare_clippy_lint ! {
227
+ /// **What it does:** Checks for wildcard pattern used with others patterns in same match arm.
228
+ ///
229
+ /// **Why is this bad?** Wildcard pattern already covers any other pattern as it will match anyway.
230
+ /// It makes the code less readable, especially to spot wildcard pattern use in match arm.
231
+ ///
232
+ /// **Known problems:** None.
233
+ ///
234
+ /// **Example:**
235
+ /// ```rust
236
+ /// match "foo" {
237
+ /// "a" => {},
238
+ /// "bar" | _ => {},
239
+ /// }
240
+ /// ```
241
+ pub PATS_WITH_WILD_MATCH_ARM ,
242
+ restriction,
243
+ "a wildcard pattern used with others patterns in same match arm"
244
+ }
245
+
226
246
declare_lint_pass ! ( Matches => [
227
247
SINGLE_MATCH ,
228
248
MATCH_REF_PATS ,
@@ -231,7 +251,8 @@ declare_lint_pass!(Matches => [
231
251
MATCH_OVERLAPPING_ARM ,
232
252
MATCH_WILD_ERR_ARM ,
233
253
MATCH_AS_REF ,
234
- WILDCARD_ENUM_MATCH_ARM
254
+ WILDCARD_ENUM_MATCH_ARM ,
255
+ PATS_WITH_WILD_MATCH_ARM
235
256
] ) ;
236
257
237
258
impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for Matches {
@@ -246,6 +267,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches {
246
267
check_wild_err_arm ( cx, ex, arms) ;
247
268
check_wild_enum_match ( cx, ex, arms) ;
248
269
check_match_as_ref ( cx, ex, arms, expr) ;
270
+ check_pats_wild_match ( cx, ex, arms, expr) ;
249
271
}
250
272
if let ExprKind :: Match ( ref ex, ref arms, _) = expr. kind {
251
273
check_match_ref_pats ( cx, ex, arms, expr) ;
@@ -664,6 +686,25 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>],
664
686
}
665
687
}
666
688
689
+ fn check_pats_wild_match ( cx : & LateContext < ' _ , ' _ > , _ex : & Expr , arms : & [ Arm ] , _expr : & Expr ) {
690
+ for arm in arms {
691
+ if let PatKind :: Or ( ref fields) = arm. pat . kind {
692
+ // look for multiple fields where one at least matches Wild pattern
693
+ if fields. len ( ) > 1 && fields. into_iter ( ) . any ( |pat| is_wild ( pat) ) {
694
+ span_lint_and_sugg (
695
+ cx,
696
+ PATS_WITH_WILD_MATCH_ARM ,
697
+ arm. pat . span ,
698
+ "wildcard pattern covers any other pattern as it will match anyway. Consider replacing with wildcard pattern only" ,
699
+ "try this" ,
700
+ "_" . to_string ( ) ,
701
+ Applicability :: MachineApplicable ,
702
+ )
703
+ }
704
+ }
705
+ }
706
+ }
707
+
667
708
/// Gets all arms that are unbounded `PatRange`s.
668
709
fn all_ranges < ' a , ' tcx > ( cx : & LateContext < ' a , ' tcx > , arms : & ' tcx [ Arm < ' _ > ] ) -> Vec < SpannedRange < Constant > > {
669
710
arms. iter ( )
0 commit comments