]> git.lizzy.rs Git - rust.git/commitdiff
Allow ~fn:Copy() to be copied.
authorBen Blum <bblum@andrew.cmu.edu>
Fri, 14 Jun 2013 00:57:23 +0000 (20:57 -0400)
committerBen Blum <bblum@andrew.cmu.edu>
Sun, 23 Jun 2013 21:54:21 +0000 (17:54 -0400)
src/librustc/middle/ty.rs
src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs [new file with mode: 0644]
src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs [new file with mode: 0644]

index b76f30a704108ab511e94b137c2be2ec555de60e..90cd8a8665ea7cb7fb6b5c068ee842d8c99a92a6 100644 (file)
@@ -1856,7 +1856,7 @@ pub fn is_copy(&self, cx: ctxt) -> bool {
     }
 
     pub fn noncopyable(_cx: ctxt) -> TypeContents {
-        TC_DTOR + TC_BORROWED_MUT + TC_ONCE_CLOSURE + TC_OWNED_CLOSURE +
+        TC_DTOR + TC_BORROWED_MUT + TC_ONCE_CLOSURE + TC_NONCOPY_TRAIT +
             TC_EMPTY_ENUM
     }
 
@@ -1905,13 +1905,19 @@ pub fn nonimplicitly_copyable(cx: ctxt) -> TypeContents {
     }
 
     pub fn needs_drop(&self, cx: ctxt) -> bool {
+        if self.intersects(TC_NONCOPY_TRAIT) {
+            // Currently all noncopyable existentials are 2nd-class types
+            // behind owned pointers. With dynamically-sized types, remove
+            // this assertion.
+            assert!(self.intersects(TC_OWNED_POINTER));
+        }
         let tc = TC_MANAGED + TC_DTOR + TypeContents::owned(cx);
         self.intersects(tc)
     }
 
     pub fn owned(_cx: ctxt) -> TypeContents {
         //! Any kind of owned contents.
-        TC_OWNED_CLOSURE + TC_OWNED_POINTER + TC_OWNED_VEC
+        TC_OWNED_POINTER + TC_OWNED_VEC
     }
 }
 
@@ -1945,8 +1951,8 @@ fn to_str(&self) -> ~str {
 /// Contains an owned vector ~[] or owned string ~str
 static TC_OWNED_VEC: TypeContents =        TypeContents{bits: 0b0000_0000_0100};
 
-/// Contains a ~fn() or a ~Trait, which is non-copyable.
-static TC_OWNED_CLOSURE: TypeContents =    TypeContents{bits: 0b0000_0000_1000};
+/// Contains a non-copyable ~fn() or a ~Trait (NOT a ~fn:Copy() or ~Trait:Copy).
+static TC_NONCOPY_TRAIT: TypeContents =    TypeContents{bits: 0b0000_0000_1000};
 
 /// Type with a destructor
 static TC_DTOR: TypeContents =             TypeContents{bits: 0b0000_0001_0000};
@@ -2061,7 +2067,8 @@ fn tc_ty(cx: ctxt,
             }
 
             ty_trait(_, _, UniqTraitStore, _, _bounds) => {
-                TC_OWNED_CLOSURE
+                // FIXME(#3569): Make this conditional on the trait's bounds.
+                TC_NONCOPY_TRAIT + TC_OWNED_POINTER
             }
 
             ty_trait(_, _, BoxTraitStore, mutbl, _bounds) => {
@@ -2184,7 +2191,9 @@ fn tc_ty(cx: ctxt,
                 match sigil {
                     ast::BorrowedSigil => TC_BORROWED_POINTER,
                     ast::ManagedSigil => TC_MANAGED,
-                    ast::OwnedSigil => TC_OWNED_CLOSURE
+                    // FIXME(#3569): Looks like noncopyability should depend
+                    // on the bounds, but I don't think this case ever comes up.
+                    ast::OwnedSigil => TC_NONCOPY_TRAIT + TC_OWNED_POINTER,
                 }
             }
 
@@ -2258,7 +2267,11 @@ fn closure_contents(cty: &ClosureTy) -> TypeContents {
         let st = match cty.sigil {
             ast::BorrowedSigil => TC_BORROWED_POINTER,
             ast::ManagedSigil => TC_MANAGED,
-            ast::OwnedSigil => TC_OWNED_CLOSURE
+            ast::OwnedSigil => if cty.bounds.contains_elem(BoundCopy) {
+                TC_OWNED_POINTER
+            } else {
+                TC_OWNED_POINTER + TC_NONCOPY_TRAIT
+            }
         };
         let rt = borrowed_contents(cty.region, m_imm);
         let ot = match cty.onceness {
diff --git a/src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs b/src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs
new file mode 100644 (file)
index 0000000..f39c914
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2013 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.
+
+// xfail-pretty
+
+// Tests correct copying of heap closures' environments.
+
+fn foo(x: ~fn:Copy()) -> (~fn(), ~fn()) {
+    (copy x, x)
+}
+fn main() {
+    let v = ~[~[1,2,3],~[4,5,6]]; // shouldn't get double-freed
+    let (f1,f2) = do foo {
+        assert!(v.len() == 2);
+    };
+    f1();
+    f2();
+}
diff --git a/src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs b/src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs
new file mode 100644 (file)
index 0000000..2fdce4e
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2013 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.
+
+// xfail-pretty
+
+// Tests correct copying of heap closures' environments.
+
+fn bar<T: Copy>(x: T) -> (T, T) {
+    (copy x, x)
+}
+fn foo(x: ~fn:Copy()) -> (~fn(), ~fn()) {
+    bar(x)
+}
+fn main() {
+    let v = ~[~[1,2,3],~[4,5,6]]; // shouldn't get double-freed
+    let (f1,f2) = do foo {
+        assert!(v.len() == 2);
+    };
+    f1();
+    f2();
+}