]> git.lizzy.rs Git - rust.git/commitdiff
[mir-opt] Fix `Inline` pass to handle inlining into `box` expressions
authorWesley Wiser <wwiser@gmail.com>
Sun, 15 Dec 2019 19:07:30 +0000 (14:07 -0500)
committerWesley Wiser <wwiser@gmail.com>
Sat, 21 Dec 2019 01:39:47 +0000 (20:39 -0500)
src/librustc_mir/transform/inline.rs
src/test/mir-opt/inline/inline-into-box-place.rs [new file with mode: 0644]

index 9763913082ddc7e09c0c525212e6a2819f338313..dca142279463c74f6500ea4663a06bb7bc01f43b 100644 (file)
@@ -663,9 +663,9 @@ fn update_target(&self, tgt: BasicBlock) -> BasicBlock {
 
     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 @@ fn visit_local(
     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);
+            }
         }
     }
 
diff --git a/src/test/mir-opt/inline/inline-into-box-place.rs b/src/test/mir-opt/inline/inline-into-box-place.rs
new file mode 100644 (file)
index 0000000..0bb9dfa
--- /dev/null
@@ -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