@@ -4,8 +4,8 @@ use crate::utils::usage::is_unused;
44use crate :: utils:: {
55 expr_block, get_arg_name, get_parent_expr, implements_trait, in_macro, indent_of, is_allowed, is_expn_of,
66 is_refutable, is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, meets_msrv, multispan_sugg,
7- remove_blocks , snippet , snippet_block , snippet_opt , snippet_with_applicability , span_lint_and_help ,
8- span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
7+ peel_hir_pat_refs , peel_mid_ty_refs , peeln_hir_expr_refs , remove_blocks , snippet , snippet_block , snippet_opt ,
8+ snippet_with_applicability , span_lint_and_help , span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
99} ;
1010use crate :: utils:: { paths, search_same, SpanlessEq , SpanlessHash } ;
1111use if_chain:: if_chain;
@@ -717,28 +717,6 @@ fn check_single_match_single_pattern(
717717 }
718718}
719719
720- fn peel_pat_refs ( pat : & ' a Pat < ' a > ) -> ( & ' a Pat < ' a > , usize ) {
721- fn peel ( pat : & ' a Pat < ' a > , count : usize ) -> ( & ' a Pat < ' a > , usize ) {
722- if let PatKind :: Ref ( pat, _) = pat. kind {
723- peel ( pat, count + 1 )
724- } else {
725- ( pat, count)
726- }
727- }
728- peel ( pat, 0 )
729- }
730-
731- fn peel_ty_refs ( ty : Ty < ' _ > ) -> ( Ty < ' _ > , usize ) {
732- fn peel ( ty : Ty < ' _ > , count : usize ) -> ( Ty < ' _ > , usize ) {
733- if let ty:: Ref ( _, ty, _) = ty. kind ( ) {
734- peel ( ty, count + 1 )
735- } else {
736- ( ty, count)
737- }
738- }
739- peel ( ty, 0 )
740- }
741-
742720fn report_single_match_single_pattern (
743721 cx : & LateContext < ' _ > ,
744722 ex : & Expr < ' _ > ,
@@ -752,9 +730,9 @@ fn report_single_match_single_pattern(
752730 } ) ;
753731
754732 let ( msg, sugg) = if_chain ! {
755- let ( pat, pat_ref_count) = peel_pat_refs ( arms[ 0 ] . pat) ;
733+ let ( pat, pat_ref_count) = peel_hir_pat_refs ( arms[ 0 ] . pat) ;
756734 if let PatKind :: Path ( _) | PatKind :: Lit ( _) = pat. kind;
757- let ( ty, ty_ref_count) = peel_ty_refs ( cx. typeck_results( ) . expr_ty( ex) ) ;
735+ let ( ty, ty_ref_count) = peel_mid_ty_refs ( cx. typeck_results( ) . expr_ty( ex) ) ;
758736 if let Some ( trait_id) = cx. tcx. lang_items( ) . structural_peq_trait( ) ;
759737 if ty. is_integral( ) || ty. is_char( ) || ty. is_str( ) || implements_trait( cx, ty, trait_id, & [ ] ) ;
760738 then {
@@ -764,19 +742,28 @@ fn report_single_match_single_pattern(
764742 PatKind :: Lit ( Expr { kind: ExprKind :: Lit ( lit) , .. } ) if lit. node. is_str( ) => pat_ref_count + 1 ,
765743 _ => pat_ref_count,
766744 } ;
767- let msg = "you seem to be trying to use match for an equality check. Consider using `if`" ;
745+ // References are only implicitly added to the pattern, so no overflow here.
746+ // e.g. will work: match &Some(_) { Some(_) => () }
747+ // will not: match Some(_) { &Some(_) => () }
748+ let ref_count_diff = ty_ref_count - pat_ref_count;
749+
750+ // Try to remove address of expressions first.
751+ let ( ex, removed) = peeln_hir_expr_refs( ex, ref_count_diff) ;
752+ let ref_count_diff = ref_count_diff - removed;
753+
754+ let msg = "you seem to be trying to use `match` for an equality check. Consider using `if`" ;
768755 let sugg = format!(
769756 "if {} == {}{} {}{}" ,
770757 snippet( cx, ex. span, ".." ) ,
771758 // PartialEq for different reference counts may not exist.
772- "&" . repeat( ty_ref_count - pat_ref_count ) ,
759+ "&" . repeat( ref_count_diff ) ,
773760 snippet( cx, arms[ 0 ] . pat. span, ".." ) ,
774761 expr_block( cx, & arms[ 0 ] . body, None , ".." , Some ( expr. span) ) ,
775762 els_str,
776763 ) ;
777764 ( msg, sugg)
778765 } else {
779- let msg = "you seem to be trying to use match for destructuring a single pattern. Consider using `if let`" ;
766+ let msg = "you seem to be trying to use ` match` for destructuring a single pattern. Consider using `if let`" ;
780767 let sugg = format!(
781768 "if let {} = {} {}{}" ,
782769 snippet( cx, arms[ 0 ] . pat. span, ".." ) ,
0 commit comments