@@ -16,7 +16,7 @@ use rustc_span::Span;
16
16
17
17
use super :: SIGNIFICANT_DROP_IN_SCRUTINEE ;
18
18
19
- pub ( super ) fn check < ' tcx > (
19
+ pub ( super ) fn check_match < ' tcx > (
20
20
cx : & LateContext < ' tcx > ,
21
21
expr : & ' tcx Expr < ' tcx > ,
22
22
scrutinee : & ' tcx Expr < ' _ > ,
@@ -27,10 +27,89 @@ pub(super) fn check<'tcx>(
27
27
return ;
28
28
}
29
29
30
- let ( suggestions, message) = has_significant_drop_in_scrutinee ( cx, scrutinee, source) ;
30
+ let scrutinee = match ( source, & scrutinee. kind ) {
31
+ ( MatchSource :: ForLoopDesugar , ExprKind :: Call ( _, [ e] ) ) => e,
32
+ _ => scrutinee,
33
+ } ;
34
+
35
+ let message = if source == MatchSource :: Normal {
36
+ "temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression"
37
+ } else {
38
+ "temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression"
39
+ } ;
40
+
41
+ let arms = arms. iter ( ) . map ( |arm| arm. body ) . collect :: < Vec < _ > > ( ) ;
42
+
43
+ check ( cx, expr, scrutinee, & arms, message, Suggestion :: Emit ) ;
44
+ }
45
+
46
+ pub ( super ) fn check_if_let < ' tcx > (
47
+ cx : & LateContext < ' tcx > ,
48
+ expr : & ' tcx Expr < ' tcx > ,
49
+ scrutinee : & ' tcx Expr < ' _ > ,
50
+ if_then : & ' tcx Expr < ' _ > ,
51
+ if_else : Option < & ' tcx Expr < ' _ > > ,
52
+ ) {
53
+ if is_lint_allowed ( cx, SIGNIFICANT_DROP_IN_SCRUTINEE , expr. hir_id ) {
54
+ return ;
55
+ }
56
+
57
+ let message =
58
+ "temporary with significant `Drop` in `if let` scrutinee will live until the end of the `if let` expression" ;
59
+
60
+ if let Some ( if_else) = if_else {
61
+ check ( cx, expr, scrutinee, & [ if_then, if_else] , message, Suggestion :: Emit ) ;
62
+ } else {
63
+ check ( cx, expr, scrutinee, & [ if_then] , message, Suggestion :: Emit ) ;
64
+ }
65
+ }
66
+
67
+ pub ( super ) fn check_while_let < ' tcx > (
68
+ cx : & LateContext < ' tcx > ,
69
+ expr : & ' tcx Expr < ' tcx > ,
70
+ scrutinee : & ' tcx Expr < ' _ > ,
71
+ body : & ' tcx Expr < ' _ > ,
72
+ ) {
73
+ if is_lint_allowed ( cx, SIGNIFICANT_DROP_IN_SCRUTINEE , expr. hir_id ) {
74
+ return ;
75
+ }
76
+
77
+ check (
78
+ cx,
79
+ expr,
80
+ scrutinee,
81
+ & [ body] ,
82
+ "temporary with significant `Drop` in `while let` scrutinee will live until the end of the `while let` expression" ,
83
+ // Don't emit wrong suggestions: We cannot fix the significant drop in the `while let` scrutinee by simply
84
+ // moving it out. We need to change the `while` to a `loop` instead.
85
+ Suggestion :: DontEmit ,
86
+ ) ;
87
+ }
88
+
89
+ #[ derive( Copy , Clone , Debug ) ]
90
+ enum Suggestion {
91
+ Emit ,
92
+ DontEmit ,
93
+ }
94
+
95
+ fn check < ' tcx > (
96
+ cx : & LateContext < ' tcx > ,
97
+ expr : & ' tcx Expr < ' tcx > ,
98
+ scrutinee : & ' tcx Expr < ' _ > ,
99
+ arms : & [ & ' tcx Expr < ' _ > ] ,
100
+ message : & ' static str ,
101
+ sugg : Suggestion ,
102
+ ) {
103
+ let mut helper = SigDropHelper :: new ( cx) ;
104
+ let suggestions = helper. find_sig_drop ( scrutinee) ;
105
+
31
106
for found in suggestions {
32
107
span_lint_and_then ( cx, SIGNIFICANT_DROP_IN_SCRUTINEE , found. found_span , message, |diag| {
33
- set_diagnostic ( diag, cx, expr, found) ;
108
+ match sugg {
109
+ Suggestion :: Emit => set_suggestion ( diag, cx, expr, found) ,
110
+ Suggestion :: DontEmit => ( ) ,
111
+ }
112
+
34
113
let s = Span :: new ( expr. span . hi ( ) , expr. span . hi ( ) , expr. span . ctxt ( ) , None ) ;
35
114
diag. span_label ( s, "temporary lives until here" ) ;
36
115
for span in has_significant_drop_in_arms ( cx, arms) {
@@ -41,7 +120,7 @@ pub(super) fn check<'tcx>(
41
120
}
42
121
}
43
122
44
- fn set_diagnostic < ' tcx > ( diag : & mut Diag < ' _ , ( ) > , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > , found : FoundSigDrop ) {
123
+ fn set_suggestion < ' tcx > ( diag : & mut Diag < ' _ , ( ) > , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > , found : FoundSigDrop ) {
45
124
let original = snippet ( cx, found. found_span , ".." ) ;
46
125
let trailing_indent = " " . repeat ( indent_of ( cx, found. found_span ) . unwrap_or ( 0 ) ) ;
47
126
@@ -79,26 +158,6 @@ fn set_diagnostic<'tcx>(diag: &mut Diag<'_, ()>, cx: &LateContext<'tcx>, expr: &
79
158
) ;
80
159
}
81
160
82
- /// If the expression is an `ExprKind::Match`, check if the scrutinee has a significant drop that
83
- /// may have a surprising lifetime.
84
- fn has_significant_drop_in_scrutinee < ' tcx > (
85
- cx : & LateContext < ' tcx > ,
86
- scrutinee : & ' tcx Expr < ' tcx > ,
87
- source : MatchSource ,
88
- ) -> ( Vec < FoundSigDrop > , & ' static str ) {
89
- let mut helper = SigDropHelper :: new ( cx) ;
90
- let scrutinee = match ( source, & scrutinee. kind ) {
91
- ( MatchSource :: ForLoopDesugar , ExprKind :: Call ( _, [ e] ) ) => e,
92
- _ => scrutinee,
93
- } ;
94
- let message = if source == MatchSource :: Normal {
95
- "temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression"
96
- } else {
97
- "temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression"
98
- } ;
99
- ( helper. find_sig_drop ( scrutinee) , message)
100
- }
101
-
102
161
struct SigDropChecker < ' a , ' tcx > {
103
162
seen_types : FxHashSet < Ty < ' tcx > > ,
104
163
cx : & ' a LateContext < ' tcx > ,
@@ -428,10 +487,10 @@ impl<'a, 'tcx> ArmSigDropHelper<'a, 'tcx> {
428
487
}
429
488
}
430
489
431
- fn has_significant_drop_in_arms < ' tcx > ( cx : & LateContext < ' tcx > , arms : & ' tcx [ Arm < ' _ > ] ) -> FxHashSet < Span > {
490
+ fn has_significant_drop_in_arms < ' tcx > ( cx : & LateContext < ' tcx > , arms : & [ & ' tcx Expr < ' _ > ] ) -> FxHashSet < Span > {
432
491
let mut helper = ArmSigDropHelper :: new ( cx) ;
433
492
for arm in arms {
434
- helper. visit_expr ( arm. body ) ;
493
+ helper. visit_expr ( arm) ;
435
494
}
436
495
helper. found_sig_drop_spans
437
496
}
0 commit comments