@@ -4,7 +4,7 @@ use clippy_utils::get_attr;
4
4
use clippy_utils:: source:: { indent_of, snippet} ;
5
5
use rustc_errors:: { Applicability , Diagnostic } ;
6
6
use rustc_hir:: intravisit:: { walk_expr, Visitor } ;
7
- use rustc_hir:: { Expr , ExprKind } ;
7
+ use rustc_hir:: { Expr , ExprKind , MatchSource } ;
8
8
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
9
9
use rustc_middle:: ty:: subst:: GenericArgKind ;
10
10
use rustc_middle:: ty:: { Ty , TypeAndMut } ;
@@ -91,15 +91,11 @@ declare_lint_pass!(SignificantDropInScrutinee => [SIGNIFICANT_DROP_IN_SCRUTINEE]
91
91
92
92
impl < ' tcx > LateLintPass < ' tcx > for SignificantDropInScrutinee {
93
93
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > ) {
94
- if let Some ( suggestions) = has_significant_drop_in_scrutinee ( cx, expr) {
94
+ if let Some ( ( suggestions, message ) ) = has_significant_drop_in_scrutinee ( cx, expr) {
95
95
for found in suggestions {
96
- span_lint_and_then (
97
- cx,
98
- SIGNIFICANT_DROP_IN_SCRUTINEE ,
99
- found. found_span ,
100
- "temporary with significant drop in match scrutinee" ,
101
- |diag| set_diagnostic ( diag, cx, expr, found) ,
102
- ) ;
96
+ span_lint_and_then ( cx, SIGNIFICANT_DROP_IN_SCRUTINEE , found. found_span , message, |diag| {
97
+ set_diagnostic ( diag, cx, expr, found) ;
98
+ } ) ;
103
99
}
104
100
}
105
101
}
@@ -153,10 +149,25 @@ fn set_diagnostic<'tcx>(diag: &mut Diagnostic, cx: &LateContext<'tcx>, expr: &'t
153
149
fn has_significant_drop_in_scrutinee < ' tcx , ' a > (
154
150
cx : & ' a LateContext < ' tcx > ,
155
151
expr : & ' tcx Expr < ' tcx > ,
156
- ) -> Option < Vec < FoundSigDrop > > {
157
- let mut helper = SigDropHelper :: new ( cx) ;
152
+ ) -> Option < ( Vec < FoundSigDrop > , & ' static str ) > {
158
153
match expr. kind {
159
- ExprKind :: Match ( match_expr, _, _) => helper. find_sig_drop ( match_expr) ,
154
+ ExprKind :: Match ( match_expr, _, source) => {
155
+ match source {
156
+ MatchSource :: Normal | MatchSource :: ForLoopDesugar => {
157
+ let mut helper = SigDropHelper :: new ( cx) ;
158
+ helper. find_sig_drop ( match_expr) . map ( |drops| {
159
+ let message = if source == MatchSource :: Normal {
160
+ "temporary with significant drop in match scrutinee"
161
+ } else {
162
+ "temporary with significant drop in for loop"
163
+ } ;
164
+ ( drops, message)
165
+ } )
166
+ } ,
167
+ // MatchSource of TryDesugar or AwaitDesugar is out of scope for this lint
168
+ MatchSource :: TryDesugar | MatchSource :: AwaitDesugar => None ,
169
+ }
170
+ } ,
160
171
_ => None ,
161
172
}
162
173
}
@@ -213,6 +224,19 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> {
213
224
self . sig_drop_spans . take ( )
214
225
}
215
226
227
+ fn replace_current_sig_drop (
228
+ & mut self ,
229
+ found_span : Span ,
230
+ is_unit_return_val : bool ,
231
+ lint_suggestion : LintSuggestion ,
232
+ ) {
233
+ self . current_sig_drop . replace ( FoundSigDrop {
234
+ found_span,
235
+ is_unit_return_val,
236
+ lint_suggestion,
237
+ } ) ;
238
+ }
239
+
216
240
/// This will try to set the current suggestion (so it can be moved into the suggestions vec
217
241
/// later). If `allow_move_and_clone` is false, the suggestion *won't* be set -- this gives us
218
242
/// an opportunity to look for another type in the chain that will be trivially copyable.
@@ -229,25 +253,15 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> {
229
253
// but let's avoid any chance of an ICE
230
254
if let Some ( TypeAndMut { ty, .. } ) = ty. builtin_deref ( true ) {
231
255
if ty. is_trivially_pure_clone_copy ( ) {
232
- self . current_sig_drop . replace ( FoundSigDrop {
233
- found_span : expr. span ,
234
- is_unit_return_val : false ,
235
- lint_suggestion : LintSuggestion :: MoveAndDerefToCopy ,
236
- } ) ;
256
+ self . replace_current_sig_drop ( expr. span , false , LintSuggestion :: MoveAndDerefToCopy ) ;
237
257
} else if allow_move_and_clone {
238
- self . current_sig_drop . replace ( FoundSigDrop {
239
- found_span : expr. span ,
240
- is_unit_return_val : false ,
241
- lint_suggestion : LintSuggestion :: MoveAndClone ,
242
- } ) ;
258
+ self . replace_current_sig_drop ( expr. span , false , LintSuggestion :: MoveAndClone ) ;
243
259
}
244
260
}
245
261
} else if ty. is_trivially_pure_clone_copy ( ) {
246
- self . current_sig_drop . replace ( FoundSigDrop {
247
- found_span : expr. span ,
248
- is_unit_return_val : false ,
249
- lint_suggestion : LintSuggestion :: MoveOnly ,
250
- } ) ;
262
+ self . replace_current_sig_drop ( expr. span , false , LintSuggestion :: MoveOnly ) ;
263
+ } else if allow_move_and_clone {
264
+ self . replace_current_sig_drop ( expr. span , false , LintSuggestion :: MoveAndClone ) ;
251
265
}
252
266
}
253
267
@@ -279,11 +293,7 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> {
279
293
// If either side had a significant drop, suggest moving the entire scrutinee to avoid
280
294
// unnecessary copies and to simplify cases where both sides have significant drops.
281
295
if self . has_significant_drop {
282
- self . current_sig_drop . replace ( FoundSigDrop {
283
- found_span : span,
284
- is_unit_return_val,
285
- lint_suggestion : LintSuggestion :: MoveOnly ,
286
- } ) ;
296
+ self . replace_current_sig_drop ( span, is_unit_return_val, LintSuggestion :: MoveOnly ) ;
287
297
}
288
298
289
299
self . special_handling_for_binary_op = false ;
@@ -363,34 +373,34 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
363
373
}
364
374
}
365
375
ExprKind :: Box ( ..) |
366
- ExprKind :: Array ( ..) |
367
- ExprKind :: Call ( ..) |
368
- ExprKind :: Unary ( ..) |
369
- ExprKind :: If ( ..) |
370
- ExprKind :: Match ( ..) |
371
- ExprKind :: Field ( ..) |
372
- ExprKind :: Index ( ..) |
373
- ExprKind :: Ret ( ..) |
374
- ExprKind :: Repeat ( ..) |
375
- ExprKind :: Yield ( ..) |
376
- ExprKind :: MethodCall ( ..) => walk_expr ( self , ex) ,
376
+ ExprKind :: Array ( ..) |
377
+ ExprKind :: Call ( ..) |
378
+ ExprKind :: Unary ( ..) |
379
+ ExprKind :: If ( ..) |
380
+ ExprKind :: Match ( ..) |
381
+ ExprKind :: Field ( ..) |
382
+ ExprKind :: Index ( ..) |
383
+ ExprKind :: Ret ( ..) |
384
+ ExprKind :: Repeat ( ..) |
385
+ ExprKind :: Yield ( ..) |
386
+ ExprKind :: MethodCall ( ..) => walk_expr ( self , ex) ,
377
387
ExprKind :: AddrOf ( _, _, _) |
378
- ExprKind :: Block ( _, _) |
379
- ExprKind :: Break ( _, _) |
380
- ExprKind :: Cast ( _, _) |
381
- // Don't want to check the closure itself, only invocation, which is covered by MethodCall
382
- ExprKind :: Closure ( _, _, _, _, _) |
383
- ExprKind :: ConstBlock ( _) |
384
- ExprKind :: Continue ( _) |
385
- ExprKind :: DropTemps ( _) |
386
- ExprKind :: Err |
387
- ExprKind :: InlineAsm ( _) |
388
- ExprKind :: Let ( _) |
389
- ExprKind :: Lit ( _) |
390
- ExprKind :: Loop ( _, _, _, _) |
391
- ExprKind :: Path ( _) |
392
- ExprKind :: Struct ( _, _, _) |
393
- ExprKind :: Type ( _, _) => {
388
+ ExprKind :: Block ( _, _) |
389
+ ExprKind :: Break ( _, _) |
390
+ ExprKind :: Cast ( _, _) |
391
+ // Don't want to check the closure itself, only invocation, which is covered by MethodCall
392
+ ExprKind :: Closure ( _, _, _, _, _) |
393
+ ExprKind :: ConstBlock ( _) |
394
+ ExprKind :: Continue ( _) |
395
+ ExprKind :: DropTemps ( _) |
396
+ ExprKind :: Err |
397
+ ExprKind :: InlineAsm ( _) |
398
+ ExprKind :: Let ( _) |
399
+ ExprKind :: Lit ( _) |
400
+ ExprKind :: Loop ( _, _, _, _) |
401
+ ExprKind :: Path ( _) |
402
+ ExprKind :: Struct ( _, _, _) |
403
+ ExprKind :: Type ( _, _) => {
394
404
return ;
395
405
}
396
406
}
0 commit comments