@@ -248,7 +248,98 @@ impl<'tcx> BorrowExplanation<'tcx> {
248248 ) ;
249249 err. span_label ( body. source_info ( drop_loc) . span , message) ;
250250
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 ( ) {
252343 if info. tail_result_is_ignored {
253344 // #85581: If the first mutable borrow's scope contains
254345 // the second borrow, this suggestion isn't helpful.
@@ -281,23 +372,6 @@ impl<'tcx> BorrowExplanation<'tcx> {
281372 Applicability :: MaybeIncorrect ,
282373 ) ;
283374 } ;
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) ;
301375 }
302376 }
303377 }
0 commit comments