diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 8974c4ec1fbfd..a625f4b04580b 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -97,13 +97,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Box { value } => { let value = this.hir.mirror(value); let result = this.temp(expr.ty, expr_span); - // to start, malloc some memory of suitable type (thus far, uninitialized): - let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty); - this.cfg.push_assign(block, source_info, &result, box_); if let Some(scope) = scope { // schedule a shallow free of that memory, lest we unwind: + this.cfg.push(block, Statement { + source_info: source_info, + kind: StatementKind::StorageLive(result.clone()) + }); this.schedule_drop(expr_span, scope, &result, value.ty); } + + // malloc some memory of suitable type (thus far, uninitialized): + let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty); + this.cfg.push_assign(block, source_info, &result, box_); + // initialize the box contents: unpack!(block = this.into(&result.clone().deref(), block, value)); block.and(Rvalue::Use(Operand::Consume(result))) diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs new file mode 100644 index 0000000000000..4015930ef7633 --- /dev/null +++ b/src/test/mir-opt/box_expr.rs @@ -0,0 +1,88 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] + +fn main() { + let x = box S::new(); + drop(x); +} + +struct S; + +impl S { + fn new() -> Self { S } +} + +impl Drop for S { + fn drop(&mut self) { + println!("splat!"); + } +} + +// END RUST SOURCE +// START rustc.node4.ElaborateDrops.before.mir +// let mut _0: (); +// let _1: std::boxed::Box; +// let mut _2: std::boxed::Box; +// let mut _3: (); +// let mut _4: std::boxed::Box; +// +// bb0: { +// StorageLive(_1); +// StorageLive(_2); +// _2 = Box(S); +// (*_2) = const S::new() -> [return: bb1, unwind: bb3]; +// } +// +// bb1: { +// _1 = _2; +// drop(_2) -> bb4; +// } +// +// bb2: { +// resume; +// } +// +// bb3: { +// drop(_2) -> bb2; +// } +// +// bb4: { +// StorageDead(_2); +// StorageLive(_4); +// _4 = _1; +// _3 = const std::mem::drop(_4) -> [return: bb5, unwind: bb7]; +// } +// +// bb5: { +// drop(_4) -> [return: bb8, unwind: bb6]; +// } +// +// bb6: { +// drop(_1) -> bb2; +// } +// +// bb7: { +// drop(_4) -> bb6; +// } +// +// bb8: { +// StorageDead(_4); +// _0 = (); +// drop(_1) -> bb9; +// } +// +// bb9: { +// StorageDead(_1); +// return; +// } +// } +// END rustc.node4.ElaborateDrops.before.mir