[mir-opt] Fix Inline pass to handle inlining into box expressions

This commit is contained in:
Wesley Wiser 2019-12-15 14:07:30 -05:00
parent ccd238309f
commit bec4fc175a
2 changed files with 91 additions and 10 deletions

View File

@ -663,9 +663,9 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> {
fn make_integrate_local(&self, local: &Local) -> Local {
if *local == RETURN_PLACE {
match self.destination.as_local() {
Some(l) => return l,
ref place => bug!("Return place is {:?}, not local", place),
match self.destination.base {
PlaceBase::Local(l) => return l,
PlaceBase::Static(ref s) => bug!("Return place is {:?}, not local", s),
}
}
@ -695,14 +695,24 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
fn visit_place(
&mut self,
place: &mut Place<'tcx>,
context: PlaceContext,
location: Location,
_context: PlaceContext,
_location: Location,
) {
if let Some(RETURN_PLACE) = place.as_local() {
// Return pointer; update the place itself
*place = self.destination.clone();
} else {
self.super_place(place, context, location);
match &mut place.base {
PlaceBase::Static(_) => {},
PlaceBase::Local(l) => {
// If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
let dest_proj_len = self.destination.projection.len();
if *l == RETURN_PLACE && dest_proj_len > 0 {
let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len());
projs.extend(self.destination.projection);
projs.extend(place.projection);
place.projection = self.tcx.intern_place_elems(&*projs);
}
*l = self.make_integrate_local(l);
}
}
}

View File

@ -0,0 +1,71 @@
// ignore-tidy-linelength
// ignore-wasm32-bare compiled with panic=abort by default
#![feature(box_syntax)]
fn main() {
let _x: Box<Vec<u32>> = box Vec::new();
}
// END RUST SOURCE
// START rustc.main.Inline.before.mir
// let mut _0: ();
// let _1: std::boxed::Box<std::vec::Vec<u32>> as UserTypeProjection { base: UserType(0), projs: [] };
// let mut _2: std::boxed::Box<std::vec::Vec<u32>>;
// let mut _3: ();
// scope 1 {
// debug _x => _1;
// }
// bb0: {
// StorageLive(_1);
// StorageLive(_2);
// _2 = Box(std::vec::Vec<u32>);
// (*_2) = const std::vec::Vec::<u32>::new() -> [return: bb2, unwind: bb4];
// }
// bb1 (cleanup): {
// resume;
// }
// bb2: {
// _1 = move _2;
// StorageDead(_2);
// _0 = ();
// drop(_1) -> [return: bb3, unwind: bb1];
// }
// bb3: {
// StorageDead(_1);
// return;
// }
// bb4 (cleanup): {
// _3 = const alloc::alloc::box_free::<std::vec::Vec<u32>>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>)) -> bb1;
// }
// END rustc.main.Inline.before.mir
// START rustc.main.Inline.after.mir
// let mut _0: ();
// let _1: std::boxed::Box<std::vec::Vec<u32>> as UserTypeProjection { base: UserType(0), projs: [] };
// let mut _2: std::boxed::Box<std::vec::Vec<u32>>;
// let mut _3: ();
// let mut _4: &mut std::vec::Vec<u32>;
// scope 1 {
// debug _x => _1;
// }
// scope 2 {
// }
// bb0: {
// StorageLive(_1);
// StorageLive(_2);
// _2 = Box(std::vec::Vec<u32>);
// _4 = &mut (*_2);
// ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32>::NEW;
// ((*_4).1: usize) = const 0usize;
// _1 = move _2;
// StorageDead(_2);
// _0 = ();
// drop(_1) -> [return: bb2, unwind: bb1];
// }
// bb1 (cleanup): {
// resume;
// }
// bb2: {
// StorageDead(_1);
// return;
// }
// END rustc.main.Inline.after.mir