@@ -5,7 +5,8 @@ use clippy_utils::higher::IfLetOrMatch;
5
5
use clippy_utils:: source:: snippet_with_context;
6
6
use clippy_utils:: ty:: is_type_diagnostic_item;
7
7
use clippy_utils:: { is_lint_allowed, is_never_expr, msrvs, pat_and_expr_can_be_question_mark, peel_blocks} ;
8
- use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
8
+ use rustc_ast:: BindingMode ;
9
+ use rustc_data_structures:: fx:: FxHashMap ;
9
10
use rustc_errors:: Applicability ;
10
11
use rustc_hir:: { Expr , ExprKind , MatchSource , Pat , PatExpr , PatExprKind , PatKind , QPath , Stmt , StmtKind } ;
11
12
use rustc_lint:: { LateContext , LintContext } ;
@@ -113,7 +114,7 @@ fn emit_manual_let_else(
113
114
cx : & LateContext < ' _ > ,
114
115
span : Span ,
115
116
expr : & Expr < ' _ > ,
116
- ident_map : & FxHashMap < Symbol , & Pat < ' _ > > ,
117
+ ident_map : & FxHashMap < Symbol , ( & Pat < ' _ > , BindingMode ) > ,
117
118
pat : & Pat < ' _ > ,
118
119
else_body : & Expr < ' _ > ,
119
120
) {
@@ -167,7 +168,7 @@ fn emit_manual_let_else(
167
168
fn replace_in_pattern (
168
169
cx : & LateContext < ' _ > ,
169
170
span : Span ,
170
- ident_map : & FxHashMap < Symbol , & Pat < ' _ > > ,
171
+ ident_map : & FxHashMap < Symbol , ( & Pat < ' _ > , BindingMode ) > ,
171
172
pat : & Pat < ' _ > ,
172
173
app : & mut Applicability ,
173
174
top_level : bool ,
@@ -185,15 +186,16 @@ fn replace_in_pattern(
185
186
186
187
match pat. kind {
187
188
PatKind :: Binding ( _ann, _id, binding_name, opt_subpt) => {
188
- let Some ( pat_to_put) = ident_map. get ( & binding_name. name ) else {
189
+ let Some ( ( pat_to_put, binding_mode ) ) = ident_map. get ( & binding_name. name ) else {
189
190
break ' a;
190
191
} ;
192
+ let sn_pfx = binding_mode. prefix_str ( ) ;
191
193
let ( sn_ptp, _) = snippet_with_context ( cx, pat_to_put. span , span. ctxt ( ) , "" , app) ;
192
194
if let Some ( subpt) = opt_subpt {
193
195
let subpt = replace_in_pattern ( cx, span, ident_map, subpt, app, false ) ;
194
- return format ! ( "{sn_ptp} @ {subpt}" ) ;
196
+ return format ! ( "{sn_pfx}{ sn_ptp} @ {subpt}" ) ;
195
197
}
196
- return sn_ptp . to_string ( ) ;
198
+ return format ! ( "{sn_pfx}{sn_ptp}" ) ;
197
199
} ,
198
200
PatKind :: Or ( pats) => {
199
201
let patterns = pats
@@ -211,17 +213,18 @@ fn replace_in_pattern(
211
213
. iter ( )
212
214
. map ( |fld| {
213
215
if let PatKind :: Binding ( _, _, name, None ) = fld. pat . kind
214
- && let Some ( pat_to_put) = ident_map. get ( & name. name )
216
+ && let Some ( ( pat_to_put, binding_mode ) ) = ident_map. get ( & name. name )
215
217
{
218
+ let sn_pfx = binding_mode. prefix_str ( ) ;
216
219
let ( sn_fld_name, _) = snippet_with_context ( cx, fld. ident . span , span. ctxt ( ) , "" , app) ;
217
220
let ( sn_ptp, _) = snippet_with_context ( cx, pat_to_put. span , span. ctxt ( ) , "" , app) ;
218
221
// TODO: this is a bit of a hack, but it does its job. Ideally, we'd check if pat_to_put is
219
222
// a PatKind::Binding but that is also hard to get right.
220
223
if sn_fld_name == sn_ptp {
221
224
// Field init shorthand
222
- return format ! ( "{sn_fld_name}" ) ;
225
+ return format ! ( "{sn_pfx}{ sn_fld_name}" ) ;
223
226
}
224
- return format ! ( "{sn_fld_name}: {sn_ptp}" ) ;
227
+ return format ! ( "{sn_fld_name}: {sn_pfx}{ sn_ptp}" ) ;
225
228
}
226
229
let ( sn_fld, _) = snippet_with_context ( cx, fld. span , span. ctxt ( ) , "" , app) ;
227
230
sn_fld. into_owned ( )
@@ -334,7 +337,7 @@ fn expr_simple_identity_map<'a, 'hir>(
334
337
local_pat : & ' a Pat < ' hir > ,
335
338
let_pat : & ' _ Pat < ' hir > ,
336
339
expr : & ' _ Expr < ' hir > ,
337
- ) -> Option < FxHashMap < Symbol , & ' a Pat < ' hir > > > {
340
+ ) -> Option < FxHashMap < Symbol , ( & ' a Pat < ' hir > , BindingMode ) > > {
338
341
let peeled = peel_blocks ( expr) ;
339
342
let ( sub_pats, paths) = match ( local_pat. kind , peeled. kind ) {
340
343
( PatKind :: Tuple ( pats, _) , ExprKind :: Tup ( exprs) ) | ( PatKind :: Slice ( pats, ..) , ExprKind :: Array ( exprs) ) => {
@@ -351,9 +354,9 @@ fn expr_simple_identity_map<'a, 'hir>(
351
354
return None ;
352
355
}
353
356
354
- let mut pat_bindings = FxHashSet :: default ( ) ;
355
- let_pat. each_binding_or_first ( & mut |_ann , _hir_id, _sp, ident| {
356
- pat_bindings. insert ( ident) ;
357
+ let mut pat_bindings = FxHashMap :: default ( ) ;
358
+ let_pat. each_binding_or_first ( & mut |binding_mode , _hir_id, _sp, ident| {
359
+ pat_bindings. insert ( ident, binding_mode ) ;
357
360
} ) ;
358
361
if pat_bindings. len ( ) < paths. len ( ) {
359
362
// This rebinds some bindings from the outer scope, or it repeats some copy-able bindings multiple
@@ -366,12 +369,10 @@ fn expr_simple_identity_map<'a, 'hir>(
366
369
for ( sub_pat, path) in sub_pats. iter ( ) . zip ( paths. iter ( ) ) {
367
370
if let ExprKind :: Path ( QPath :: Resolved ( _ty, path) ) = path. kind
368
371
&& let [ path_seg] = path. segments
372
+ && let ident = path_seg. ident
373
+ && let Some ( let_binding_mode) = pat_bindings. remove ( & ident)
369
374
{
370
- let ident = path_seg. ident ;
371
- if !pat_bindings. remove ( & ident) {
372
- return None ;
373
- }
374
- ident_map. insert ( ident. name , sub_pat) ;
375
+ ident_map. insert ( ident. name , ( sub_pat, let_binding_mode) ) ;
375
376
} else {
376
377
return None ;
377
378
}
0 commit comments