提交 7be2fd85 编写于 作者: M Mikhail Modin

create a drop ladder for an array if any value is moved out

上级 8bcbf91a
......@@ -61,7 +61,12 @@ fn place_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx,
place: &mir::Place<'tcx>) -> bool {
let ty = place.ty(mir, tcx).to_ty(tcx);
match ty.sty {
ty::TyArray(..) | ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
ty::TyArray(..) => {
debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
place, ty);
false
}
ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
place, ty);
true
......
......@@ -280,6 +280,9 @@ fn deref_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
fn downcast_subpath(&self, _path: Self::Path, _variant: usize) -> Option<Self::Path> {
Some(())
}
fn array_subpath(&self, _path: Self::Path, _index: u32, _size: u32) -> Option<Self::Path> {
None
}
}
/// Build a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`.
......
......@@ -257,6 +257,20 @@ fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path> {
})
}
fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option<Self::Path> {
dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
match p {
&Projection {
elem: ProjectionElem::ConstantIndex{offset, min_length: _, from_end: false}, ..
} => offset == index,
&Projection {
elem: ProjectionElem::ConstantIndex{offset, min_length: _, from_end: true}, ..
} => size - offset == index,
_ => false
}
})
}
fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
match p {
......
......@@ -19,7 +19,7 @@
use rustc_data_structures::indexed_vec::Idx;
use util::patch::MirPatch;
use std::iter;
use std::{iter, u32};
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum DropFlagState {
......@@ -95,6 +95,7 @@ pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug {
fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path>;
fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path>;
fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option<Self::Path>;
fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option<Self::Path>;
}
#[derive(Debug)]
......@@ -632,8 +633,8 @@ fn drop_loop(&mut self,
loop_block
}
fn open_drop_for_array(&mut self, ety: Ty<'tcx>) -> BasicBlock {
debug!("open_drop_for_array({:?})", ety);
fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option<u64>) -> BasicBlock {
debug!("open_drop_for_array({:?}, {:?})", ety, opt_size);
// if size_of::<ety>() == 0 {
// index_based_loop
......@@ -641,9 +642,27 @@ fn open_drop_for_array(&mut self, ety: Ty<'tcx>) -> BasicBlock {
// ptr_based_loop
// }
let tcx = self.tcx();
if let Some(size) = opt_size {
assert!(size <= (u32::MAX as u64),
"move out check doesn't implemented for array bigger then u32");
let size = size as u32;
let fields: Vec<(Place<'tcx>, Option<D::Path>)> = (0..size).map(|i| {
(self.place.clone().elem(ProjectionElem::ConstantIndex{
offset: i,
min_length: size,
from_end: false
}),
self.elaborator.array_subpath(self.path, i, size))
}).collect();
if fields.iter().any(|(_,path)| path.is_some()) {
let (succ, unwind) = self.drop_ladder_bottom();
return self.drop_ladder(fields, succ, unwind).0
}
}
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
let tcx = self.tcx();
let size = &Place::Local(self.new_temp(tcx.types.usize));
let size_is_zero = &Place::Local(self.new_temp(tcx.types.bool));
let base_block = BasicBlockData {
......@@ -779,9 +798,10 @@ fn open_drop<'a>(&mut self) -> BasicBlock {
let succ = self.succ;
self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
}
ty::TyArray(ety, _) | ty::TySlice(ety) => {
self.open_drop_for_array(ety)
}
ty::TyArray(ety, size) => self.open_drop_for_array(
ety, size.val.to_const_int().and_then(|v| v.to_u64())),
ty::TySlice(ety) => self.open_drop_for_array(ety, None),
_ => bug!("open drop from non-ADT `{:?}`", ty)
}
}
......
......@@ -10,7 +10,7 @@
// ignore-wasm32-bare compiled with panic=abort by default
#![feature(generators, generator_trait, untagged_unions)]
#![feature(generators, generator_trait, untagged_unions, slice_patterns, advanced_slice_patterns)]
use std::cell::{Cell, RefCell};
use std::ops::Generator;
......@@ -195,6 +195,33 @@ fn vec_unreachable(a: &Allocator) {
let _x = vec![a.alloc(), a.alloc(), a.alloc(), return];
}
fn slice_pattern_first(a: &Allocator) {
let[_x, ..] = [a.alloc(), a.alloc(), a.alloc()];
}
fn slice_pattern_middle(a: &Allocator) {
let[_, _x, _] = [a.alloc(), a.alloc(), a.alloc()];
}
fn slice_pattern_two(a: &Allocator) {
let[_x, _, _y, _] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
}
fn slice_pattern_last(a: &Allocator) {
let[.., _y] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
}
fn slice_pattern_one_of(a: &Allocator, i: usize) {
let array = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
let _x = match i {
0 => { let [a, ..] = array; a }
1 => { let [_, a, ..] = array; a }
2 => { let [_, _, a, _] = array; a }
3 => { let [_, _, _, a] = array; a }
_ => panic!("unmatched"),
};
}
fn run_test<F>(mut f: F)
where F: FnMut(&Allocator)
{
......@@ -264,5 +291,14 @@ fn main() {
run_test(|a| mixed_drop_and_nondrop(a));
run_test(|a| slice_pattern_first(a));
run_test(|a| slice_pattern_middle(a));
run_test(|a| slice_pattern_two(a));
run_test(|a| slice_pattern_last(a));
run_test(|a| slice_pattern_one_of(a, 0));
run_test(|a| slice_pattern_one_of(a, 1));
run_test(|a| slice_pattern_one_of(a, 2));
run_test(|a| slice_pattern_one_of(a, 3));
run_test_nopanic(|a| union1(a));
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册