@@ -13,6 +13,7 @@ use rustc_hir::LangItem::OptionNone;
13
13
use rustc_hir:: { Arm , Expr , ExprKind , HirId , Pat , PatExpr , PatExprKind , PatKind } ;
14
14
use rustc_lint:: LateContext ;
15
15
use rustc_span:: Span ;
16
+ use rustc_span:: symbol:: Ident ;
16
17
17
18
use super :: { COLLAPSIBLE_MATCH , pat_contains_disallowed_or} ;
18
19
@@ -50,15 +51,17 @@ fn check_arm<'tcx>(
50
51
if let Some ( inner) = IfLetOrMatch :: parse ( cx, inner_expr)
51
52
&& let Some ( ( inner_scrutinee, inner_then_pat, inner_else_body) ) = match inner {
52
53
IfLetOrMatch :: IfLet ( scrutinee, pat, _, els, _) => Some ( ( scrutinee, pat, els) ) ,
53
- IfLetOrMatch :: Match ( scrutinee, arms, ..) => if arms. len ( ) == 2 && arms. iter ( ) . all ( |a| a. guard . is_none ( ) )
54
- // if there are more than two arms, collapsing would be non-trivial
55
- // one of the arms must be "wild-like"
56
- && let Some ( wild_idx) = arms. iter ( ) . rposition ( |a| arm_is_wild_like ( cx, a) )
57
- {
58
- let ( then, els) = ( & arms[ 1 - wild_idx] , & arms[ wild_idx] ) ;
59
- Some ( ( scrutinee, then. pat , Some ( els. body ) ) )
60
- } else {
61
- None
54
+ IfLetOrMatch :: Match ( scrutinee, arms, ..) => {
55
+ if arms. len ( ) == 2 && arms. iter ( ) . all ( |a| a. guard . is_none ( ) )
56
+ // if there are more than two arms, collapsing would be non-trivial
57
+ // one of the arms must be "wild-like"
58
+ && let Some ( wild_idx) = arms. iter ( ) . rposition ( |a| arm_is_wild_like ( cx, a) )
59
+ {
60
+ let ( then, els) = ( & arms[ 1 - wild_idx] , & arms[ wild_idx] ) ;
61
+ Some ( ( scrutinee, then. pat , Some ( els. body ) ) )
62
+ } else {
63
+ None
64
+ }
62
65
} ,
63
66
}
64
67
&& outer_pat. span . eq_ctxt ( inner_scrutinee. span )
@@ -68,18 +71,16 @@ fn check_arm<'tcx>(
68
71
&& !pat_contains_disallowed_or ( cx, inner_then_pat, msrv)
69
72
// the binding must come from the pattern of the containing match arm
70
73
// ..<local>.. => match <local> { .. }
71
- && let ( Some ( binding_span) , is_innermost_parent_pat_struct)
72
- = find_pat_binding_and_is_innermost_parent_pat_struct ( outer_pat, binding_id)
74
+ && let ( Some ( ( binding_ident , binding_span) ) , is_innermost_parent_pat_struct) =
75
+ find_pat_binding_and_is_innermost_parent_pat_struct ( outer_pat, binding_id)
73
76
// the "else" branches must be equal
74
77
&& match ( outer_else_body, inner_else_body) {
75
78
( None , None ) => true ,
76
79
( None , Some ( e) ) | ( Some ( e) , None ) => is_unit_expr ( e) ,
77
80
( Some ( a) , Some ( b) ) => SpanlessEq :: new ( cx) . eq_expr ( a, b) ,
78
81
}
79
82
// the binding must not be used in the if guard
80
- && outer_guard. is_none_or (
81
- |e| !is_local_used ( cx, e, binding_id)
82
- )
83
+ && outer_guard. is_none_or ( |e| !is_local_used ( cx, e, binding_id) )
83
84
// ...or anywhere in the inner expression
84
85
&& match inner {
85
86
IfLetOrMatch :: IfLet ( _, _, body, els, _) => {
@@ -103,7 +104,7 @@ fn check_arm<'tcx>(
103
104
// collapsing patterns need an explicit field name in struct pattern matching
104
105
// ex: Struct {x: Some(1)}
105
106
let replace_msg = if is_innermost_parent_pat_struct {
106
- format ! ( ", prefixed by `{}`:" , snippet ( cx , binding_span , "their field name" ) )
107
+ format ! ( ", prefixed by `{binding_ident}: `" )
107
108
} else {
108
109
String :: new ( )
109
110
} ;
@@ -140,16 +141,16 @@ fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
140
141
}
141
142
}
142
143
143
- fn find_pat_binding_and_is_innermost_parent_pat_struct ( pat : & Pat < ' _ > , hir_id : HirId ) -> ( Option < Span > , bool ) {
144
- let mut span = None ;
144
+ fn find_pat_binding_and_is_innermost_parent_pat_struct ( pat : & Pat < ' _ > , hir_id : HirId ) -> ( Option < ( Ident , Span ) > , bool ) {
145
+ let mut binding = None ;
145
146
let mut is_innermost_parent_pat_struct = false ;
146
- pat. walk_short ( |p| match & p. kind {
147
+ pat. walk_short ( |p| match p. kind {
147
148
// ignore OR patterns
148
149
PatKind :: Or ( _) => false ,
149
- PatKind :: Binding ( _bm, _, _ident , _) => {
150
+ PatKind :: Binding ( _bm, _, ident , _) => {
150
151
let found = p. hir_id == hir_id;
151
152
if found {
152
- span = Some ( p. span ) ;
153
+ binding = Some ( ( ident , p. span ) ) ;
153
154
}
154
155
!found
155
156
} ,
@@ -158,7 +159,7 @@ fn find_pat_binding_and_is_innermost_parent_pat_struct(pat: &Pat<'_>, hir_id: Hi
158
159
true
159
160
} ,
160
161
} ) ;
161
- ( span , is_innermost_parent_pat_struct)
162
+ ( binding , is_innermost_parent_pat_struct)
162
163
}
163
164
164
165
/// Builds a chain of reference-manipulation method calls (e.g., `.as_ref()`, `.as_mut()`,
0 commit comments