Skip to content

Commit 2decde6

Browse files
committed
add subslice support in drop ladder for array
1 parent 3ece2d9 commit 2decde6

File tree

4 files changed

+211
-87
lines changed

4 files changed

+211
-87
lines changed

src/librustc_mir/shim.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,15 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
264264
}
265265
}
266266

267-
fn get_drop_flag(&mut self, _path: Self::Path) -> Option<Operand<'tcx>> {
267+
fn get_drop_flags(&mut self, _path: Self::Path) -> Option<Operand<'tcx>> {
268268
None
269269
}
270270

271-
fn clear_drop_flag(&mut self, _location: Location, _path: Self::Path, _mode: DropFlagMode) {
271+
fn clear_drop_flag(&mut self,
272+
_location: Location,
273+
_path: Self::Path,
274+
_mode: DropFlagMode,
275+
_opt_flag: Option<Local>) {
272276
}
273277

274278
fn field_subpath(&self, _path: Self::Path, _field: Field) -> Option<Self::Path> {
@@ -280,8 +284,9 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
280284
fn downcast_subpath(&self, _path: Self::Path, _variant: usize) -> Option<Self::Path> {
281285
Some(())
282286
}
283-
fn array_subpath(&self, _path: Self::Path, _index: u32, _size: u32) -> Option<Self::Path> {
284-
None
287+
fn array_subpaths(&self, _path: Self::Path, _size: u64)
288+
-> Vec<(Place<'tcx>, Option<Self::Path>, Option<Local>)> {
289+
vec![]
285290
}
286291
}
287292

src/librustc_mir/transform/elaborate_drops.rs

+115-25
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
2929
use syntax::ast;
3030
use syntax_pos::Span;
3131

32-
use std::fmt;
32+
use std::{fmt, u32};
3333

3434
pub struct ElaborateDrops;
3535

@@ -74,6 +74,7 @@ impl MirPass for ElaborateDrops {
7474
flow_inits,
7575
flow_uninits,
7676
drop_flags: FxHashMap(),
77+
array_items_drop_flags: FxHashMap(),
7778
patch: MirPatch::new(mir),
7879
}.elaborate()
7980
};
@@ -224,6 +225,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
224225
((some_live, some_dead), children_count != 1)
225226
}
226227
};
228+
227229
match (maybe_live, maybe_dead, multipart) {
228230
(false, _, _) => DropStyle::Dead,
229231
(true, false, _) => DropStyle::Static,
@@ -232,7 +234,16 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
232234
}
233235
}
234236

235-
fn clear_drop_flag(&mut self, loc: Location, path: Self::Path, mode: DropFlagMode) {
237+
fn clear_drop_flag(
238+
&mut self,
239+
loc: Location,
240+
path: Self::Path,
241+
mode: DropFlagMode,
242+
opt_flag: Option<Local>) {
243+
if let Some(flag) = opt_flag {
244+
self.ctxt.set_drop_flag_impl(loc, flag, DropFlagState::Absent);
245+
return;
246+
}
236247
match mode {
237248
DropFlagMode::Shallow => {
238249
self.ctxt.set_drop_flag(loc, path, DropFlagState::Absent);
@@ -257,18 +268,37 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
257268
})
258269
}
259270

260-
fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option<Self::Path> {
261-
dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
262-
match p {
263-
&Projection {
264-
elem: ProjectionElem::ConstantIndex{offset, min_length: _, from_end: false}, ..
265-
} => offset == index,
266-
&Projection {
267-
elem: ProjectionElem::ConstantIndex{offset, min_length: _, from_end: true}, ..
268-
} => size - offset == index,
269-
_ => false
270-
}
271-
})
271+
fn array_subpaths(&self, path: Self::Path, size: u64)
272+
-> Vec<(Place<'tcx>, Option<Self::Path>, Option<Local>)> {
273+
if dataflow::move_path_children_matching(self.ctxt.move_data(), path, |_| {
274+
assert!(size <= (u32::MAX as u64),
275+
"move out check doesn't implemented for array bigger then u32");
276+
true
277+
}).is_none() {
278+
return vec![];
279+
}
280+
281+
let size = size as u32;
282+
let flags = self.ctxt.array_items_drop_flags.get(&path);
283+
(0..size).map(|i| {
284+
let place = &self.ctxt.move_data().move_paths[path].place;
285+
(place.clone().elem(ProjectionElem::ConstantIndex{
286+
offset: i,
287+
min_length: size,
288+
from_end: false
289+
}),
290+
dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p|
291+
match p.elem {
292+
ProjectionElem::ConstantIndex{offset, min_length: _, from_end: false} =>
293+
offset == i,
294+
ProjectionElem::ConstantIndex{offset, min_length: _, from_end: true} =>
295+
size - offset == i,
296+
ProjectionElem::Subslice{from, to} => from <= i && i < size - to,
297+
_ => false
298+
}
299+
),
300+
flags.map(|f| f[i as usize]))
301+
}).collect()
272302
}
273303

274304
fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
@@ -291,18 +321,28 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
291321
})
292322
}
293323

294-
fn get_drop_flag(&mut self, path: Self::Path) -> Option<Operand<'tcx>> {
295-
self.ctxt.drop_flag(path).map(Operand::Copy)
324+
fn get_drop_flags(&mut self, path: Self::Path) -> Option<Operand<'tcx>> {
325+
self.ctxt.drop_flag(path).map(|f| match f{
326+
DropFlag::Single(l) => Operand::Copy(Place::Local(*l)),
327+
DropFlag::Subslice(_) =>
328+
panic!("get_drop_flags shouldn't be calles for sublice move path")
329+
})
296330
}
297331
}
298332

333+
enum DropFlag {
334+
Single(Local),
335+
Subslice(Vec<Local>),
336+
}
337+
299338
struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
300339
tcx: TyCtxt<'a, 'tcx, 'tcx>,
301340
mir: &'a Mir<'tcx>,
302341
env: &'a MoveDataParamEnv<'tcx, 'tcx>,
303342
flow_inits: DataflowResults<MaybeInitializedLvals<'a, 'tcx, 'tcx>>,
304343
flow_uninits: DataflowResults<MaybeUninitializedLvals<'a, 'tcx, 'tcx>>,
305-
drop_flags: FxHashMap<MovePathIndex, Local>,
344+
drop_flags: FxHashMap<MovePathIndex, DropFlag>,
345+
array_items_drop_flags: FxHashMap<MovePathIndex, Vec<Local>>,
306346
patch: MirPatch<'tcx>,
307347
}
308348

@@ -329,15 +369,48 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
329369

330370
fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) {
331371
let tcx = self.tcx;
372+
if let Place::Projection(
373+
box Projection{ref base, elem: ProjectionElem::Subslice{from, to}}) =
374+
self.move_data().move_paths[index].place {
375+
let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
376+
if let ty::TyArray(_, n) = base_ty.sty {
377+
let flags = {
378+
let n = n.val.to_const_int().and_then(|v| v.to_u64())
379+
.expect("expected u64 size") as usize;
380+
let span = self.mir.span;
381+
let parent_index = self.move_data().move_paths[index].parent
382+
.expect("subslice has parent");
383+
let patch = &mut self.patch;
384+
let array_flags = self.array_items_drop_flags.entry(parent_index)
385+
.or_insert_with(|| {
386+
let flags = (0..n).map(|_| patch.new_internal(tcx.types.bool, span))
387+
.collect();
388+
debug!("create_drop_flags for array with subslice({:?}, {:?}, {:?})",
389+
parent_index, span, flags);
390+
flags
391+
});
392+
let from = from as usize;
393+
let to = to as usize;
394+
array_flags[from .. n-to].iter().map(|x| *x).collect()
395+
};
396+
397+
let span = self.mir.span;
398+
self.drop_flags.entry(index).or_insert_with(|| {
399+
debug!("create_drop_flags for subslice({:?}, {:?}, {:?})", index, span, flags);
400+
DropFlag::Subslice(flags)
401+
});
402+
return;
403+
}
404+
}
332405
let patch = &mut self.patch;
333406
debug!("create_drop_flag({:?})", self.mir.span);
334407
self.drop_flags.entry(index).or_insert_with(|| {
335-
patch.new_internal(tcx.types.bool, span)
408+
DropFlag::Single(patch.new_internal(tcx.types.bool, span))
336409
});
337410
}
338411

339-
fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
340-
self.drop_flags.get(&index).map(|t| Place::Local(*t))
412+
fn drop_flag(&mut self, index: MovePathIndex) -> Option<&DropFlag> {
413+
self.drop_flags.get(&index)
341414
}
342415

343416
/// create a patch that elaborates all drops in the input
@@ -389,6 +462,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
389462
}
390463
};
391464

465+
392466
on_all_drop_children_bits(self.tcx, self.mir, self.env, path, |child| {
393467
let (maybe_live, maybe_dead) = init_data.state(child);
394468
debug!("collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}",
@@ -548,11 +622,20 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
548622
})))
549623
}
550624

625+
fn set_drop_flag_impl(&mut self, loc: Location, flag: Local, val: DropFlagState) {
626+
let span = self.patch.source_info_for_location(self.mir, loc).span;
627+
let val = self.constant_bool(span, val.value());
628+
self.patch.add_assign(loc, Place::Local(flag), val);
629+
}
630+
551631
fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagState) {
552-
if let Some(&flag) = self.drop_flags.get(&path) {
553-
let span = self.patch.source_info_for_location(self.mir, loc).span;
554-
let val = self.constant_bool(span, val.value());
555-
self.patch.add_assign(loc, Place::Local(flag), val);
632+
match self.drop_flags.get(&path) {
633+
Some(DropFlag::Single(flag)) => self.set_drop_flag_impl(loc, *flag, val),
634+
Some(DropFlag::Subslice(flags)) =>
635+
for flag in flags {
636+
self.set_drop_flag_impl(loc, *flag, val);
637+
}
638+
_ => {}
556639
}
557640
}
558641

@@ -561,7 +644,14 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
561644
let span = self.patch.source_info_for_location(self.mir, loc).span;
562645
let false_ = self.constant_bool(span, false);
563646
for flag in self.drop_flags.values() {
564-
self.patch.add_assign(loc, Place::Local(*flag), false_.clone());
647+
match flag {
648+
DropFlag::Single(flag) =>
649+
self.patch.add_assign(loc, Place::Local(*flag), false_.clone()),
650+
DropFlag::Subslice(flags) =>
651+
for flag in flags {
652+
self.patch.add_assign(loc, Place::Local(*flag), false_.clone());
653+
},
654+
}
565655
}
566656
}
567657

0 commit comments

Comments
 (0)