diff options
| author | bors <bors@rust-lang.org> | 2014-04-15 21:17:00 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-04-15 21:17:00 -0700 |
| commit | 74bd2338eb25d0d165458a09d7aab3d2ecb98c48 (patch) | |
| tree | b1c7fb6409a322c2b95298f3a2ad1a07307b1381 | |
| parent | b400a4d27256dba01089c56d856f6f0b84c63e2f (diff) | |
| parent | 0cc257eb42c72d26a151623825ecc6a8074c53cf (diff) | |
| download | rust-74bd2338eb25d0d165458a09d7aab3d2ecb98c48.tar.gz rust-74bd2338eb25d0d165458a09d7aab3d2ecb98c48.zip | |
auto merge of #13390 : alexcrichton/rust/run-some-destructors, r=brson
Previously, if statements of the form "Foo;" or "let _ = Foo;" were encountered where Foo had a destructor, the destructors were not run. This changes the relevant locations in trans to check for ty::type_needs_drop and invokes trans_to_lvalue instead of trans_into. Closes #4734 Closes #6892
| -rw-r--r-- | src/librustc/middle/trans/base.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/trans/controlflow.rs | 13 | ||||
| -rw-r--r-- | src/test/run-pass/issue-4734.rs | 44 | ||||
| -rw-r--r-- | src/test/run-pass/issue-6892.rs | 52 |
4 files changed, 109 insertions, 2 deletions
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 60d6e6850f7..5f063bb31ca 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 a6c86f9d564..7905436a7a3 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 00000000000..c08d3503fa4 --- /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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..891892ff9cb --- /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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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); +} |
