@@ -20,6 +20,7 @@ use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
20
20
use rustc:: mir:: { Statement , StatementKind , Terminator , TerminatorKind } ;
21
21
use transform:: nll;
22
22
23
+ use rustc_data_structures:: fx:: FxHashSet ;
23
24
use rustc_data_structures:: indexed_set:: { self , IdxSetBuf } ;
24
25
use rustc_data_structures:: indexed_vec:: { Idx } ;
25
26
@@ -136,6 +137,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
136
137
node_id : id,
137
138
move_data : & mdpe. move_data ,
138
139
param_env : param_env,
140
+ storage_drop_or_dead_error_reported : FxHashSet ( ) ,
139
141
} ;
140
142
141
143
let mut state = InProgress :: new ( flow_borrows,
@@ -153,6 +155,10 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
153
155
node_id : ast:: NodeId ,
154
156
move_data : & ' cx MoveData < ' tcx > ,
155
157
param_env : ParamEnv < ' gcx > ,
158
+ /// This field keeps track of when storage drop or dead errors are reported
159
+ /// in order to stop duplicate error reporting and identify the conditions required
160
+ /// for a "temporary value dropped here while still borrowed" error. See #45360.
161
+ storage_drop_or_dead_error_reported : FxHashSet < Local > ,
156
162
}
157
163
158
164
// (forced to be `pub` due to its use as an associated type below.)
@@ -281,10 +287,12 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
281
287
}
282
288
283
289
StatementKind :: StorageDead ( local) => {
284
- self . access_lvalue ( ContextKind :: StorageDead . new ( location) ,
285
- ( & Lvalue :: Local ( local) , span) ,
286
- ( Shallow ( None ) , Write ( WriteKind :: StorageDead ) ) ,
287
- flow_state) ;
290
+ if self . storage_drop_or_dead_error_reported . insert ( local) {
291
+ self . access_lvalue ( ContextKind :: StorageDead . new ( location) ,
292
+ ( & Lvalue :: Local ( local) , span) ,
293
+ ( Shallow ( None ) , Write ( WriteKind :: StorageDead ) ) ,
294
+ flow_state) ;
295
+ }
288
296
}
289
297
}
290
298
}
@@ -604,12 +612,23 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
604
612
let erased_ty = gcx. lift ( & self . tcx . erase_regions ( & ty) ) . unwrap ( ) ;
605
613
let moves_by_default = erased_ty. moves_by_default ( gcx, self . param_env , DUMMY_SP ) ;
606
614
607
- if moves_by_default {
608
- // move of lvalue: check if this is move of already borrowed path
609
- self . access_lvalue ( context, lvalue_span, ( Deep , Write ( WriteKind :: Move ) ) , flow_state) ;
610
- } else {
611
- // copy of lvalue: check if this is "copy of frozen path" (FIXME: see check_loans.rs)
612
- self . access_lvalue ( context, lvalue_span, ( Deep , Read ( ReadKind :: Copy ) ) , flow_state) ;
615
+ // Check if error has already been reported to stop duplicate reporting.
616
+ let has_storage_drop_or_dead_error_reported = match * lvalue {
617
+ Lvalue :: Local ( local) => self . storage_drop_or_dead_error_reported . insert ( local) ,
618
+ _ => false ,
619
+ } ;
620
+
621
+ if !has_storage_drop_or_dead_error_reported {
622
+ if moves_by_default {
623
+ // move of lvalue: check if this is move of already borrowed path
624
+ self . access_lvalue ( context, lvalue_span, ( Deep , Write ( WriteKind :: Move ) ) ,
625
+ flow_state) ;
626
+ } else {
627
+ // copy of lvalue: check if this is "copy of frozen path"
628
+ // (FIXME: see check_loans.rs)
629
+ self . access_lvalue ( context, lvalue_span, ( Deep , Read ( ReadKind :: Copy ) ) ,
630
+ flow_state) ;
631
+ }
613
632
}
614
633
615
634
// Finally, check if path was already moved.
0 commit comments