1
Fork 0

address review comments

This commit is contained in:
Ariel Ben-Yehuda 2016-05-27 15:07:08 +03:00
parent a091cfd4f3
commit 8d6d646203
3 changed files with 82 additions and 78 deletions

View file

@ -201,7 +201,7 @@ impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O>
pub struct DataflowResults<O>(DataflowState<O>) where O: BitDenotation; pub struct DataflowResults<O>(DataflowState<O>) where O: BitDenotation;
impl<O: BitDenotation> DataflowResults<O> { impl<O: BitDenotation> DataflowResults<O> {
pub fn sets(&self) -> &AllSets { pub fn sets(&self) -> &AllSets<O::Idx> {
&self.0.sets &self.0.sets
} }
} }

View file

@ -8,12 +8,12 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use bitslice::BitSlice; use indexed_set::IdxSetBuf;
use super::gather_moves::{MoveData, MovePathIndex, MovePathContent, Location}; use super::gather_moves::{MoveData, MovePathIndex, MovePathContent, Location};
use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
use super::dataflow::{DataflowResults}; use super::dataflow::{DataflowResults};
use super::{drop_flag_effects_for_location, on_all_children_bits}; use super::{drop_flag_effects_for_location, on_all_children_bits};
use super::{DropFlagState}; use super::{DropFlagState, MoveDataParamEnv};
use super::patch::MirPatch; use super::patch::MirPatch;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::{Subst, Substs, VecPerParamSpace}; use rustc::ty::subst::{Subst, Substs, VecPerParamSpace};
@ -44,23 +44,26 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
let move_data = MoveData::gather_moves(mir, tcx); let move_data = MoveData::gather_moves(mir, tcx);
let elaborate_patch = { let elaborate_patch = {
let mir = &*mir; let mir = &*mir;
let ((_, _, move_data), flow_inits) = let env = MoveDataParamEnv {
super::do_dataflow(tcx, mir, id, &[], (tcx, mir, move_data), move_data: move_data,
MaybeInitializedLvals::default()); param_env: param_env
let ((_, _, move_data), flow_uninits) = };
super::do_dataflow(tcx, mir, id, &[], (tcx, mir, move_data), let flow_inits =
MaybeUninitializedLvals::default()); super::do_dataflow(tcx, mir, id, &[], &env,
MaybeInitializedLvals::new(tcx, mir));
let flow_uninits =
super::do_dataflow(tcx, mir, id, &[], &env,
MaybeUninitializedLvals::new(tcx, mir));
match (tcx, mir, move_data) { ElaborateDropsCtxt {
ref ctxt => ElaborateDropsCtxt { tcx: tcx,
ctxt: ctxt, mir: mir,
param_env: &param_env, env: &env,
flow_inits: flow_inits, flow_inits: flow_inits,
flow_uninits: flow_uninits, flow_uninits: flow_uninits,
drop_flags: FnvHashMap(), drop_flags: FnvHashMap(),
patch: MirPatch::new(mir), patch: MirPatch::new(mir),
}.elaborate() }.elaborate()
}
}; };
pretty::dump_mir(tcx, "elaborate_drops", &0, src, mir, None); pretty::dump_mir(tcx, "elaborate_drops", &0, src, mir, None);
elaborate_patch.apply(mir); elaborate_patch.apply(mir);
@ -71,35 +74,35 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
impl Pass for ElaborateDrops {} impl Pass for ElaborateDrops {}
struct InitializationData { struct InitializationData {
live: Vec<usize>, live: IdxSetBuf<MovePathIndex>,
dead: Vec<usize> dead: IdxSetBuf<MovePathIndex>
} }
impl InitializationData { impl InitializationData {
fn apply_location<'a,'tcx>(&mut self, fn apply_location<'a,'tcx>(&mut self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>, mir: &Mir<'tcx>,
move_data: &MoveData<'tcx>, env: &MoveDataParamEnv<'tcx>,
loc: Location) loc: Location)
{ {
drop_flag_effects_for_location(tcx, mir, move_data, loc, |path, df| { drop_flag_effects_for_location(tcx, mir, env, loc, |path, df| {
debug!("at location {:?}: setting {:?} to {:?}", debug!("at location {:?}: setting {:?} to {:?}",
loc, path, df); loc, path, df);
match df { match df {
DropFlagState::Live => { DropFlagState::Present => {
self.live.set_bit(path.idx()); self.live.add(&path);
self.dead.clear_bit(path.idx()); self.dead.remove(&path);
} }
DropFlagState::Dead => { DropFlagState::Absent => {
self.dead.set_bit(path.idx()); self.dead.add(&path);
self.live.clear_bit(path.idx()); self.live.remove(&path);
} }
} }
}); });
} }
fn state(&self, path: MovePathIndex) -> (bool, bool) { fn state(&self, path: MovePathIndex) -> (bool, bool) {
(self.live.get_bit(path.idx()), self.dead.get_bit(path.idx())) (self.live.contains(&path), self.dead.contains(&path))
} }
} }
@ -110,8 +113,9 @@ impl fmt::Debug for InitializationData {
} }
struct ElaborateDropsCtxt<'a, 'tcx: 'a> { struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
ctxt: &'a (TyCtxt<'a, 'tcx, 'tcx>, &'a Mir<'tcx>, MoveData<'tcx>), tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: &'a ty::ParameterEnvironment<'tcx>, mir: &'a Mir<'tcx>,
env: &'a MoveDataParamEnv<'tcx>,
flow_inits: DataflowResults<MaybeInitializedLvals<'a, 'tcx>>, flow_inits: DataflowResults<MaybeInitializedLvals<'a, 'tcx>>,
flow_uninits: DataflowResults<MaybeUninitializedLvals<'a, 'tcx>>, flow_uninits: DataflowResults<MaybeUninitializedLvals<'a, 'tcx>>,
drop_flags: FnvHashMap<MovePathIndex, u32>, drop_flags: FnvHashMap<MovePathIndex, u32>,
@ -133,9 +137,10 @@ struct DropCtxt<'a, 'tcx: 'a> {
} }
impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> { self.ctxt.0 } fn move_data(&self) -> &'b MoveData<'tcx> { &self.env.move_data }
fn mir(&self) -> &'b Mir<'tcx> { self.ctxt.1 } fn param_env(&self) -> &'b ty::ParameterEnvironment<'tcx> {
fn move_data(&self) -> &'b MoveData<'tcx> { &self.ctxt.2 } &self.env.param_env
}
fn initialization_data_at(&self, loc: Location) -> InitializationData { fn initialization_data_at(&self, loc: Location) -> InitializationData {
let mut data = InitializationData { let mut data = InitializationData {
@ -145,14 +150,14 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
.to_owned(), .to_owned(),
}; };
for stmt in 0..loc.index { for stmt in 0..loc.index {
data.apply_location(self.ctxt.0, self.ctxt.1, &self.ctxt.2, data.apply_location(self.tcx, self.mir, self.env,
Location { block: loc.block, index: stmt }); Location { block: loc.block, index: stmt });
} }
data data
} }
fn create_drop_flag(&mut self, index: MovePathIndex) { fn create_drop_flag(&mut self, index: MovePathIndex) {
let tcx = self.tcx(); let tcx = self.tcx;
let patch = &mut self.patch; let patch = &mut self.patch;
self.drop_flags.entry(index).or_insert_with(|| { self.drop_flags.entry(index).or_insert_with(|| {
patch.new_temp(tcx.types.bool) patch.new_temp(tcx.types.bool)
@ -183,11 +188,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
{ {
match self.move_data().move_paths[path].content { match self.move_data().move_paths[path].content {
MovePathContent::Lvalue(ref lvalue) => { MovePathContent::Lvalue(ref lvalue) => {
let ty = self.mir().lvalue_ty(self.tcx(), lvalue) let ty = self.mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
.to_ty(self.tcx());
debug!("path_needs_drop({:?}, {:?} : {:?})", path, lvalue, ty); debug!("path_needs_drop({:?}, {:?} : {:?})", path, lvalue, ty);
self.tcx().type_needs_drop_given_env(ty, &self.param_env) self.tcx.type_needs_drop_given_env(ty, self.param_env())
} }
_ => false _ => false
} }
@ -210,7 +214,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
} }
fn lvalue_contents_are_tracked(&self, lv: &Lvalue<'tcx>) -> bool { fn lvalue_contents_are_tracked(&self, lv: &Lvalue<'tcx>) -> bool {
let ty = self.mir().lvalue_ty(self.tcx(), lv).to_ty(self.tcx()); let ty = self.mir.lvalue_ty(self.tcx, lv).to_ty(self.tcx);
match ty.sty { match ty.sty {
ty::TyArray(..) | ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => { ty::TyArray(..) | ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
false false
@ -221,8 +225,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
fn collect_drop_flags(&mut self) fn collect_drop_flags(&mut self)
{ {
for bb in self.mir().all_basic_blocks() { for bb in self.mir.all_basic_blocks() {
let data = self.mir().basic_block_data(bb); let data = self.mir.basic_block_data(bb);
let terminator = data.terminator(); let terminator = data.terminator();
let location = match terminator.kind { let location = match terminator.kind {
TerminatorKind::Drop { ref location, .. } | TerminatorKind::Drop { ref location, .. } |
@ -243,7 +247,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
debug!("collect_drop_flags: {:?}, lv {:?} (index {:?})", debug!("collect_drop_flags: {:?}, lv {:?} (index {:?})",
bb, location, path); bb, location, path);
on_all_children_bits(self.tcx(), self.mir(), self.move_data(), path, |child| { on_all_children_bits(self.tcx, self.mir, self.move_data(), path, |child| {
if self.path_needs_drop(child) { if self.path_needs_drop(child) {
let (maybe_live, maybe_dead) = init_data.state(child); let (maybe_live, maybe_dead) = init_data.state(child);
debug!("collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}", debug!("collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}",
@ -258,8 +262,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
fn elaborate_drops(&mut self) fn elaborate_drops(&mut self)
{ {
for bb in self.mir().all_basic_blocks() { for bb in self.mir.all_basic_blocks() {
let data = self.mir().basic_block_data(bb); let data = self.mir.basic_block_data(bb);
let loc = Location { block: bb, index: data.statements.len() }; let loc = Location { block: bb, index: data.statements.len() };
let terminator = data.terminator(); let terminator = data.terminator();
@ -320,7 +324,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
unwind: Option<BasicBlock>) unwind: Option<BasicBlock>)
{ {
let bb = loc.block; let bb = loc.block;
let data = self.mir().basic_block_data(bb); let data = self.mir.basic_block_data(bb);
let terminator = data.terminator(); let terminator = data.terminator();
let unwind = Some(unwind.unwrap_or_else(|| { let unwind = Some(unwind.unwrap_or_else(|| {
@ -354,12 +358,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
succ: target, succ: target,
unwind: unwind unwind: unwind
}, bb); }, bb);
on_all_children_bits(self.tcx(), self.mir(), self.move_data(), path, |child| { on_all_children_bits(self.tcx, self.mir, self.move_data(), path, |child| {
self.set_drop_flag(Location { block: target, index: 0 }, self.set_drop_flag(Location { block: target, index: 0 },
child, DropFlagState::Live); child, DropFlagState::Present);
if let Some(unwind) = unwind { if let Some(unwind) = unwind {
self.set_drop_flag(Location { block: unwind, index: 0 }, self.set_drop_flag(Location { block: unwind, index: 0 },
child, DropFlagState::Live); child, DropFlagState::Present);
} }
}); });
} }
@ -397,7 +401,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
let mut some_dead = false; let mut some_dead = false;
let mut children_count = 0; let mut children_count = 0;
on_all_children_bits( on_all_children_bits(
self.tcx(), self.mir(), self.move_data(), self.tcx, self.mir, self.move_data(),
c.path, |child| { c.path, |child| {
if self.path_needs_drop(child) { if self.path_needs_drop(child) {
let (live, dead) = c.init_data.state(child); let (live, dead) = c.init_data.state(child);
@ -463,9 +467,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
}); });
let field_ty = let field_ty =
self.tcx().normalize_associated_type_in_env( self.tcx.normalize_associated_type_in_env(
&f.ty(self.tcx(), substs), &f.ty(self.tcx, substs),
&self.param_env self.param_env()
); );
(base_lv.clone().field(Field::new(i), field_ty), subpath) (base_lv.clone().field(Field::new(i), field_ty), subpath)
}).collect() }).collect()
@ -704,7 +708,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
/// This creates a "drop ladder" that drops the needed fields of the /// This creates a "drop ladder" that drops the needed fields of the
/// ADT, both in the success case or if one of the destructors fail. /// ADT, both in the success case or if one of the destructors fail.
fn open_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock { fn open_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock {
let ty = self.mir().lvalue_ty(self.tcx(), c.lvalue).to_ty(self.tcx()); let ty = self.mir.lvalue_ty(self.tcx, c.lvalue).to_ty(self.tcx);
match ty.sty { match ty.sty {
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => { ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
self.open_drop_for_adt(c, def, substs) self.open_drop_for_adt(c, def, substs)
@ -741,7 +745,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
self.set_drop_flag( self.set_drop_flag(
Location { block: drop_block, index: 0 }, Location { block: drop_block, index: 0 },
c.path, c.path,
DropFlagState::Dead DropFlagState::Absent
); );
} }
@ -859,7 +863,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
}); });
} }
let tcx = self.tcx(); let tcx = self.tcx;
let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil())); let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil()));
let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
.unwrap_or_else(|e| tcx.sess.fatal(&e)); .unwrap_or_else(|e| tcx.sess.fatal(&e));
@ -896,12 +900,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
// dataflow can create unneeded children in some cases // dataflow can create unneeded children in some cases
// - be sure to ignore them. // - be sure to ignore them.
let ty = self.mir().lvalue_ty(self.tcx(), c.lvalue).to_ty(self.tcx()); let ty = self.mir.lvalue_ty(self.tcx, c.lvalue).to_ty(self.tcx);
match ty.sty { match ty.sty {
ty::TyStruct(def, _) | ty::TyEnum(def, _) => { ty::TyStruct(def, _) | ty::TyEnum(def, _) => {
if def.has_dtor() { if def.has_dtor() {
self.tcx().sess.span_warn( self.tcx.sess.span_warn(
c.span, c.span,
&format!("dataflow bug??? moving out of type with dtor {:?}", &format!("dataflow bug??? moving out of type with dtor {:?}",
c)); c));
@ -917,14 +921,14 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> { fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
Rvalue::Use(Operand::Constant(Constant { Rvalue::Use(Operand::Constant(Constant {
span: span, span: span,
ty: self.tcx().types.bool, ty: self.tcx.types.bool,
literal: Literal::Value { value: ConstVal::Bool(val) } literal: Literal::Value { value: ConstVal::Bool(val) }
})) }))
} }
fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagState) { fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagState) {
if let Some(&flag) = self.drop_flags.get(&path) { if let Some(&flag) = self.drop_flags.get(&path) {
let span = self.patch.context_for_location(self.mir(), loc).0; let span = self.patch.context_for_location(self.mir, loc).0;
let val = self.constant_bool(span, val.value()); let val = self.constant_bool(span, val.value());
self.patch.add_assign(loc, Lvalue::Temp(flag), val); self.patch.add_assign(loc, Lvalue::Temp(flag), val);
} }
@ -932,7 +936,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
fn drop_flags_on_init(&mut self) { fn drop_flags_on_init(&mut self) {
let loc = Location { block: START_BLOCK, index: 0 }; let loc = Location { block: START_BLOCK, index: 0 };
let span = self.patch.context_for_location(self.mir(), loc).0; let span = self.patch.context_for_location(self.mir, loc).0;
let false_ = self.constant_bool(span, false); let false_ = self.constant_bool(span, false);
for flag in self.drop_flags.values() { for flag in self.drop_flags.values() {
self.patch.add_assign(loc, Lvalue::Temp(*flag), false_.clone()); self.patch.add_assign(loc, Lvalue::Temp(*flag), false_.clone());
@ -940,8 +944,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
} }
fn drop_flags_for_fn_rets(&mut self) { fn drop_flags_for_fn_rets(&mut self) {
for bb in self.mir().all_basic_blocks() { for bb in self.mir.all_basic_blocks() {
let data = self.mir().basic_block_data(bb); let data = self.mir.basic_block_data(bb);
if let TerminatorKind::Call { if let TerminatorKind::Call {
destination: Some((ref lv, tgt)), cleanup: Some(_), .. destination: Some((ref lv, tgt)), cleanup: Some(_), ..
} = data.terminator().kind { } = data.terminator().kind {
@ -950,8 +954,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
let loc = Location { block: tgt, index: 0 }; let loc = Location { block: tgt, index: 0 };
let path = self.move_data().rev_lookup.find(lv); let path = self.move_data().rev_lookup.find(lv);
on_all_children_bits( on_all_children_bits(
self.tcx(), self.mir(), self.move_data(), path, self.tcx, self.mir, self.move_data(), path,
|child| self.set_drop_flag(loc, child, DropFlagState::Live) |child| self.set_drop_flag(loc, child, DropFlagState::Present)
); );
} }
} }
@ -960,7 +964,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
fn drop_flags_for_args(&mut self) { fn drop_flags_for_args(&mut self) {
let loc = Location { block: START_BLOCK, index: 0 }; let loc = Location { block: START_BLOCK, index: 0 };
super::drop_flag_effects_for_function_entry( super::drop_flag_effects_for_function_entry(
self.tcx(), self.mir(), self.move_data(), |path, ds| { self.tcx, self.mir, self.env, |path, ds| {
self.set_drop_flag(loc, path, ds); self.set_drop_flag(loc, path, ds);
} }
) )
@ -973,8 +977,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
// drop flags by themselves, to avoid the drop flags being // drop flags by themselves, to avoid the drop flags being
// clobbered before they are read. // clobbered before they are read.
for bb in self.mir().all_basic_blocks() { for bb in self.mir.all_basic_blocks() {
let data = self.mir().basic_block_data(bb); let data = self.mir.basic_block_data(bb);
debug!("drop_flags_for_locs({:?})", data); debug!("drop_flags_for_locs({:?})", data);
for i in 0..(data.statements.len()+1) { for i in 0..(data.statements.len()+1) {
debug!("drop_flag_for_locs: stmt {}", i); debug!("drop_flag_for_locs: stmt {}", i);
@ -999,8 +1003,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
} }
let loc = Location { block: bb, index: i }; let loc = Location { block: bb, index: i };
super::drop_flag_effects_for_location( super::drop_flag_effects_for_location(
self.tcx(), self.mir(), self.move_data(), loc, |path, ds| { self.tcx, self.mir, self.env, loc, |path, ds| {
if ds == DropFlagState::Dead || allow_initializations { if ds == DropFlagState::Absent || allow_initializations {
self.set_drop_flag(loc, path, ds) self.set_drop_flag(loc, path, ds)
} }
} }
@ -1018,8 +1022,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
let loc = Location { block: bb, index: data.statements.len() }; let loc = Location { block: bb, index: data.statements.len() };
let path = self.move_data().rev_lookup.find(lv); let path = self.move_data().rev_lookup.find(lv);
on_all_children_bits( on_all_children_bits(
self.tcx(), self.mir(), self.move_data(), path, self.tcx, self.mir, self.move_data(), path,
|child| self.set_drop_flag(loc, child, DropFlagState::Live) |child| self.set_drop_flag(loc, child, DropFlagState::Present)
); );
} }
} }
@ -1029,10 +1033,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
c: &DropCtxt<'a, 'tcx>, c: &DropCtxt<'a, 'tcx>,
bb: BasicBlock) bb: BasicBlock)
{ {
let loc = self.patch.terminator_loc(self.mir(), bb); let loc = self.patch.terminator_loc(self.mir, bb);
on_all_children_bits( on_all_children_bits(
self.tcx(), self.mir(), self.move_data(), c.path, self.tcx, self.mir, self.move_data(), c.path,
|child| self.set_drop_flag(loc, child, DropFlagState::Dead) |child| self.set_drop_flag(loc, child, DropFlagState::Absent)
); );
} }
} }

View file

@ -207,8 +207,8 @@ enum DropFlagState {
impl DropFlagState { impl DropFlagState {
fn value(self) -> bool { fn value(self) -> bool {
match self { match self {
DropFlagState::Live => true, DropFlagState::Present => true,
DropFlagState::Dead => false DropFlagState::Absent => false
} }
} }
} }