@@ -28,13 +28,20 @@ fn place_has_common_prefix<'tcx>(left: &Place<'tcx>, right: &Place<'tcx>) -> boo
2828 && left. projection . iter ( ) . zip ( right. projection ) . all ( |( left, right) | left == right)
2929}
3030
31+ #[ derive( Debug , Clone , Copy ) ]
32+ enum MovePathIndexAtBlock {
33+ Unknown ,
34+ None ,
35+ Some ( MovePathIndex ) ,
36+ }
37+
3138struct DropsReachable < ' a , ' mir , ' tcx > {
3239 body : & ' a Body < ' tcx > ,
3340 place : & ' a Place < ' tcx > ,
3441 drop_span : & ' a mut Option < Span > ,
3542 move_data : & ' a MoveData < ' tcx > ,
3643 maybe_init : & ' a mut ResultsCursor < ' mir , ' tcx , MaybeInitializedPlaces < ' mir , ' tcx > > ,
37- block_drop_value_info : & ' a mut IndexSlice < BasicBlock , Option < MovePathIndex > > ,
44+ block_drop_value_info : & ' a mut IndexSlice < BasicBlock , MovePathIndexAtBlock > ,
3845 collected_drops : & ' a mut ChunkedBitSet < MovePathIndex > ,
3946 visited : FxHashMap < BasicBlock , Rc < RefCell < ChunkedBitSet < MovePathIndex > > > > ,
4047}
@@ -53,27 +60,35 @@ impl<'a, 'mir, 'tcx> DropsReachable<'a, 'mir, 'tcx> {
5360 self . visited . entry ( block) . or_insert_with ( make_new_path_set) . clone ( ) ;
5461 // We could have invoked reverse lookup for a `MovePathIndex` every time, but unfortunately it is expensive.
5562 // Let's cache them in `self.block_drop_value_info`.
56- if let Some ( dropped) = self . block_drop_value_info [ block] {
57- dropped_local_here. borrow_mut ( ) . insert ( dropped) ;
58- } else if let TerminatorKind :: Drop { place, .. } = & terminator. kind
59- && let LookupResult :: Exact ( idx) | LookupResult :: Parent ( Some ( idx) ) =
60- self . move_data . rev_lookup . find ( place. as_ref ( ) )
61- {
62- // Since we are working with MIRs at a very early stage,
63- // observing a `drop` terminator is not indicative enough that
64- // the drop will definitely happen.
65- // That is decided in the drop elaboration pass instead.
66- // Therefore, we need to consult with the maybe-initialization information.
67- self . maybe_init . seek_before_primary_effect ( Location {
68- block,
69- statement_index : data. statements . len ( ) ,
70- } ) ;
71- if let MaybeReachable :: Reachable ( maybe_init) = self . maybe_init . get ( )
72- && maybe_init. contains ( idx)
73- {
74- self . block_drop_value_info [ block] = Some ( idx) ;
75- dropped_local_here. borrow_mut ( ) . insert ( idx) ;
63+ match self . block_drop_value_info [ block] {
64+ MovePathIndexAtBlock :: Some ( dropped) => {
65+ dropped_local_here. borrow_mut ( ) . insert ( dropped) ;
66+ }
67+ MovePathIndexAtBlock :: Unknown => {
68+ if let TerminatorKind :: Drop { place, .. } = & terminator. kind
69+ && let LookupResult :: Exact ( idx) | LookupResult :: Parent ( Some ( idx) ) =
70+ self . move_data . rev_lookup . find ( place. as_ref ( ) )
71+ {
72+ // Since we are working with MIRs at a very early stage,
73+ // observing a `drop` terminator is not indicative enough that
74+ // the drop will definitely happen.
75+ // That is decided in the drop elaboration pass instead.
76+ // Therefore, we need to consult with the maybe-initialization information.
77+ self . maybe_init . seek_before_primary_effect ( Location {
78+ block,
79+ statement_index : data. statements . len ( ) ,
80+ } ) ;
81+ if let MaybeReachable :: Reachable ( maybe_init) = self . maybe_init . get ( )
82+ && maybe_init. contains ( idx)
83+ {
84+ self . block_drop_value_info [ block] = MovePathIndexAtBlock :: Some ( idx) ;
85+ dropped_local_here. borrow_mut ( ) . insert ( idx) ;
86+ } else {
87+ self . block_drop_value_info [ block] = MovePathIndexAtBlock :: None ;
88+ }
89+ }
7690 }
91+ MovePathIndexAtBlock :: None => { }
7792 }
7893
7994 for succ in terminator. successors ( ) {
@@ -283,7 +298,8 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<
283298 let move_data = MoveData :: gather_moves ( body, tcx, |_| true ) ;
284299 let maybe_init = MaybeInitializedPlaces :: new ( tcx, body, & move_data) ;
285300 let mut maybe_init = maybe_init. iterate_to_fixpoint ( tcx, body, None ) . into_results_cursor ( body) ;
286- let mut block_drop_value_info = IndexVec :: from_elem_n ( None , body. basic_blocks . len ( ) ) ;
301+ let mut block_drop_value_info =
302+ IndexVec :: from_elem_n ( MovePathIndexAtBlock :: Unknown , body. basic_blocks . len ( ) ) ;
287303 for ( & block, candidates) in & bid_per_block {
288304 let mut all_locals_dropped = ChunkedBitSet :: new_empty ( move_data. move_paths . len ( ) ) ;
289305 let mut drop_span = None ;
0 commit comments