@@ -4,7 +4,7 @@ use clippy_utils::get_attr;
44use clippy_utils:: source:: { indent_of, snippet} ;
55use rustc_errors:: { Applicability , Diagnostic } ;
66use rustc_hir:: intravisit:: { walk_expr, Visitor } ;
7- use rustc_hir:: { Expr , ExprKind } ;
7+ use rustc_hir:: { Expr , ExprKind , MatchSource } ;
88use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
99use rustc_middle:: ty:: subst:: GenericArgKind ;
1010use rustc_middle:: ty:: { Ty , TypeAndMut } ;
@@ -91,15 +91,11 @@ declare_lint_pass!(SignificantDropInScrutinee => [SIGNIFICANT_DROP_IN_SCRUTINEE]
9191
9292impl < ' tcx > LateLintPass < ' tcx > for SignificantDropInScrutinee {
9393 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) {
9595 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+ } ) ;
10399 }
104100 }
105101 }
@@ -153,10 +149,25 @@ fn set_diagnostic<'tcx>(diag: &mut Diagnostic, cx: &LateContext<'tcx>, expr: &'t
153149fn has_significant_drop_in_scrutinee < ' tcx , ' a > (
154150 cx : & ' a LateContext < ' tcx > ,
155151 expr : & ' tcx Expr < ' tcx > ,
156- ) -> Option < Vec < FoundSigDrop > > {
157- let mut helper = SigDropHelper :: new ( cx) ;
152+ ) -> Option < ( Vec < FoundSigDrop > , & ' static str ) > {
158153 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+ } ,
160171 _ => None ,
161172 }
162173}
@@ -213,6 +224,19 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> {
213224 self . sig_drop_spans . take ( )
214225 }
215226
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+
216240 /// This will try to set the current suggestion (so it can be moved into the suggestions vec
217241 /// later). If `allow_move_and_clone` is false, the suggestion *won't* be set -- this gives us
218242 /// 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> {
229253 // but let's avoid any chance of an ICE
230254 if let Some ( TypeAndMut { ty, .. } ) = ty. builtin_deref ( true ) {
231255 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 ) ;
237257 } 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 ) ;
243259 }
244260 }
245261 } 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 ) ;
251265 }
252266 }
253267
@@ -279,11 +293,7 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> {
279293 // If either side had a significant drop, suggest moving the entire scrutinee to avoid
280294 // unnecessary copies and to simplify cases where both sides have significant drops.
281295 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 ) ;
287297 }
288298
289299 self . special_handling_for_binary_op = false ;
@@ -363,34 +373,34 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
363373 }
364374 }
365375 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) ,
377387 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 ( _, _) => {
394404 return ;
395405 }
396406 }
0 commit comments