@@ -5,7 +5,8 @@ use clippy_utils::higher::IfLetOrMatch;
55use clippy_utils:: source:: snippet_with_context;
66use clippy_utils:: ty:: is_type_diagnostic_item;
77use 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 ;
910use rustc_errors:: Applicability ;
1011use rustc_hir:: { Expr , ExprKind , MatchSource , Pat , PatExpr , PatExprKind , PatKind , QPath , Stmt , StmtKind } ;
1112use rustc_lint:: { LateContext , LintContext } ;
@@ -113,7 +114,7 @@ fn emit_manual_let_else(
113114 cx : & LateContext < ' _ > ,
114115 span : Span ,
115116 expr : & Expr < ' _ > ,
116- ident_map : & FxHashMap < Symbol , & Pat < ' _ > > ,
117+ ident_map : & FxHashMap < Symbol , ( & Pat < ' _ > , BindingMode ) > ,
117118 pat : & Pat < ' _ > ,
118119 else_body : & Expr < ' _ > ,
119120) {
@@ -167,7 +168,7 @@ fn emit_manual_let_else(
167168fn replace_in_pattern (
168169 cx : & LateContext < ' _ > ,
169170 span : Span ,
170- ident_map : & FxHashMap < Symbol , & Pat < ' _ > > ,
171+ ident_map : & FxHashMap < Symbol , ( & Pat < ' _ > , BindingMode ) > ,
171172 pat : & Pat < ' _ > ,
172173 app : & mut Applicability ,
173174 top_level : bool ,
@@ -185,15 +186,16 @@ fn replace_in_pattern(
185186
186187 match pat. kind {
187188 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 {
189190 break ' a;
190191 } ;
192+ let sn_pfx = binding_mode. prefix_str ( ) ;
191193 let ( sn_ptp, _) = snippet_with_context ( cx, pat_to_put. span , span. ctxt ( ) , "" , app) ;
192194 if let Some ( subpt) = opt_subpt {
193195 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}" ) ;
195197 }
196- return sn_ptp . to_string ( ) ;
198+ return format ! ( "{sn_pfx}{sn_ptp}" ) ;
197199 } ,
198200 PatKind :: Or ( pats) => {
199201 let patterns = pats
@@ -211,17 +213,18 @@ fn replace_in_pattern(
211213 . iter ( )
212214 . map ( |fld| {
213215 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 )
215217 {
218+ let sn_pfx = binding_mode. prefix_str ( ) ;
216219 let ( sn_fld_name, _) = snippet_with_context ( cx, fld. ident . span , span. ctxt ( ) , "" , app) ;
217220 let ( sn_ptp, _) = snippet_with_context ( cx, pat_to_put. span , span. ctxt ( ) , "" , app) ;
218221 // TODO: this is a bit of a hack, but it does its job. Ideally, we'd check if pat_to_put is
219222 // a PatKind::Binding but that is also hard to get right.
220223 if sn_fld_name == sn_ptp {
221224 // Field init shorthand
222- return format ! ( "{sn_fld_name}" ) ;
225+ return format ! ( "{sn_pfx}{ sn_fld_name}" ) ;
223226 }
224- return format ! ( "{sn_fld_name}: {sn_ptp}" ) ;
227+ return format ! ( "{sn_fld_name}: {sn_pfx}{ sn_ptp}" ) ;
225228 }
226229 let ( sn_fld, _) = snippet_with_context ( cx, fld. span , span. ctxt ( ) , "" , app) ;
227230 sn_fld. into_owned ( )
@@ -334,7 +337,7 @@ fn expr_simple_identity_map<'a, 'hir>(
334337 local_pat : & ' a Pat < ' hir > ,
335338 let_pat : & ' _ Pat < ' hir > ,
336339 expr : & ' _ Expr < ' hir > ,
337- ) -> Option < FxHashMap < Symbol , & ' a Pat < ' hir > > > {
340+ ) -> Option < FxHashMap < Symbol , ( & ' a Pat < ' hir > , BindingMode ) > > {
338341 let peeled = peel_blocks ( expr) ;
339342 let ( sub_pats, paths) = match ( local_pat. kind , peeled. kind ) {
340343 ( PatKind :: Tuple ( pats, _) , ExprKind :: Tup ( exprs) ) | ( PatKind :: Slice ( pats, ..) , ExprKind :: Array ( exprs) ) => {
@@ -351,9 +354,9 @@ fn expr_simple_identity_map<'a, 'hir>(
351354 return None ;
352355 }
353356
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 ) ;
357360 } ) ;
358361 if pat_bindings. len ( ) < paths. len ( ) {
359362 // 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>(
366369 for ( sub_pat, path) in sub_pats. iter ( ) . zip ( paths. iter ( ) ) {
367370 if let ExprKind :: Path ( QPath :: Resolved ( _ty, path) ) = path. kind
368371 && let [ path_seg] = path. segments
372+ && let ident = path_seg. ident
373+ && let Some ( let_binding_mode) = pat_bindings. remove ( & ident)
369374 {
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) ) ;
375376 } else {
376377 return None ;
377378 }
0 commit comments