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
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`.
})
}
+ 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 {
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 {
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)]
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
// 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 {
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)
}
}
// 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;
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)
{
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));
}