@@ -72,11 +72,65 @@ pub(super) fn check_match<'tcx>(
7272 && let Some ( b0) = find_bool_lit ( first_arm. body )
7373 && let Some ( b1) = find_bool_lit ( last_arm. body )
7474 && b0 != b1
75- && ( first_arm. guard . is_none ( ) || middle_arms. is_empty ( ) )
76- && cx. tcx . hir_attrs ( first_arm. hir_id ) . is_empty ( )
77- && middle_arms. iter ( ) . all ( |arm| {
78- cx. tcx . hir_attrs ( arm. hir_id ) . is_empty ( ) && arm. guard . is_none ( ) && find_bool_lit ( arm. body ) == Some ( b0)
79- } )
75+ // We handle two cases:
76+ && (
77+ // - There are no middle arms, i.e., 2 arms in total
78+ //
79+ // In that case, the first arm may or may not have a guard, because this:
80+ // ```rs
81+ // match e {
82+ // Either::Left $(if $guard)|+ => true, // or `false`, but then we'll need `!matches!(..)`
83+ // _ => false,
84+ // }
85+ // ```
86+ // can always become this:
87+ // ```rs
88+ // matches!(e, Either::Left $(if $guard)|+)
89+ // ```
90+ middle_arms. is_empty ( )
91+
92+ // - (added in #6216) There are middle arms
93+ //
94+ // In that case, neither they nor the first arm may have guards
95+ // -- otherwise, they couldn't be combined into an or-pattern in `matches!`
96+ //
97+ // This:
98+ // ```rs
99+ // match e {
100+ // Either3::First => true,
101+ // Either3::Second => true,
102+ // _ /* matches `Either3::Third` */ => false,
103+ // }
104+ // ```
105+ // can become this:
106+ // ```rs
107+ // matches!(e, Either3::First | Either3::Second)
108+ // ```
109+ //
110+ // But this:
111+ // ```rs
112+ // match e {
113+ // Either3::First if X => true,
114+ // Either3::Second => true,
115+ // _ => false,
116+ // }
117+ // ```
118+ // cannot be transformed.
119+ //
120+ // We set an additional constraint of all of them needing to return the same bool,
121+ // so we don't lint things like:
122+ // ```rs
123+ // match e {
124+ // Either3::First => true,
125+ // Either3::Second => false,
126+ // _ => false,
127+ // }
128+ // ```
129+ // This is not *strictly* necessary, but it simplifies the logic a bit
130+ || arms_without_last. iter ( ) . all ( |arm| {
131+ cx. tcx . hir_attrs ( arm. hir_id ) . is_empty ( ) && arm. guard . is_none ( ) && find_bool_lit ( arm. body ) == Some ( b0)
132+ } )
133+ )
80134 {
81135 if !is_wild ( last_arm. pat ) {
82136 return false ;
0 commit comments