1
Fork 0

address review comments

This commit is contained in:
Ariel Ben-Yehuda 2017-05-12 15:00:36 +03:00
parent 24c1a07c72
commit c6d0b5bdd8
4 changed files with 138 additions and 127 deletions

View file

@ -585,7 +585,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}) })
} }
pub fn const_usize(&self, val: usize) -> ConstInt { pub fn const_usize(&self, val: u16) -> ConstInt {
match self.sess.target.uint_type { match self.sess.target.uint_type {
ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(val as u16)), ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(val as u16)),
ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(val as u32)), ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(val as u32)),

View file

@ -22,7 +22,7 @@ use rustc::util::nodemap::FxHashMap;
use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_set::IdxSetBuf;
use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::Idx;
use rustc_mir::util::patch::MirPatch; use rustc_mir::util::patch::MirPatch;
use rustc_mir::util::elaborate_drops::{DropFlagState, elaborate_drop}; use rustc_mir::util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
use rustc_mir::util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode}; use rustc_mir::util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
use syntax::ast; use syntax::ast;
use syntax_pos::Span; use syntax_pos::Span;
@ -399,14 +399,13 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
ctxt: self ctxt: self
}, },
terminator.source_info, terminator.source_info,
data.is_cleanup,
location, location,
path, path,
target, target,
if data.is_cleanup { if data.is_cleanup {
None Unwind::InCleanup
} else { } else {
Some(Option::unwrap_or(unwind, resume_block)) Unwind::To(Option::unwrap_or(unwind, resume_block))
}, },
bb) bb)
} }
@ -455,6 +454,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
let bb = loc.block; let bb = loc.block;
let data = &self.mir[bb]; let data = &self.mir[bb];
let terminator = data.terminator(); let terminator = data.terminator();
assert!(!data.is_cleanup, "DropAndReplace in unwind path not supported");
let assign = Statement { let assign = Statement {
kind: StatementKind::Assign(location.clone(), Rvalue::Use(value.clone())), kind: StatementKind::Assign(location.clone(), Rvalue::Use(value.clone())),
@ -477,7 +477,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
kind: TerminatorKind::Goto { target: target }, kind: TerminatorKind::Goto { target: target },
..*terminator ..*terminator
}), }),
is_cleanup: data.is_cleanup, is_cleanup: false,
}); });
match self.move_data().rev_lookup.find(location) { match self.move_data().rev_lookup.find(location) {
@ -491,11 +491,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
ctxt: self ctxt: self
}, },
terminator.source_info, terminator.source_info,
data.is_cleanup,
location, location,
path, path,
target, target,
Some(unwind), Unwind::To(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, statement_index: 0 }, self.set_drop_flag(Location { block: target, statement_index: 0 },

View file

@ -198,11 +198,10 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
elaborate_drops::elaborate_drop( elaborate_drops::elaborate_drop(
&mut elaborator, &mut elaborator,
source_info, source_info,
false,
&dropee, &dropee,
(), (),
return_block, return_block,
Some(resume_block), elaborate_drops::Unwind::To(resume_block),
START_BLOCK START_BLOCK
); );
elaborator.patch elaborator.patch

View file

@ -50,6 +50,35 @@ pub enum DropFlagMode {
Deep Deep
} }
#[derive(Copy, Clone, Debug)]
pub enum Unwind {
To(BasicBlock),
InCleanup
}
impl Unwind {
fn is_cleanup(self) -> bool {
match self {
Unwind::To(..) => false,
Unwind::InCleanup => true
}
}
fn into_option(self) -> Option<BasicBlock> {
match self {
Unwind::To(bb) => Some(bb),
Unwind::InCleanup => None,
}
}
fn map<F>(self, f: F) -> Self where F: FnOnce(BasicBlock) -> BasicBlock {
match self {
Unwind::To(bb) => Unwind::To(f(bb)),
Unwind::InCleanup => Unwind::InCleanup
}
}
}
pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug { pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug {
type Path : Copy + fmt::Debug; type Path : Copy + fmt::Debug;
@ -75,28 +104,25 @@ struct DropCtxt<'l, 'b: 'l, 'tcx: 'b, D>
elaborator: &'l mut D, elaborator: &'l mut D,
source_info: SourceInfo, source_info: SourceInfo,
is_cleanup: bool,
lvalue: &'l Lvalue<'tcx>, lvalue: &'l Lvalue<'tcx>,
path: D::Path, path: D::Path,
succ: BasicBlock, succ: BasicBlock,
unwind: Option<BasicBlock>, unwind: Unwind,
} }
pub fn elaborate_drop<'b, 'tcx, D>( pub fn elaborate_drop<'b, 'tcx, D>(
elaborator: &mut D, elaborator: &mut D,
source_info: SourceInfo, source_info: SourceInfo,
is_cleanup: bool,
lvalue: &Lvalue<'tcx>, lvalue: &Lvalue<'tcx>,
path: D::Path, path: D::Path,
succ: BasicBlock, succ: BasicBlock,
unwind: Option<BasicBlock>, unwind: Unwind,
bb: BasicBlock) bb: BasicBlock)
where D: DropElaborator<'b, 'tcx> where D: DropElaborator<'b, 'tcx>
{ {
assert_eq!(unwind.is_none(), is_cleanup);
DropCtxt { DropCtxt {
elaborator, source_info, is_cleanup, lvalue, path, succ, unwind elaborator, source_info, lvalue, path, succ, unwind
}.elaborate_drop(bb) }.elaborate_drop(bb)
} }
@ -145,14 +171,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
self.elaborator.patch().patch_terminator(bb, TerminatorKind::Drop { self.elaborator.patch().patch_terminator(bb, TerminatorKind::Drop {
location: self.lvalue.clone(), location: self.lvalue.clone(),
target: self.succ, target: self.succ,
unwind: self.unwind unwind: self.unwind.into_option(),
}); });
} }
DropStyle::Conditional => { DropStyle::Conditional => {
let is_cleanup = self.is_cleanup; // FIXME(#6393) let unwind = self.unwind; // FIXME(#6393)
let succ = self.succ; let succ = self.succ;
let drop_bb = self.complete_drop( let drop_bb = self.complete_drop(Some(DropFlagMode::Deep), succ, unwind);
is_cleanup, Some(DropFlagMode::Deep), succ);
self.elaborator.patch().patch_terminator(bb, TerminatorKind::Goto { self.elaborator.patch().patch_terminator(bb, TerminatorKind::Goto {
target: drop_bb target: drop_bb
}); });
@ -189,11 +214,10 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
} }
fn drop_subpath(&mut self, fn drop_subpath(&mut self,
is_cleanup: bool,
lvalue: &Lvalue<'tcx>, lvalue: &Lvalue<'tcx>,
path: Option<D::Path>, path: Option<D::Path>,
succ: BasicBlock, succ: BasicBlock,
unwind: Option<BasicBlock>) unwind: Unwind)
-> BasicBlock -> BasicBlock
{ {
if let Some(path) = path { if let Some(path) = path {
@ -202,7 +226,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
DropCtxt { DropCtxt {
elaborator: self.elaborator, elaborator: self.elaborator,
source_info: self.source_info, source_info: self.source_info,
path, lvalue, succ, unwind, is_cleanup path, lvalue, succ, unwind,
}.elaborated_drop_block() }.elaborated_drop_block()
} else { } else {
debug!("drop_subpath: for rest field {:?}", lvalue); debug!("drop_subpath: for rest field {:?}", lvalue);
@ -210,11 +234,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
DropCtxt { DropCtxt {
elaborator: self.elaborator, elaborator: self.elaborator,
source_info: self.source_info, source_info: self.source_info,
lvalue, succ, unwind, is_cleanup, lvalue, succ, unwind,
// Using `self.path` here to condition the drop on // Using `self.path` here to condition the drop on
// our own drop flag. // our own drop flag.
path: self.path path: self.path
}.complete_drop(is_cleanup, None, succ) }.complete_drop(None, succ, unwind)
} }
} }
@ -222,24 +246,15 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
/// the list of steps in it in reverse order. /// the list of steps in it in reverse order.
/// ///
/// `unwind_ladder` is such a list of steps in reverse order, /// `unwind_ladder` is such a list of steps in reverse order,
/// which is called instead of the next step if the drop unwinds /// which is called if the matching step of the drop glue panics.
/// (the first field is never reached). If it is `None`, all fn drop_halfladder(&mut self,
/// unwind targets are left blank. unwind_ladder: &[Unwind],
fn drop_halfladder<'a>(&mut self, succ: BasicBlock,
unwind_ladder: Option<&[BasicBlock]>, fields: &[(Lvalue<'tcx>, Option<D::Path>)])
succ: BasicBlock, -> Vec<BasicBlock>
fields: &[(Lvalue<'tcx>, Option<D::Path>)],
is_cleanup: bool)
-> Vec<BasicBlock>
{ {
let mut unwind_succ = if is_cleanup {
None
} else {
self.unwind
};
let goto = TerminatorKind::Goto { target: succ }; let goto = TerminatorKind::Goto { target: succ };
let mut succ = self.new_block(is_cleanup, goto); let mut succ = self.new_block(unwind_ladder[0], goto);
// Always clear the "master" drop flag at the bottom of the // Always clear the "master" drop flag at the bottom of the
// ladder. This is needed because the "master" drop flag // ladder. This is needed because the "master" drop flag
@ -248,9 +263,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
let succ_loc = Location { block: succ, statement_index: 0 }; let succ_loc = Location { block: succ, statement_index: 0 };
self.elaborator.clear_drop_flag(succ_loc, self.path, DropFlagMode::Shallow); self.elaborator.clear_drop_flag(succ_loc, self.path, DropFlagMode::Shallow);
fields.iter().rev().enumerate().map(|(i, &(ref lv, path))| { fields.iter().rev().zip(unwind_ladder).map(|(&(ref lv, path), &unwind_succ)| {
succ = self.drop_subpath(is_cleanup, lv, path, succ, unwind_succ); succ = self.drop_subpath(lv, path, succ, unwind_succ);
unwind_succ = unwind_ladder.as_ref().map(|p| p[i]);
succ succ
}).collect() }).collect()
} }
@ -271,7 +285,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
/// ELAB(drop location.2 [target=`self.unwind`]) /// ELAB(drop location.2 [target=`self.unwind`])
fn drop_ladder<'a>(&mut self, fn drop_ladder<'a>(&mut self,
fields: Vec<(Lvalue<'tcx>, Option<D::Path>)>) fields: Vec<(Lvalue<'tcx>, Option<D::Path>)>)
-> (BasicBlock, Option<BasicBlock>) -> (BasicBlock, Unwind)
{ {
debug!("drop_ladder({:?}, {:?})", self, fields); debug!("drop_ladder({:?}, {:?})", self, fields);
@ -282,21 +296,21 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
debug!("drop_ladder - fields needing drop: {:?}", fields); debug!("drop_ladder - fields needing drop: {:?}", fields);
let unwind_ladder = if self.is_cleanup { let unwind_ladder = vec![Unwind::InCleanup; fields.len() + 1];
None let unwind_ladder: Vec<_> = if let Unwind::To(target) = self.unwind {
let halfladder = self.drop_halfladder(&unwind_ladder, target, &fields);
Some(self.unwind).into_iter().chain(halfladder.into_iter().map(Unwind::To))
.collect()
} else { } else {
let unwind = self.unwind.unwrap(); // FIXME(#6393) unwind_ladder
Some(self.drop_halfladder(None, unwind, &fields, true))
}; };
let succ = self.succ; // FIXME(#6393) let succ = self.succ; // FIXME(#6393)
let is_cleanup = self.is_cleanup;
let normal_ladder = let normal_ladder =
self.drop_halfladder(unwind_ladder.as_ref().map(|x| &**x), self.drop_halfladder(&unwind_ladder, succ, &fields);
succ, &fields, is_cleanup);
(normal_ladder.last().cloned().unwrap_or(succ), (normal_ladder.last().cloned().unwrap_or(succ),
unwind_ladder.and_then(|l| l.last().cloned()).or(self.unwind)) unwind_ladder.last().cloned().unwrap_or(self.unwind))
} }
fn open_drop_for_tuple<'a>(&mut self, tys: &[Ty<'tcx>]) fn open_drop_for_tuple<'a>(&mut self, tys: &[Ty<'tcx>])
@ -320,13 +334,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
let interior_path = self.elaborator.deref_subpath(self.path); let interior_path = self.elaborator.deref_subpath(self.path);
let succ = self.succ; // FIXME(#6393) let succ = self.succ; // FIXME(#6393)
let is_cleanup = self.is_cleanup; let unwind = self.unwind;
let succ = self.box_free_block(ty, succ, is_cleanup); let succ = self.box_free_block(ty, succ, unwind);
let unwind_succ = self.unwind.map(|u| { let unwind_succ = self.unwind.map(|unwind| {
self.box_free_block(ty, u, true) self.box_free_block(ty, unwind, Unwind::InCleanup)
}); });
self.drop_subpath(is_cleanup, &interior, interior_path, succ, unwind_succ) self.drop_subpath(&interior, interior_path, succ, unwind_succ)
} }
fn open_drop_for_adt<'a>(&mut self, adt: &'tcx ty::AdtDef, substs: &'tcx Substs<'tcx>) fn open_drop_for_adt<'a>(&mut self, adt: &'tcx ty::AdtDef, substs: &'tcx Substs<'tcx>)
@ -339,7 +353,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
source_info: self.source_info, source_info: self.source_info,
kind: TerminatorKind::Unreachable kind: TerminatorKind::Unreachable
}), }),
is_cleanup: self.is_cleanup is_cleanup: self.unwind.is_cleanup()
}); });
} }
@ -358,7 +372,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
fn open_drop_for_adt_contents<'a>(&mut self, adt: &'tcx ty::AdtDef, fn open_drop_for_adt_contents<'a>(&mut self, adt: &'tcx ty::AdtDef,
substs: &'tcx Substs<'tcx>) substs: &'tcx Substs<'tcx>)
-> (BasicBlock, Option<BasicBlock>) { -> (BasicBlock, Unwind) {
match adt.variants.len() { match adt.variants.len() {
1 => { 1 => {
let fields = self.move_paths_for_fields( let fields = self.move_paths_for_fields(
@ -370,13 +384,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
self.drop_ladder(fields) self.drop_ladder(fields)
} }
_ => { _ => {
let is_cleanup = self.is_cleanup;
let succ = self.succ; let succ = self.succ;
let unwind = self.unwind; // FIXME(#6393) let unwind = self.unwind; // FIXME(#6393)
let mut values = Vec::with_capacity(adt.variants.len()); let mut values = Vec::with_capacity(adt.variants.len());
let mut normal_blocks = Vec::with_capacity(adt.variants.len()); let mut normal_blocks = Vec::with_capacity(adt.variants.len());
let mut unwind_blocks = if is_cleanup { let mut unwind_blocks = if unwind.is_cleanup() {
None None
} else { } else {
Some(Vec::with_capacity(adt.variants.len())) Some(Vec::with_capacity(adt.variants.len()))
@ -396,7 +409,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
&adt.variants[variant_index], &adt.variants[variant_index],
substs); substs);
values.push(discr); values.push(discr);
if let Some(ref mut unwind_blocks) = unwind_blocks { if let Unwind::To(unwind) = unwind {
// We can't use the half-ladder from the original // We can't use the half-ladder from the original
// drop ladder, because this breaks the // drop ladder, because this breaks the
// "funclet can't have 2 successor funclets" // "funclet can't have 2 successor funclets"
@ -415,12 +428,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
// I want to minimize the divergence between MSVC // I want to minimize the divergence between MSVC
// and non-MSVC. // and non-MSVC.
let unwind = unwind.unwrap(); let unwind_blocks = unwind_blocks.as_mut().unwrap();
let halfladder = self.drop_halfladder( let unwind_ladder = vec![Unwind::InCleanup; fields.len() + 1];
None, unwind, &fields, true); let halfladder =
unwind_blocks.push( self.drop_halfladder(&unwind_ladder, unwind, &fields);
halfladder.last().cloned().unwrap_or(unwind) unwind_blocks.push(halfladder.last().cloned().unwrap_or(unwind));
);
} }
let (normal, _) = self.drop_ladder(fields); let (normal, _) = self.drop_ladder(fields);
normal_blocks.push(normal); normal_blocks.push(normal);
@ -428,14 +440,16 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
// variant not found - drop the entire enum // variant not found - drop the entire enum
if let None = otherwise { if let None = otherwise {
otherwise = Some(self.complete_drop( otherwise = Some(self.complete_drop(
is_cleanup,
Some(DropFlagMode::Shallow), Some(DropFlagMode::Shallow),
succ)); succ,
unwind_otherwise = unwind.map(|unwind| self.complete_drop( unwind));
true, if let Unwind::To(unwind) = unwind {
Some(DropFlagMode::Shallow), unwind_otherwise = Some(self.complete_drop(
unwind Some(DropFlagMode::Shallow),
)); unwind,
Unwind::InCleanup
));
}
} }
} }
} }
@ -448,10 +462,10 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
values.pop(); values.pop();
} }
(self.adt_switch_block(is_cleanup, adt, normal_blocks, &values, succ), (self.adt_switch_block(adt, normal_blocks, &values, succ, unwind),
unwind_blocks.map(|unwind_blocks| { unwind.map(|unwind| {
self.adt_switch_block( self.adt_switch_block(
is_cleanup, adt, unwind_blocks, &values, unwind.unwrap() adt, unwind_blocks.unwrap(), &values, unwind, Unwind::InCleanup
) )
})) }))
} }
@ -459,11 +473,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
} }
fn adt_switch_block(&mut self, fn adt_switch_block(&mut self,
is_cleanup: bool,
adt: &'tcx ty::AdtDef, adt: &'tcx ty::AdtDef,
blocks: Vec<BasicBlock>, blocks: Vec<BasicBlock>,
values: &[ConstInt], values: &[ConstInt],
succ: BasicBlock) succ: BasicBlock,
unwind: Unwind)
-> BasicBlock { -> BasicBlock {
// If there are multiple variants, then if something // If there are multiple variants, then if something
// is present within the enum the discriminant, tracked // is present within the enum the discriminant, tracked
@ -491,12 +505,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
targets: blocks, targets: blocks,
} }
}), }),
is_cleanup: is_cleanup, is_cleanup: unwind.is_cleanup(),
}); });
self.drop_flag_test_block(is_cleanup, switch_block, succ) self.drop_flag_test_block(switch_block, succ, unwind)
} }
fn destructor_call_block<'a>(&mut self, (succ, unwind): (BasicBlock, Option<BasicBlock>)) fn destructor_call_block<'a>(&mut self, (succ, unwind): (BasicBlock, Unwind))
-> BasicBlock -> BasicBlock
{ {
debug!("destructor_call_block({:?}, {:?})", self, succ); debug!("destructor_call_block({:?}, {:?})", self, succ);
@ -527,11 +541,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
self.source_info.span), self.source_info.span),
args: vec![Operand::Consume(Lvalue::Local(ref_lvalue))], args: vec![Operand::Consume(Lvalue::Local(ref_lvalue))],
destination: Some((unit_temp, succ)), destination: Some((unit_temp, succ)),
cleanup: unwind, cleanup: unwind.into_option(),
}, },
source_info: self.source_info source_info: self.source_info
}), }),
is_cleanup: self.is_cleanup, is_cleanup: unwind.is_cleanup(),
}) })
} }
@ -541,16 +555,15 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
/// can_go = index < len /// can_go = index < len
/// if can_go then drop-block else succ /// if can_go then drop-block else succ
/// drop-block: /// drop-block:
/// ptr = &mut LV[len] /// ptr = &mut LV[index]
/// index = index + 1 /// index = index + 1
/// drop(ptr) /// drop(ptr)
fn drop_loop(&mut self, fn drop_loop(&mut self,
unwind: Option<BasicBlock>,
succ: BasicBlock, succ: BasicBlock,
index: &Lvalue<'tcx>, index: &Lvalue<'tcx>,
length: &Lvalue<'tcx>, length: &Lvalue<'tcx>,
ety: Ty<'tcx>, ety: Ty<'tcx>,
is_cleanup: bool) unwind: Unwind)
-> BasicBlock -> BasicBlock
{ {
let use_ = |lv: &Lvalue<'tcx>| Operand::Consume(lv.clone()); let use_ = |lv: &Lvalue<'tcx>| Operand::Consume(lv.clone());
@ -576,10 +589,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
index.clone(), Rvalue::BinaryOp(BinOp::Add, use_(index), one) index.clone(), Rvalue::BinaryOp(BinOp::Add, use_(index), one)
)}, )},
], ],
is_cleanup, is_cleanup: unwind.is_cleanup(),
terminator: Some(Terminator { terminator: Some(Terminator {
source_info: self.source_info, source_info: self.source_info,
kind: TerminatorKind::Resume, // this gets overwritten by drop elaboration.
kind: TerminatorKind::Unreachable,
}) })
}); });
@ -589,7 +603,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
can_go.clone(), Rvalue::BinaryOp(BinOp::Lt, use_(index), use_(length)) can_go.clone(), Rvalue::BinaryOp(BinOp::Lt, use_(index), use_(length))
)}, )},
], ],
is_cleanup, is_cleanup: unwind.is_cleanup(),
terminator: Some(Terminator { terminator: Some(Terminator {
source_info: self.source_info, source_info: self.source_info,
kind: TerminatorKind::if_(tcx, use_(can_go), drop_block, succ) kind: TerminatorKind::if_(tcx, use_(can_go), drop_block, succ)
@ -599,7 +613,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
self.elaborator.patch().patch_terminator(drop_block, TerminatorKind::Drop { self.elaborator.patch().patch_terminator(drop_block, TerminatorKind::Drop {
location: ptr.clone().deref(), location: ptr.clone().deref(),
target: loop_block, target: loop_block,
unwind: unwind unwind: unwind.into_option()
}); });
loop_block loop_block
@ -614,12 +628,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
let length = &Lvalue::Local(self.new_temp(tcx.types.usize)); let length = &Lvalue::Local(self.new_temp(tcx.types.usize));
let unwind = self.unwind.map(|unwind| { let unwind = self.unwind.map(|unwind| {
self.drop_loop(None, unwind, index, length, ety, true) self.drop_loop(unwind, index, length, ety, Unwind::InCleanup)
}); });
let is_cleanup = self.is_cleanup;
let succ = self.succ; // FIXME(#6393) let succ = self.succ; // FIXME(#6393)
let loop_block = self.drop_loop(unwind, succ, index, length, ety, is_cleanup); let loop_block = self.drop_loop(succ, index, length, ety, unwind);
let zero = self.constant_usize(0); let zero = self.constant_usize(0);
let drop_block = self.elaborator.patch().new_block(BasicBlockData { let drop_block = self.elaborator.patch().new_block(BasicBlockData {
@ -631,7 +644,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
index.clone(), Rvalue::Use(zero), index.clone(), Rvalue::Use(zero),
)}, )},
], ],
is_cleanup, is_cleanup: unwind.is_cleanup(),
terminator: Some(Terminator { terminator: Some(Terminator {
source_info: self.source_info, source_info: self.source_info,
kind: TerminatorKind::Goto { target: loop_block } kind: TerminatorKind::Goto { target: loop_block }
@ -640,7 +653,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
// FIXME(#34708): handle partially-dropped array/slice elements. // FIXME(#34708): handle partially-dropped array/slice elements.
self.drop_flag_test_and_reset_block( self.drop_flag_test_and_reset_block(
is_cleanup, Some(DropFlagMode::Deep), drop_block, succ) Some(DropFlagMode::Deep), drop_block, succ, unwind)
} }
/// The slow-path - create an "open", elaborated drop for a type /// The slow-path - create an "open", elaborated drop for a type
@ -653,8 +666,6 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
/// 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) -> BasicBlock { fn open_drop<'a>(&mut self) -> BasicBlock {
let ty = self.lvalue_ty(self.lvalue); let ty = self.lvalue_ty(self.lvalue);
let is_cleanup = self.is_cleanup; // FIXME(#6393)
let succ = self.succ;
match ty.sty { match ty.sty {
ty::TyClosure(def_id, substs) => { ty::TyClosure(def_id, substs) => {
let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect(); let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect();
@ -670,7 +681,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
self.open_drop_for_adt(def, substs) self.open_drop_for_adt(def, substs)
} }
ty::TyDynamic(..) => { ty::TyDynamic(..) => {
self.complete_drop(is_cleanup, Some(DropFlagMode::Deep), succ) let unwind = self.unwind; // FIXME(#6393)
let succ = self.succ;
self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
} }
ty::TyArray(ety, _) | ty::TySlice(ety) => { ty::TyArray(ety, _) | ty::TySlice(ety) => {
self.open_drop_for_array(ety) self.open_drop_for_array(ety)
@ -687,21 +700,21 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
/// if let Some(mode) = mode: FLAG(self.path)[mode] = false /// if let Some(mode) = mode: FLAG(self.path)[mode] = false
/// drop(self.lv) /// drop(self.lv)
fn complete_drop<'a>(&mut self, fn complete_drop<'a>(&mut self,
is_cleanup: bool,
drop_mode: Option<DropFlagMode>, drop_mode: Option<DropFlagMode>,
succ: BasicBlock) -> BasicBlock succ: BasicBlock,
unwind: Unwind) -> BasicBlock
{ {
debug!("complete_drop({:?},{:?})", self, drop_mode); debug!("complete_drop({:?},{:?})", self, drop_mode);
let drop_block = self.drop_block(is_cleanup, succ); let drop_block = self.drop_block(succ, unwind);
self.drop_flag_test_and_reset_block(is_cleanup, drop_mode, drop_block, succ) self.drop_flag_test_and_reset_block(drop_mode, drop_block, succ, unwind)
} }
fn drop_flag_test_and_reset_block(&mut self, fn drop_flag_test_and_reset_block(&mut self,
is_cleanup: bool,
drop_mode: Option<DropFlagMode>, drop_mode: Option<DropFlagMode>,
drop_block: BasicBlock, drop_block: BasicBlock,
succ: BasicBlock) -> BasicBlock succ: BasicBlock,
unwind: Unwind) -> BasicBlock
{ {
debug!("drop_flag_test_and_reset_block({:?},{:?})", self, drop_mode); debug!("drop_flag_test_and_reset_block({:?},{:?})", self, drop_mode);
@ -710,14 +723,14 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
self.elaborator.clear_drop_flag(block_start, self.path, mode); self.elaborator.clear_drop_flag(block_start, self.path, mode);
} }
self.drop_flag_test_block(is_cleanup, drop_block, succ) self.drop_flag_test_block(drop_block, succ, unwind)
} }
fn elaborated_drop_block<'a>(&mut self) -> BasicBlock { fn elaborated_drop_block<'a>(&mut self) -> BasicBlock {
debug!("elaborated_drop_block({:?})", self); debug!("elaborated_drop_block({:?})", self);
let is_cleanup = self.is_cleanup; // FIXME(#6393) let unwind = self.unwind; // FIXME(#6393)
let succ = self.succ; let succ = self.succ;
let blk = self.drop_block(is_cleanup, succ); let blk = self.drop_block(succ, unwind);
self.elaborate_drop(blk); self.elaborate_drop(blk);
blk blk
} }
@ -726,17 +739,17 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
&mut self, &mut self,
ty: Ty<'tcx>, ty: Ty<'tcx>,
target: BasicBlock, target: BasicBlock,
is_cleanup: bool unwind: Unwind,
) -> BasicBlock { ) -> BasicBlock {
let block = self.unelaborated_free_block(ty, target, is_cleanup); let block = self.unelaborated_free_block(ty, target, unwind);
self.drop_flag_test_block(is_cleanup, block, target) self.drop_flag_test_block(block, target, unwind)
} }
fn unelaborated_free_block<'a>( fn unelaborated_free_block<'a>(
&mut self, &mut self,
ty: Ty<'tcx>, ty: Ty<'tcx>,
target: BasicBlock, target: BasicBlock,
is_cleanup: bool unwind: Unwind
) -> BasicBlock { ) -> BasicBlock {
let tcx = self.tcx(); let tcx = self.tcx();
let unit_temp = Lvalue::Local(self.new_temp(tcx.mk_nil())); let unit_temp = Lvalue::Local(self.new_temp(tcx.mk_nil()));
@ -749,31 +762,31 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
destination: Some((unit_temp, target)), destination: Some((unit_temp, target)),
cleanup: None cleanup: None
}; // FIXME(#6393) }; // FIXME(#6393)
let free_block = self.new_block(is_cleanup, call); let free_block = self.new_block(unwind, call);
let block_start = Location { block: free_block, statement_index: 0 }; let block_start = Location { block: free_block, statement_index: 0 };
self.elaborator.clear_drop_flag(block_start, self.path, DropFlagMode::Shallow); self.elaborator.clear_drop_flag(block_start, self.path, DropFlagMode::Shallow);
free_block free_block
} }
fn drop_block<'a>(&mut self, is_cleanup: bool, succ: BasicBlock) -> BasicBlock { fn drop_block<'a>(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock {
let block = TerminatorKind::Drop { let block = TerminatorKind::Drop {
location: self.lvalue.clone(), location: self.lvalue.clone(),
target: succ, target: target,
unwind: if is_cleanup { None } else { self.unwind } unwind: unwind.into_option()
}; };
self.new_block(is_cleanup, block) self.new_block(unwind, block)
} }
fn drop_flag_test_block(&mut self, fn drop_flag_test_block(&mut self,
is_cleanup: bool,
on_set: BasicBlock, on_set: BasicBlock,
on_unset: BasicBlock) on_unset: BasicBlock,
unwind: Unwind)
-> BasicBlock -> BasicBlock
{ {
let style = self.elaborator.drop_style(self.path, DropFlagMode::Shallow); let style = self.elaborator.drop_style(self.path, DropFlagMode::Shallow);
debug!("drop_flag_test_block({:?},{:?},{:?}) - {:?}", debug!("drop_flag_test_block({:?},{:?},{:?},{:?}) - {:?}",
self, is_cleanup, on_set, style); self, on_set, on_unset, unwind, style);
match style { match style {
DropStyle::Dead => on_unset, DropStyle::Dead => on_unset,
@ -781,13 +794,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
DropStyle::Conditional | DropStyle::Open => { DropStyle::Conditional | DropStyle::Open => {
let flag = self.elaborator.get_drop_flag(self.path).unwrap(); let flag = self.elaborator.get_drop_flag(self.path).unwrap();
let term = TerminatorKind::if_(self.tcx(), flag, on_set, on_unset); let term = TerminatorKind::if_(self.tcx(), flag, on_set, on_unset);
self.new_block(is_cleanup, term) self.new_block(unwind, term)
} }
} }
} }
fn new_block<'a>(&mut self, fn new_block<'a>(&mut self,
is_cleanup: bool, unwind: Unwind,
k: TerminatorKind<'tcx>) k: TerminatorKind<'tcx>)
-> BasicBlock -> BasicBlock
{ {
@ -796,7 +809,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
terminator: Some(Terminator { terminator: Some(Terminator {
source_info: self.source_info, kind: k source_info: self.source_info, kind: k
}), }),
is_cleanup: is_cleanup is_cleanup: unwind.is_cleanup()
}) })
} }
@ -809,7 +822,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
self.elaborator.patch().terminator_loc(mir, bb) self.elaborator.patch().terminator_loc(mir, bb)
} }
fn constant_usize(&self, val: usize) -> Operand<'tcx> { fn constant_usize(&self, val: u16) -> Operand<'tcx> {
Operand::Constant(box Constant { Operand::Constant(box Constant {
span: self.source_info.span, span: self.source_info.span,
ty: self.tcx().types.usize, ty: self.tcx().types.usize,