}
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
}
}
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
}
}
/// 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};
}
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) => {
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,
}
}
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 {
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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();
+}