@@ -10,19 +10,19 @@ use rustc_hir::{Block, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind, Path,
10
10
use rustc_lint:: LateContext ;
11
11
12
12
pub ( super ) fn check < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > , loop_block : & ' tcx Block < ' _ > ) {
13
- let ( init, let_info) = match ( loop_block. stmts , loop_block. expr ) {
13
+ let ( init, let_info, els ) = match ( loop_block. stmts , loop_block. expr ) {
14
14
( [ stmt, ..] , _) => match stmt. kind {
15
15
StmtKind :: Let ( LetStmt {
16
16
init : Some ( e) ,
17
- els : None ,
17
+ els,
18
18
pat,
19
19
ty,
20
20
..
21
- } ) => ( * e, Some ( ( * pat, * ty) ) ) ,
22
- StmtKind :: Semi ( e) | StmtKind :: Expr ( e) => ( e, None ) ,
21
+ } ) => ( * e, Some ( ( * pat, * ty) ) , * els ) ,
22
+ StmtKind :: Semi ( e) | StmtKind :: Expr ( e) => ( e, None , None ) ,
23
23
_ => return ,
24
24
} ,
25
- ( [ ] , Some ( e) ) => ( e, None ) ,
25
+ ( [ ] , Some ( e) ) => ( e, None , None ) ,
26
26
_ => return ,
27
27
} ;
28
28
let has_trailing_exprs = loop_block. stmts . len ( ) + usize:: from ( loop_block. expr . is_some ( ) ) > 1 ;
@@ -38,14 +38,26 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_blo
38
38
if_let. let_expr ,
39
39
has_trailing_exprs,
40
40
let_info,
41
- if_let. if_then ,
41
+ Some ( if_let. if_then ) ,
42
42
) ;
43
+ } else if els. and_then ( |x| x. expr ) . is_some_and ( is_simple_break_expr)
44
+ && let Some ( ( pat, _) ) = let_info
45
+ {
46
+ could_be_while_let ( cx, expr, pat, init, has_trailing_exprs, let_info, None ) ;
43
47
} else if let ExprKind :: Match ( scrutinee, [ arm1, arm2] , MatchSource :: Normal ) = init. kind
44
48
&& arm1. guard . is_none ( )
45
49
&& arm2. guard . is_none ( )
46
50
&& is_simple_break_expr ( arm2. body )
47
51
{
48
- could_be_while_let ( cx, expr, arm1. pat , scrutinee, has_trailing_exprs, let_info, arm1. body ) ;
52
+ could_be_while_let (
53
+ cx,
54
+ expr,
55
+ arm1. pat ,
56
+ scrutinee,
57
+ has_trailing_exprs,
58
+ let_info,
59
+ Some ( arm1. body ) ,
60
+ ) ;
49
61
}
50
62
}
51
63
@@ -70,7 +82,7 @@ fn could_be_while_let<'tcx>(
70
82
let_expr : & ' tcx Expr < ' _ > ,
71
83
has_trailing_exprs : bool ,
72
84
let_info : Option < ( & Pat < ' _ > , Option < & Ty < ' _ > > ) > ,
73
- inner_expr : & Expr < ' _ > ,
85
+ inner_expr : Option < & Expr < ' _ > > ,
74
86
) {
75
87
if has_trailing_exprs
76
88
&& ( needs_ordered_drop ( cx, cx. typeck_results ( ) . expr_ty ( let_expr) )
@@ -85,7 +97,7 @@ fn could_be_while_let<'tcx>(
85
97
// 1) it was ugly with big bodies;
86
98
// 2) it was not indented properly;
87
99
// 3) it wasn’t very smart (see #675).
88
- let inner_content = if let Some ( ( pat, ty) ) = let_info
100
+ let inner_content = if let Some ( ( ( pat, ty) , inner_expr ) ) = let_info. zip ( inner_expr )
89
101
// Prevent trivial reassignments such as `let x = x;` or `let _ = …;`, but
90
102
// keep them if the type has been explicitly specified.
91
103
&& ( !is_trivial_assignment ( pat, peel_blocks ( inner_expr) ) || ty. is_some ( ) )
0 commit comments