@@ -248,7 +248,98 @@ impl<'tcx> BorrowExplanation<'tcx> {
248
248
) ;
249
249
err. span_label ( body. source_info ( drop_loc) . span , message) ;
250
250
251
- if let LocalInfo :: BlockTailTemp ( info) = local_decl. local_info ( ) {
251
+ struct FindLetExpr < ' hir > {
252
+ span : Span ,
253
+ result : Option < ( Span , & ' hir hir:: Pat < ' hir > , & ' hir hir:: Expr < ' hir > ) > ,
254
+ tcx : TyCtxt < ' hir > ,
255
+ }
256
+
257
+ impl < ' hir > rustc_hir:: intravisit:: Visitor < ' hir > for FindLetExpr < ' hir > {
258
+ type NestedFilter = rustc_middle:: hir:: nested_filter:: OnlyBodies ;
259
+ fn nested_visit_map ( & mut self ) -> Self :: Map {
260
+ self . tcx . hir ( )
261
+ }
262
+ fn visit_expr ( & mut self , expr : & ' hir hir:: Expr < ' hir > ) {
263
+ if let hir:: ExprKind :: If ( cond, _conseq, _alt)
264
+ | hir:: ExprKind :: Loop (
265
+ hir:: Block {
266
+ expr :
267
+ Some ( & hir:: Expr {
268
+ kind : hir:: ExprKind :: If ( cond, _conseq, _alt) ,
269
+ ..
270
+ } ) ,
271
+ ..
272
+ } ,
273
+ _,
274
+ hir:: LoopSource :: While ,
275
+ _,
276
+ ) = expr. kind
277
+ && let hir:: ExprKind :: Let ( hir:: LetExpr {
278
+ init : let_expr_init,
279
+ span : let_expr_span,
280
+ pat : let_expr_pat,
281
+ ..
282
+ } ) = cond. kind
283
+ && let_expr_init. span . contains ( self . span )
284
+ {
285
+ self . result =
286
+ Some ( ( * let_expr_span, let_expr_pat, let_expr_init) )
287
+ } else {
288
+ hir:: intravisit:: walk_expr ( self , expr) ;
289
+ }
290
+ }
291
+ }
292
+
293
+ if let & LocalInfo :: IfThenRescopeTemp { if_then } = local_decl. local_info ( )
294
+ && let hir:: Node :: Expr ( expr) = tcx. hir_node ( if_then)
295
+ && let hir:: ExprKind :: If ( cond, conseq, alt) = expr. kind
296
+ && let hir:: ExprKind :: Let ( & hir:: LetExpr {
297
+ span : _,
298
+ pat,
299
+ init,
300
+ // FIXME(#101728): enable rewrite when type ascription is
301
+ // stabilized again.
302
+ ty : None ,
303
+ recovered : _,
304
+ } ) = cond. kind
305
+ && pat. span . can_be_used_for_suggestions ( )
306
+ && let Ok ( pat) = tcx. sess . source_map ( ) . span_to_snippet ( pat. span )
307
+ {
308
+ suggest_rewrite_if_let ( tcx, expr, & pat, init, conseq, alt, err) ;
309
+ } else if let Some ( ( old, new) ) = multiple_borrow_span
310
+ && let def_id = body. source . def_id ( )
311
+ && let Some ( node) = tcx. hir ( ) . get_if_local ( def_id)
312
+ && let Some ( body_id) = node. body_id ( )
313
+ && let hir_body = tcx. hir ( ) . body ( body_id)
314
+ && let mut expr_finder = ( FindLetExpr { span : old, result : None , tcx } )
315
+ && let Some ( ( let_expr_span, let_expr_pat, let_expr_init) ) = {
316
+ expr_finder. visit_expr ( hir_body. value ) ;
317
+ expr_finder. result
318
+ }
319
+ && !let_expr_span. contains ( new)
320
+ {
321
+ // #133941: The `old` expression is at the conditional part of an
322
+ // if/while let expression. Adding a semicolon won't work.
323
+ // Instead, try suggesting the `matches!` macro or a temporary.
324
+ if let_expr_pat
325
+ . walk_short ( |pat| !matches ! ( pat. kind, hir:: PatKind :: Binding ( ..) ) )
326
+ {
327
+ if let Ok ( pat_snippet) =
328
+ tcx. sess . source_map ( ) . span_to_snippet ( let_expr_pat. span )
329
+ && let Ok ( init_snippet) =
330
+ tcx. sess . source_map ( ) . span_to_snippet ( let_expr_init. span )
331
+ {
332
+ err. span_suggestion_verbose (
333
+ let_expr_span,
334
+ "consider using the `matches!` macro" ,
335
+ format ! ( "matches!({init_snippet}, {pat_snippet})" ) ,
336
+ Applicability :: MaybeIncorrect ,
337
+ ) ;
338
+ } else {
339
+ err. note ( "consider using the `matches!` macro" ) ;
340
+ }
341
+ }
342
+ } else if let LocalInfo :: BlockTailTemp ( info) = local_decl. local_info ( ) {
252
343
if info. tail_result_is_ignored {
253
344
// #85581: If the first mutable borrow's scope contains
254
345
// the second borrow, this suggestion isn't helpful.
@@ -281,23 +372,6 @@ impl<'tcx> BorrowExplanation<'tcx> {
281
372
Applicability :: MaybeIncorrect ,
282
373
) ;
283
374
} ;
284
- } else if let & LocalInfo :: IfThenRescopeTemp { if_then } =
285
- local_decl. local_info ( )
286
- && let hir:: Node :: Expr ( expr) = tcx. hir_node ( if_then)
287
- && let hir:: ExprKind :: If ( cond, conseq, alt) = expr. kind
288
- && let hir:: ExprKind :: Let ( & hir:: LetExpr {
289
- span : _,
290
- pat,
291
- init,
292
- // FIXME(#101728): enable rewrite when type ascription is
293
- // stabilized again.
294
- ty : None ,
295
- recovered : _,
296
- } ) = cond. kind
297
- && pat. span . can_be_used_for_suggestions ( )
298
- && let Ok ( pat) = tcx. sess . source_map ( ) . span_to_snippet ( pat. span )
299
- {
300
- suggest_rewrite_if_let ( tcx, expr, & pat, init, conseq, alt, err) ;
301
375
}
302
376
}
303
377
}
0 commit comments