@@ -61,10 +61,26 @@ pub struct SignificantDropTightening<'tcx> {
61
61
}
62
62
63
63
impl < ' tcx > SignificantDropTightening < ' tcx > {
64
+ /// Unifies the statements of a block with its return expression.
65
+ fn all_block_stmts < ' ret , ' rslt , ' stmts > (
66
+ block_stmts : & ' stmts [ hir:: Stmt < ' tcx > ] ,
67
+ dummy_ret_stmt : Option < & ' ret hir:: Stmt < ' tcx > > ,
68
+ ) -> impl Iterator < Item = & ' rslt hir:: Stmt < ' tcx > >
69
+ where
70
+ ' ret : ' rslt ,
71
+ ' stmts : ' rslt ,
72
+ {
73
+ block_stmts. iter ( ) . chain ( dummy_ret_stmt)
74
+ }
75
+
64
76
/// Searches for at least one statement that could slow down the release of a significant drop.
65
- fn at_least_one_stmt_is_expensive ( stmts : & [ hir:: Stmt < ' _ > ] ) -> bool {
77
+ fn at_least_one_stmt_is_expensive < ' stmt > ( stmts : impl Iterator < Item = & ' stmt hir:: Stmt < ' tcx > > ) -> bool
78
+ where
79
+ ' tcx : ' stmt ,
80
+ {
66
81
for stmt in stmts {
67
82
match stmt. kind {
83
+ hir:: StmtKind :: Expr ( expr) if let hir:: ExprKind :: Path ( _) = expr. kind => { }
68
84
hir:: StmtKind :: Local ( local) if let Some ( expr) = local. init
69
85
&& let hir:: ExprKind :: Path ( _) = expr. kind => { } ,
70
86
_ => return true
@@ -99,7 +115,7 @@ impl<'tcx> SignificantDropTightening<'tcx> {
99
115
expr : & ' tcx hir:: Expr < ' _ > ,
100
116
idx : usize ,
101
117
sdap : & mut SigDropAuxParams ,
102
- stmt : & ' tcx hir:: Stmt < ' _ > ,
118
+ stmt : & hir:: Stmt < ' _ > ,
103
119
cb : impl Fn ( & mut SigDropAuxParams ) ,
104
120
) {
105
121
let mut sig_drop_finder = SigDropFinder :: new ( cx, & mut self . seen_types ) ;
@@ -117,7 +133,7 @@ impl<'tcx> SignificantDropTightening<'tcx> {
117
133
}
118
134
}
119
135
120
- /// Shows a generic overall message as well as specialized messages depending on the usage.
136
+ /// Shows generic overall messages as well as specialized messages depending on the usage.
121
137
fn set_suggestions ( cx : & LateContext < ' tcx > , block_span : Span , diag : & mut Diagnostic , sdap : & SigDropAuxParams ) {
122
138
match sdap. number_of_stmts {
123
139
0 | 1 => { } ,
@@ -172,8 +188,13 @@ impl<'tcx> SignificantDropTightening<'tcx> {
172
188
173
189
impl < ' tcx > LateLintPass < ' tcx > for SignificantDropTightening < ' tcx > {
174
190
fn check_block ( & mut self , cx : & LateContext < ' tcx > , block : & ' tcx hir:: Block < ' _ > ) {
191
+ let dummy_ret_stmt = block. expr . map ( |expr| hir:: Stmt {
192
+ hir_id : hir:: HirId :: INVALID ,
193
+ kind : hir:: StmtKind :: Expr ( expr) ,
194
+ span : DUMMY_SP ,
195
+ } ) ;
175
196
let mut sdap = SigDropAuxParams :: default ( ) ;
176
- for ( idx, stmt) in block. stmts . iter ( ) . enumerate ( ) {
197
+ for ( idx, stmt) in Self :: all_block_stmts ( block. stmts , dummy_ret_stmt . as_ref ( ) ) . enumerate ( ) {
177
198
match stmt. kind {
178
199
hir:: StmtKind :: Expr ( expr) => self . modify_sdap_if_sig_drop_exists (
179
200
cx,
@@ -213,11 +234,9 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
213
234
_ => { }
214
235
} ;
215
236
}
216
- let stmts_after_last_use = sdap
217
- . last_use_stmt_idx
218
- . checked_add ( 1 )
219
- . and_then ( |idx| block. stmts . get ( idx..) )
220
- . unwrap_or_default ( ) ;
237
+
238
+ let idx = sdap. last_use_stmt_idx . wrapping_add ( 1 ) ;
239
+ let stmts_after_last_use = Self :: all_block_stmts ( block. stmts , dummy_ret_stmt. as_ref ( ) ) . skip ( idx) ;
221
240
if sdap. number_of_stmts > 1 && Self :: at_least_one_stmt_is_expensive ( stmts_after_last_use) {
222
241
span_lint_and_then (
223
242
cx,
0 commit comments