@@ -5,7 +5,7 @@ use clippy_utils::diagnostics::{
5
5
use clippy_utils:: macros:: { is_panic, root_macro_call} ;
6
6
use clippy_utils:: source:: { expr_block, indent_of, snippet, snippet_block, snippet_opt, snippet_with_applicability} ;
7
7
use clippy_utils:: sugg:: Sugg ;
8
- use clippy_utils:: ty:: { implements_trait, is_type_diagnostic_item, peel_mid_ty_refs} ;
8
+ use clippy_utils:: ty:: { implements_trait, is_type_diagnostic_item, match_type , peel_mid_ty_refs} ;
9
9
use clippy_utils:: visitors:: is_local_used;
10
10
use clippy_utils:: {
11
11
get_parent_expr, is_lang_ctor, is_lint_allowed, is_refutable, is_unit_expr, is_wild, meets_msrv, msrvs,
@@ -741,7 +741,7 @@ fn check_single_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], exp
741
741
let ty = cx. typeck_results ( ) . expr_ty ( ex) ;
742
742
if * ty. kind ( ) != ty:: Bool || is_lint_allowed ( cx, MATCH_BOOL , ex. hir_id ) {
743
743
check_single_match_single_pattern ( cx, ex, arms, expr, els) ;
744
- check_single_match_opt_like ( cx, ex, arms, expr, els) ;
744
+ check_single_match_opt_like ( cx, ex, arms, expr, ty , els) ;
745
745
}
746
746
}
747
747
}
@@ -830,11 +830,12 @@ fn report_single_match_single_pattern(
830
830
) ;
831
831
}
832
832
833
- fn check_single_match_opt_like (
834
- cx : & LateContext < ' _ > ,
833
+ fn check_single_match_opt_like < ' a > (
834
+ cx : & LateContext < ' a > ,
835
835
ex : & Expr < ' _ > ,
836
836
arms : & [ Arm < ' _ > ] ,
837
837
expr : & Expr < ' _ > ,
838
+ ty : Ty < ' a > ,
838
839
els : Option < & Expr < ' _ > > ,
839
840
) {
840
841
// list of candidate `Enum`s we know will never get any more members
@@ -854,44 +855,50 @@ fn check_single_match_opt_like(
854
855
return ;
855
856
}
856
857
857
- let mut paths = Vec :: new ( ) ;
858
- if !collect_pat_paths ( & mut paths , arms[ 1 ] . pat ) {
858
+ let mut paths_and_types = Vec :: new ( ) ;
859
+ if !collect_pat_paths ( & mut paths_and_types , cx , arms[ 1 ] . pat , ty ) {
859
860
return ;
860
861
}
861
862
862
- let in_candidate_enum = |path : & String | -> bool {
863
- for & ( _, pat_path) in candidates {
864
- if path == pat_path {
863
+ let in_candidate_enum = |path_info : & ( String , & TyS < ' _ > ) | -> bool {
864
+ let ( path, ty) = path_info;
865
+ for & ( ty_path, pat_path) in candidates {
866
+ if path == pat_path && match_type ( cx, ty, ty_path) {
865
867
return true ;
866
868
}
867
869
}
868
870
false
869
871
} ;
870
- if paths . iter ( ) . all ( in_candidate_enum) {
872
+ if paths_and_types . iter ( ) . all ( in_candidate_enum) {
871
873
report_single_match_single_pattern ( cx, ex, arms, expr, els) ;
872
874
}
873
875
}
874
876
875
- /// Collects paths from the given paths . Returns true if the given pattern could be simplified,
876
- /// false otherwise.
877
- fn collect_pat_paths ( acc : & mut Vec < String > , pat : & Pat < ' _ > ) -> bool {
877
+ /// Collects paths and their types from the given patterns . Returns true if the given pattern could
878
+ /// be simplified, false otherwise.
879
+ fn collect_pat_paths < ' a > ( acc : & mut Vec < ( String , Ty < ' a > ) > , cx : & LateContext < ' a > , pat : & Pat < ' _ > , ty : Ty < ' a > ) -> bool {
878
880
match pat. kind {
879
881
PatKind :: Wild => true ,
880
- PatKind :: Tuple ( inner, _) => inner. iter ( ) . all ( |p| collect_pat_paths ( acc, p) ) ,
882
+ PatKind :: Tuple ( inner, _) => inner. iter ( ) . all ( |p| {
883
+ let p_ty = cx. typeck_results ( ) . pat_ty ( p) ;
884
+ collect_pat_paths ( acc, cx, p, p_ty)
885
+ } ) ,
881
886
PatKind :: TupleStruct ( ref path, ..) => {
882
- acc . push ( rustc_hir_pretty:: to_string ( rustc_hir_pretty:: NO_ANN , |s| {
887
+ let path = rustc_hir_pretty:: to_string ( rustc_hir_pretty:: NO_ANN , |s| {
883
888
s. print_qpath ( path, false ) ;
884
- } ) ) ;
889
+ } ) ;
890
+ acc. push ( ( path, ty) ) ;
885
891
true
886
892
} ,
887
893
PatKind :: Binding ( BindingAnnotation :: Unannotated , .., ident, None ) => {
888
- acc. push ( ident. to_string ( ) ) ;
894
+ acc. push ( ( ident. to_string ( ) , ty ) ) ;
889
895
true
890
896
} ,
891
897
PatKind :: Path ( ref path) => {
892
- acc . push ( rustc_hir_pretty:: to_string ( rustc_hir_pretty:: NO_ANN , |s| {
898
+ let path = rustc_hir_pretty:: to_string ( rustc_hir_pretty:: NO_ANN , |s| {
893
899
s. print_qpath ( path, false ) ;
894
- } ) ) ;
900
+ } ) ;
901
+ acc. push ( ( path, ty) ) ;
895
902
true
896
903
} ,
897
904
_ => false ,
0 commit comments