/// This elaborates a single drop instruction, located at `bb`, and
/// patches over it.
///
/// The elaborated drop checks the drop flags to only drop what
/// is initialized.
///
/// In addition, the relevant drop flags also need to be cleared
/// to avoid double-drops. However, in the middle of a complex
/// drop, one must avoid clearing some of the flags before they
/// are read, as that would cause a memory leak.
///
/// In particular, when dropping an ADT, multiple fields may be
/// joined together under the `rest` subpath. They are all controlled
/// by the primary drop flag, but only the last rest-field dropped
/// should clear it (and it must also not clear anything else).
///
/// FIXME: I think we should just control the flags externally
/// and then we do not need this machinery.
This elaborates a single drop instruction, located at `bb`, and
patches over it.

The elaborated drop checks the drop flags to only drop what
is initialized.

In addition, the relevant drop flags also need to be cleared
to avoid double-drops. However, in the middle of a complex
drop, one must avoid clearing some of the flags before they
are read, as that would cause a memory leak.

In particular, when dropping an ADT, multiple fields may be
joined together under the `rest` subpath. They are all controlled
by the primary drop flag, but only the last rest-field dropped
should clear it (and it must also not clear anything else).

I think we should just control the flags externally
and then we do not need this machinery.
This elaborates a single drop instruction located at ` bb ` and patches over it . The elaborated drop checks the drop flags to only drop what is initialized . In addition the relevant drop flags also need to be cleared to avoid double - drops . However in the middle of a complex drop one must avoid clearing some of the flags before they are read as that would cause a memory leak . In particular when dropping an ADT multiple fields may be joined together under the ` rest ` subpath . They are all controlled by the primary drop flag but only the last rest - field dropped should clear it ( and it must also not clear anything else ) . I think we should just control the flags externally and then we do not need this machinery .
fn elaborate_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>, bb: BasicBlock) {
        debug!("elaborate_drop({:?})", c);
        let mut some_live = false;
        let mut some_dead = false;
        let mut children_count = 0;
        on_all_children_bits(
            self.tcx, self.mir, self.move_data(),
            c.path, |child| {
                if self.path_needs_drop(child) {
                    let (live, dead) = c.init_data.state(child);
                    debug!("elaborate_drop: state({:?}) = {:?}",
                           child, (live, dead));
                    some_live |= live;
                    some_dead |= dead;
                    children_count += 1;
                }
            });
        debug!("elaborate_drop({:?}): live - {:?}", c,
               (some_live, some_dead));
        match (some_live, some_dead) {
            (false, false) | (false, true) => {
                // dead drop - patch it out
                self.patch.patch_terminator(bb, TerminatorKind::Goto {
                    target: c.succ
                });
            }
            (true, false) => {
                // static drop - just set the flag
                self.patch.patch_terminator(bb, TerminatorKind::Drop {
                    location: c.lvalue.clone(),
                    target: c.succ,
                    unwind: c.unwind
                });
                self.drop_flags_for_drop(c, bb);
            }
            (true, true) => {
                // dynamic drop
                let drop_bb = if children_count == 1 || self.must_complete_drop(c) {
                    self.conditional_drop(c)
                } else {
                    self.open_drop(c)
                };
                self.patch.patch_terminator(bb, TerminatorKind::Goto {
                    target: drop_bb
                });
            }
        }
    }
fn elaborate_drop < ' a > ( & mut self , c : & DropCtxt < ' a , ' tcx > , bb : BasicBlock ) { debug ! ( " " c ) ; let mut some_live = false ; let mut some_dead = false ; let mut children_count = 0 ; on_all_children_bits ( self . tcx , self . mir , self . move_data ( ) , c . path , | child | { if self . path_needs_drop ( child ) { let ( live , dead ) = c . init_data . state ( child ) ; debug ! ( " " child ( live dead ) ) ; some_live |= live ; some_dead |= dead ; children_count += 1 ; } } ) ; debug ! ( " " c ( some_live some_dead ) ) ; match ( some_live , some_dead ) { ( false , false ) | ( false , true ) => { // dead drop - patch it out self . patch . patch_terminator ( bb , TerminatorKind :: Goto { target : c . succ } ) ; } ( true , false ) => { // static drop - just set the flag self . patch . patch_terminator ( bb , TerminatorKind :: Drop { location : c . lvalue . clone ( ) , target : c . succ , unwind : c . unwind } ) ; self . drop_flags_for_drop ( c , bb ) ; } ( true , true ) => { // dynamic drop let drop_bb = if children_count == 1 || self . must_complete_drop ( c ) { self . conditional_drop ( c ) } else { self . open_drop ( c ) } ; self . patch . patch_terminator ( bb , TerminatorKind :: Goto { target : drop_bb } ) ; } } }
This elaborates a single drop instruction, located at `bb`, and
patches over it.
This elaborates a single drop instruction located at ` bb ` and patches over it .
&mut self
c
&DropCtxt<'a, 'tcx>
bb
BasicBlock