about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-04-15 21:17:00 -0700
committerbors <bors@rust-lang.org>2014-04-15 21:17:00 -0700
commit74bd2338eb25d0d165458a09d7aab3d2ecb98c48 (patch)
treeb1c7fb6409a322c2b95298f3a2ad1a07307b1381
parentb400a4d27256dba01089c56d856f6f0b84c63e2f (diff)
parent0cc257eb42c72d26a151623825ecc6a8074c53cf (diff)
downloadrust-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.rs2
-rw-r--r--src/librustc/middle/trans/controlflow.rs13
-rw-r--r--src/test/run-pass/issue-4734.rs44
-rw-r--r--src/test/run-pass/issue-6892.rs52
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);
+}