Auto merge of #46334 - mikhail-m1:slice_pattern_array_drop, r=arielb1
create a drop ladder for an array if any value is moved out r? @arielb1 first commit for fix https://github.com/rust-lang/rust/issues/34708 (note: this still handles the subslice case in a very broken manner)
This commit is contained in:
commit
0d11e51993
5 changed files with 87 additions and 9 deletions
|
@ -61,7 +61,12 @@ fn place_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx,
|
||||||
place: &mir::Place<'tcx>) -> bool {
|
place: &mir::Place<'tcx>) -> bool {
|
||||||
let ty = place.ty(mir, tcx).to_ty(tcx);
|
let ty = place.ty(mir, tcx).to_ty(tcx);
|
||||||
match ty.sty {
|
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",
|
debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
|
||||||
place, ty);
|
place, ty);
|
||||||
true
|
true
|
||||||
|
|
|
@ -280,6 +280,9 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
|
||||||
fn downcast_subpath(&self, _path: Self::Path, _variant: usize) -> Option<Self::Path> {
|
fn downcast_subpath(&self, _path: Self::Path, _variant: usize) -> Option<Self::Path> {
|
||||||
Some(())
|
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`.
|
/// Build a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`.
|
||||||
|
|
|
@ -257,6 +257,20 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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> {
|
fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
|
||||||
dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
|
dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
|
||||||
match p {
|
match p {
|
||||||
|
|
|
@ -19,7 +19,7 @@ use rustc::ty::util::IntTypeExt;
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
use util::patch::MirPatch;
|
use util::patch::MirPatch;
|
||||||
|
|
||||||
use std::iter;
|
use std::{iter, u32};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
pub enum DropFlagState {
|
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 field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path>;
|
||||||
fn deref_subpath(&self, path: Self::Path) -> 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 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)]
|
#[derive(Debug)]
|
||||||
|
@ -632,8 +633,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
loop_block
|
loop_block
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_drop_for_array(&mut self, ety: Ty<'tcx>) -> BasicBlock {
|
fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option<u64>) -> BasicBlock {
|
||||||
debug!("open_drop_for_array({:?})", ety);
|
debug!("open_drop_for_array({:?}, {:?})", ety, opt_size);
|
||||||
|
|
||||||
// if size_of::<ety>() == 0 {
|
// if size_of::<ety>() == 0 {
|
||||||
// index_based_loop
|
// index_based_loop
|
||||||
|
@ -641,9 +642,27 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
// ptr_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 move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
|
||||||
|
let tcx = self.tcx();
|
||||||
let size = &Place::Local(self.new_temp(tcx.types.usize));
|
let size = &Place::Local(self.new_temp(tcx.types.usize));
|
||||||
let size_is_zero = &Place::Local(self.new_temp(tcx.types.bool));
|
let size_is_zero = &Place::Local(self.new_temp(tcx.types.bool));
|
||||||
let base_block = BasicBlockData {
|
let base_block = BasicBlockData {
|
||||||
|
@ -779,9 +798,10 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
let succ = self.succ;
|
let succ = self.succ;
|
||||||
self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
|
self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
|
||||||
}
|
}
|
||||||
ty::TyArray(ety, _) | ty::TySlice(ety) => {
|
ty::TyArray(ety, size) => self.open_drop_for_array(
|
||||||
self.open_drop_for_array(ety)
|
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)
|
_ => bug!("open drop from non-ADT `{:?}`", ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
// ignore-wasm32-bare compiled with panic=abort by default
|
// 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::cell::{Cell, RefCell};
|
||||||
use std::ops::Generator;
|
use std::ops::Generator;
|
||||||
|
@ -195,6 +195,33 @@ fn vec_unreachable(a: &Allocator) {
|
||||||
let _x = vec![a.alloc(), a.alloc(), a.alloc(), return];
|
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)
|
fn run_test<F>(mut f: F)
|
||||||
where F: FnMut(&Allocator)
|
where F: FnMut(&Allocator)
|
||||||
{
|
{
|
||||||
|
@ -264,5 +291,14 @@ fn main() {
|
||||||
|
|
||||||
run_test(|a| mixed_drop_and_nondrop(a));
|
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));
|
run_test_nopanic(|a| union1(a));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue