about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWesley Wiser <wwiser@gmail.com>2019-07-03 08:25:27 -0400
committerWesley Wiser <wwiser@gmail.com>2019-07-11 20:12:19 -0400
commitaabaf121550dd3743f12ff30bab625d6f2d6f89c (patch)
tree28f92d3d1040d47957823a57cbc641bc84fd58cd
parent78ca1bda3522b14bc0336bc01dd1d49fdba2cda7 (diff)
downloadrust-aabaf121550dd3743f12ff30bab625d6f2d6f89c.tar.gz
rust-aabaf121550dd3743f12ff30bab625d6f2d6f89c.zip
Fix leak when early returning out of `box` syntax
Fixes #62289
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs2
-rw-r--r--src/test/mir-opt/issue-62289.rs91
2 files changed, 92 insertions, 1 deletions
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 17e7b1acc68..56c518a6d57 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -128,7 +128,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         expr_span,
                         scope,
                         result,
-                        value.ty,
+                        expr.ty,
                     );
                 }
 
diff --git a/src/test/mir-opt/issue-62289.rs b/src/test/mir-opt/issue-62289.rs
new file mode 100644
index 00000000000..a3b517e9bca
--- /dev/null
+++ b/src/test/mir-opt/issue-62289.rs
@@ -0,0 +1,91 @@
+// check that we don't forget to drop the Box if we early return before
+// initializing it
+// ignore-tidy-linelength
+// ignore-wasm32-bare compiled with panic=abort by default
+
+#![feature(box_syntax)]
+
+fn test() -> Option<Box<u32>> {
+    Some(box (None?))
+}
+
+fn main() {
+    test();
+}
+
+// END RUST SOURCE
+// START rustc.test.ElaborateDrops.before.mir
+// fn test() -> std::option::Option<std::boxed::Box<u32>> {
+//     ...
+//     bb0: {
+//         StorageLive(_1);
+//         StorageLive(_2);
+//         _2 = Box(u32);
+//         StorageLive(_3);
+//         StorageLive(_4);
+//         _4 = std::option::Option::<u32>::None;
+//         _3 = const <std::option::Option<u32> as std::ops::Try>::into_result(move _4) -> [return: bb2, unwind: bb3];
+//     }
+//     bb1 (cleanup): {
+//         resume;
+//     }
+//     bb2: {
+//         StorageDead(_4);
+//         _5 = discriminant(_3);
+//         switchInt(move _5) -> [0isize: bb10, 1isize: bb5, otherwise: bb4];
+//     }
+//     bb3 (cleanup): {
+//         drop(_2) -> bb1;
+//     }
+//     bb4: {
+//         unreachable;
+//     }
+//     bb5: {
+//         StorageLive(_6);
+//         _6 = ((_3 as Err).0: std::option::NoneError);
+//         StorageLive(_8);
+//         StorageLive(_9);
+//         _9 = _6;
+//         _8 = const <std::option::NoneError as std::convert::From<std::option::NoneError>>::from(move _9) -> [return: bb7, unwind: bb3];
+//     }
+//     bb6: {
+//         return;
+//     }
+//     bb7: {
+//         StorageDead(_9);
+//         _0 = const <std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error(move _8) -> [return: bb8, unwind: bb3];
+//     }
+//     bb8: {
+//         StorageDead(_8);
+//         StorageDead(_6);
+//         drop(_2) -> bb9;
+//     }
+//     bb9: {
+//         StorageDead(_2);
+//         StorageDead(_1);
+//         StorageDead(_3);
+//         goto -> bb6;
+//     }
+//     bb10: {
+//         StorageLive(_10);
+//         _10 = ((_3 as Ok).0: u32);
+//         (*_2) = _10;
+//         StorageDead(_10);
+//         _1 = move _2;
+//         drop(_2) -> [return: bb12, unwind: bb11];
+//     }
+//     bb11 (cleanup): {
+//         drop(_1) -> bb1;
+//     }
+//     bb12: {
+//         StorageDead(_2);
+//         _0 = std::option::Option::<std::boxed::Box<u32>>::Some(move _1,);
+//         drop(_1) -> bb13;
+//     }
+//     bb13: {
+//         StorageDead(_1);
+//         StorageDead(_3);
+//         goto -> bb6;
+//     }
+// }
+// END rustc.test.ElaborateDrops.before.mir