diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index e48b8fc9db4cd..dda5f295a99ae 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -936,7 +936,7 @@ pub fn init_local<'a>(bcx: &'a Block<'a>, local: &ast::Local) // Handle let _ = e; just like e; match local.init { Some(init) => { - return expr::trans_into(bcx, init, expr::Ignore); + return controlflow::trans_stmt_semi(bcx, init) } None => { return bcx; } } diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index a6c86f9d56435..7905436a7a3ad 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -19,6 +19,7 @@ use middle::trans::debuginfo; use middle::trans::cleanup; use middle::trans::cleanup::CleanupMethods; use middle::trans::expr; +use middle::ty; use util::ppaux::Repr; use middle::trans::type_::Type; @@ -49,7 +50,7 @@ pub fn trans_stmt<'a>(cx: &'a Block<'a>, match s.node { ast::StmtExpr(e, _) | ast::StmtSemi(e, _) => { - bcx = expr::trans_into(cx, e, expr::Ignore); + bcx = trans_stmt_semi(bcx, e); } ast::StmtDecl(d, _) => { match d.node { @@ -71,6 +72,16 @@ pub fn trans_stmt<'a>(cx: &'a Block<'a>, return bcx; } +pub fn trans_stmt_semi<'a>(cx: &'a Block<'a>, e: &ast::Expr) -> &'a Block<'a> { + let _icx = push_ctxt("trans_stmt_semi"); + let ty = expr_ty(cx, e); + if ty::type_needs_drop(cx.tcx(), ty) { + expr::trans_to_lvalue(cx, e, "stmt").bcx + } else { + expr::trans_into(cx, e, expr::Ignore) + } +} + pub fn trans_block<'a>(bcx: &'a Block<'a>, b: &ast::Block, mut dest: expr::Dest) diff --git a/src/test/run-pass/issue-4734.rs b/src/test/run-pass/issue-4734.rs new file mode 100644 index 0000000000000..c08d3503fa4c1 --- /dev/null +++ b/src/test/run-pass/issue-4734.rs @@ -0,0 +1,44 @@ +// Copyright 2012-2014 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. + +// Ensures that destructors are run for expressions of the form "e;" where +// `e` is a type which requires a destructor. + +#![allow(path_statement)] + +struct A { n: int } +struct B; + +static mut NUM_DROPS: uint = 0; + +impl Drop for A { + fn drop(&mut self) { + unsafe { NUM_DROPS += 1; } + } +} + +impl Drop for B { + fn drop(&mut self) { + unsafe { NUM_DROPS += 1; } + } +} + +fn main() { + assert_eq!(unsafe { NUM_DROPS }, 0); + { let _a = A { n: 1 }; } + assert_eq!(unsafe { NUM_DROPS }, 1); + { A { n: 3 }; } + assert_eq!(unsafe { NUM_DROPS }, 2); + + { let _b = B; } + assert_eq!(unsafe { NUM_DROPS }, 3); + { B; } + assert_eq!(unsafe { NUM_DROPS }, 4); +} diff --git a/src/test/run-pass/issue-6892.rs b/src/test/run-pass/issue-6892.rs new file mode 100644 index 0000000000000..891892ff9cbff --- /dev/null +++ b/src/test/run-pass/issue-6892.rs @@ -0,0 +1,52 @@ +// Copyright 2012-2014 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. + +// Ensures that destructors are run for expressions of the form "let _ = e;" +// where `e` is a type which requires a destructor. + +struct Foo; +struct Bar { x: int } +struct Baz(int); + +static mut NUM_DROPS: uint = 0; + +impl Drop for Foo { + fn drop(&mut self) { + unsafe { NUM_DROPS += 1; } + } +} +impl Drop for Bar { + fn drop(&mut self) { + unsafe { NUM_DROPS += 1; } + } +} +impl Drop for Baz { + fn drop(&mut self) { + unsafe { NUM_DROPS += 1; } + } +} + +fn main() { + assert_eq!(unsafe { NUM_DROPS }, 0); + { let _x = Foo; } + assert_eq!(unsafe { NUM_DROPS }, 1); + { let _x = Bar { x: 21 }; } + assert_eq!(unsafe { NUM_DROPS }, 2); + { let _x = Baz(21); } + assert_eq!(unsafe { NUM_DROPS }, 3); + + assert_eq!(unsafe { NUM_DROPS }, 3); + { let _ = Foo; } + assert_eq!(unsafe { NUM_DROPS }, 4); + { let _ = Bar { x: 21 }; } + assert_eq!(unsafe { NUM_DROPS }, 5); + { let _ = Baz(21); } + assert_eq!(unsafe { NUM_DROPS }, 6); +}