about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-12-21 19:07:36 +0100
committerGitHub <noreply@github.com>2019-12-21 19:07:36 +0100
commitac6dbff45e7bce90b70533d322f06de9730c2781 (patch)
tree7a06bdad125cc49139578ed7e5a59e57f3a8b73f
parentb50c3b7ddfd4e6f6b3aa2f99522637138320dab0 (diff)
parentf1325a78e6567d86d4c83d21477097b8ee3f7526 (diff)
downloadrust-ac6dbff45e7bce90b70533d322f06de9730c2781.tar.gz
rust-ac6dbff45e7bce90b70533d322f06de9730c2781.zip
Rollup merge of #67333 - wesleywiser:fix_inline_into_box_place, r=oli-obk
[mir-opt] Fix `Inline` pass to handle inlining into `box` expressions

r? @oli-obk

Before, the test case just ICE'd here:

https://github.com/rust-lang/rust/blob/a605441e049f0b6d5f7715b94b8ac4662fd7fcf6/src/librustc_mir/transform/inline.rs#L668
-rw-r--r--src/librustc_mir/transform/inline.rs30
-rw-r--r--src/test/mir-opt/inline/inline-any-operand.rs (renamed from src/test/mir-opt/inline-any-operand.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-closure-borrows-arg.rs (renamed from src/test/mir-opt/inline-closure-borrows-arg.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-closure-captures.rs (renamed from src/test/mir-opt/inline-closure-captures.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-closure.rs (renamed from src/test/mir-opt/inline-closure.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-into-box-place.rs71
-rw-r--r--src/test/mir-opt/inline/inline-retag.rs (renamed from src/test/mir-opt/inline-retag.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-trait-method.rs (renamed from src/test/mir-opt/inline-trait-method.rs)0
-rw-r--r--src/test/mir-opt/inline/inline-trait-method_2.rs (renamed from src/test/mir-opt/inline-trait-method_2.rs)0
9 files changed, 91 insertions, 10 deletions
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 9763913082d..dca14227946 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -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);
+            }
         }
     }
 
diff --git a/src/test/mir-opt/inline-any-operand.rs b/src/test/mir-opt/inline/inline-any-operand.rs
index b5455003719..b5455003719 100644
--- a/src/test/mir-opt/inline-any-operand.rs
+++ b/src/test/mir-opt/inline/inline-any-operand.rs
diff --git a/src/test/mir-opt/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline/inline-closure-borrows-arg.rs
index 768f4953228..768f4953228 100644
--- a/src/test/mir-opt/inline-closure-borrows-arg.rs
+++ b/src/test/mir-opt/inline/inline-closure-borrows-arg.rs
diff --git a/src/test/mir-opt/inline-closure-captures.rs b/src/test/mir-opt/inline/inline-closure-captures.rs
index e000a418d90..e000a418d90 100644
--- a/src/test/mir-opt/inline-closure-captures.rs
+++ b/src/test/mir-opt/inline/inline-closure-captures.rs
diff --git a/src/test/mir-opt/inline-closure.rs b/src/test/mir-opt/inline/inline-closure.rs
index bd36e77818e..bd36e77818e 100644
--- a/src/test/mir-opt/inline-closure.rs
+++ b/src/test/mir-opt/inline/inline-closure.rs
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
index 00000000000..0bb9dfa403d
--- /dev/null
+++ b/src/test/mir-opt/inline/inline-into-box-place.rs
@@ -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
diff --git a/src/test/mir-opt/inline-retag.rs b/src/test/mir-opt/inline/inline-retag.rs
index 6cdbcfdb0ad..6cdbcfdb0ad 100644
--- a/src/test/mir-opt/inline-retag.rs
+++ b/src/test/mir-opt/inline/inline-retag.rs
diff --git a/src/test/mir-opt/inline-trait-method.rs b/src/test/mir-opt/inline/inline-trait-method.rs
index a2c5fb920cd..a2c5fb920cd 100644
--- a/src/test/mir-opt/inline-trait-method.rs
+++ b/src/test/mir-opt/inline/inline-trait-method.rs
diff --git a/src/test/mir-opt/inline-trait-method_2.rs b/src/test/mir-opt/inline/inline-trait-method_2.rs
index 4ad4311113a..4ad4311113a 100644
--- a/src/test/mir-opt/inline-trait-method_2.rs
+++ b/src/test/mir-opt/inline/inline-trait-method_2.rs