@@ -140,6 +140,23 @@ fn check_opt_like<'a>(
140140 ty : Ty < ' a > ,
141141 els : Option < & Expr < ' _ > > ,
142142) {
143+ // We want to suggest to exclude an arm that contains only wildcards or forms the exhaustive
144+ // match with the second branch, without enum variants in matches.
145+ if !contains_only_wilds ( arms[ 1 ] . pat ) && !form_exhaustive_matches ( cx, ty, arms[ 0 ] . pat , arms[ 1 ] . pat ) {
146+ return ;
147+ }
148+
149+ let mut paths_and_types = Vec :: new ( ) ;
150+ if !collect_pat_paths ( & mut paths_and_types, cx, arms[ 1 ] . pat , ty) {
151+ return ;
152+ }
153+
154+ if paths_and_types. iter ( ) . all ( |info| in_candidate_enum ( cx, info) ) {
155+ report_single_pattern ( cx, ex, arms, expr, els) ;
156+ }
157+ }
158+
159+ fn in_candidate_enum < ' a > ( cx : & LateContext < ' a > , path_info : & ( String , Ty < ' _ > ) ) -> bool {
143160 // list of candidate `Enum`s we know will never get any more members
144161 let candidates = & [
145162 ( & paths:: COW , "Borrowed" ) ,
@@ -151,29 +168,13 @@ fn check_opt_like<'a>(
151168 ( & paths:: RESULT , "Ok" ) ,
152169 ] ;
153170
154- // We want to suggest to exclude an arm that contains only wildcards or forms the exhaustive
155- // match with the second branch, without enum variants in matches.
156- if !contains_only_wilds ( arms[ 1 ] . pat ) && !form_exhaustive_matches ( arms[ 0 ] . pat , arms[ 1 ] . pat ) {
157- return ;
158- }
159-
160- let mut paths_and_types = Vec :: new ( ) ;
161- if !collect_pat_paths ( & mut paths_and_types, cx, arms[ 1 ] . pat , ty) {
162- return ;
163- }
164-
165- let in_candidate_enum = |path_info : & ( String , Ty < ' _ > ) | -> bool {
166- let ( path, ty) = path_info;
167- for & ( ty_path, pat_path) in candidates {
168- if path == pat_path && match_type ( cx, * ty, ty_path) {
169- return true ;
170- }
171+ let ( path, ty) = path_info;
172+ for & ( ty_path, pat_path) in candidates {
173+ if path == pat_path && match_type ( cx, * ty, ty_path) {
174+ return true ;
171175 }
172- false
173- } ;
174- if paths_and_types. iter ( ) . all ( in_candidate_enum) {
175- report_single_pattern ( cx, ex, arms, expr, els) ;
176176 }
177+ false
177178}
178179
179180/// Collects paths and their types from the given patterns. Returns true if the given pattern could
@@ -218,7 +219,7 @@ fn contains_only_wilds(pat: &Pat<'_>) -> bool {
218219
219220/// Returns true if the given patterns forms only exhaustive matches that don't contain enum
220221/// patterns without a wildcard.
221- fn form_exhaustive_matches ( left : & Pat < ' _ > , right : & Pat < ' _ > ) -> bool {
222+ fn form_exhaustive_matches < ' a > ( cx : & LateContext < ' a > , ty : Ty < ' a > , left : & Pat < ' _ > , right : & Pat < ' _ > ) -> bool {
222223 match ( & left. kind , & right. kind ) {
223224 ( PatKind :: Wild , _) | ( _, PatKind :: Wild ) => true ,
224225 ( PatKind :: Tuple ( left_in, left_pos) , PatKind :: Tuple ( right_in, right_pos) ) => {
@@ -264,6 +265,14 @@ fn form_exhaustive_matches(left: &Pat<'_>, right: &Pat<'_>) -> bool {
264265 }
265266 true
266267 } ,
268+ ( PatKind :: TupleStruct ( ..) , PatKind :: Path ( _) | PatKind :: TupleStruct ( ..) ) => {
269+ let mut paths_and_types = Vec :: new ( ) ;
270+ if !collect_pat_paths ( & mut paths_and_types, cx, right, ty) {
271+ return false ;
272+ }
273+
274+ paths_and_types. iter ( ) . all ( |info| in_candidate_enum ( cx, info) )
275+ } ,
267276 _ => false ,
268277 }
269278}
0 commit comments