Skip to content

Commit 1ffcc6f

Browse files
committed
Allow ~fn:Copy() to be copied.
1 parent c454e95 commit 1ffcc6f

File tree

3 files changed

+73
-7
lines changed

3 files changed

+73
-7
lines changed

src/librustc/middle/ty.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -1856,7 +1856,7 @@ impl TypeContents {
18561856
}
18571857

18581858
pub fn noncopyable(_cx: ctxt) -> TypeContents {
1859-
TC_DTOR + TC_BORROWED_MUT + TC_ONCE_CLOSURE + TC_OWNED_CLOSURE +
1859+
TC_DTOR + TC_BORROWED_MUT + TC_ONCE_CLOSURE + TC_NONCOPY_TRAIT +
18601860
TC_EMPTY_ENUM
18611861
}
18621862

@@ -1905,13 +1905,19 @@ impl TypeContents {
19051905
}
19061906

19071907
pub fn needs_drop(&self, cx: ctxt) -> bool {
1908+
if self.intersects(TC_NONCOPY_TRAIT) {
1909+
// Currently all noncopyable existentials are 2nd-class types
1910+
// behind owned pointers. With dynamically-sized types, remove
1911+
// this assertion.
1912+
assert!(self.intersects(TC_OWNED_POINTER));
1913+
}
19081914
let tc = TC_MANAGED + TC_DTOR + TypeContents::owned(cx);
19091915
self.intersects(tc)
19101916
}
19111917

19121918
pub fn owned(_cx: ctxt) -> TypeContents {
19131919
//! Any kind of owned contents.
1914-
TC_OWNED_CLOSURE + TC_OWNED_POINTER + TC_OWNED_VEC
1920+
TC_OWNED_POINTER + TC_OWNED_VEC
19151921
}
19161922
}
19171923

@@ -1945,8 +1951,8 @@ static TC_OWNED_POINTER: TypeContents = TypeContents{bits: 0b0000_0000_0010};
19451951
/// Contains an owned vector ~[] or owned string ~str
19461952
static TC_OWNED_VEC: TypeContents = TypeContents{bits: 0b0000_0000_0100};
19471953

1948-
/// Contains a ~fn() or a ~Trait, which is non-copyable.
1949-
static TC_OWNED_CLOSURE: TypeContents = TypeContents{bits: 0b0000_0000_1000};
1954+
/// Contains a non-copyable ~fn() or a ~Trait (NOT a ~fn:Copy() or ~Trait:Copy).
1955+
static TC_NONCOPY_TRAIT: TypeContents = TypeContents{bits: 0b0000_0000_1000};
19501956

19511957
/// Type with a destructor
19521958
static TC_DTOR: TypeContents = TypeContents{bits: 0b0000_0001_0000};
@@ -2061,7 +2067,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
20612067
}
20622068

20632069
ty_trait(_, _, UniqTraitStore, _, _bounds) => {
2064-
TC_OWNED_CLOSURE
2070+
// FIXME(#3569): Make this conditional on the trait's bounds.
2071+
TC_NONCOPY_TRAIT + TC_OWNED_POINTER
20652072
}
20662073

20672074
ty_trait(_, _, BoxTraitStore, mutbl, _bounds) => {
@@ -2184,7 +2191,9 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
21842191
match sigil {
21852192
ast::BorrowedSigil => TC_BORROWED_POINTER,
21862193
ast::ManagedSigil => TC_MANAGED,
2187-
ast::OwnedSigil => TC_OWNED_CLOSURE
2194+
// FIXME(#3569): Looks like noncopyability should depend
2195+
// on the bounds, but I don't think this case ever comes up.
2196+
ast::OwnedSigil => TC_NONCOPY_TRAIT + TC_OWNED_POINTER,
21882197
}
21892198
}
21902199

@@ -2258,7 +2267,11 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
22582267
let st = match cty.sigil {
22592268
ast::BorrowedSigil => TC_BORROWED_POINTER,
22602269
ast::ManagedSigil => TC_MANAGED,
2261-
ast::OwnedSigil => TC_OWNED_CLOSURE
2270+
ast::OwnedSigil => if cty.bounds.contains_elem(BoundCopy) {
2271+
TC_OWNED_POINTER
2272+
} else {
2273+
TC_OWNED_POINTER + TC_NONCOPY_TRAIT
2274+
}
22622275
};
22632276
let rt = borrowed_contents(cty.region, m_imm);
22642277
let ot = match cty.onceness {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-pretty
12+
13+
// Tests correct copying of heap closures' environments.
14+
15+
fn foo(x: ~fn:Copy()) -> (~fn(), ~fn()) {
16+
(copy x, x)
17+
}
18+
fn main() {
19+
let v = ~[~[1,2,3],~[4,5,6]]; // shouldn't get double-freed
20+
let (f1,f2) = do foo {
21+
assert!(v.len() == 2);
22+
};
23+
f1();
24+
f2();
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-pretty
12+
13+
// Tests correct copying of heap closures' environments.
14+
15+
fn bar<T: Copy>(x: T) -> (T, T) {
16+
(copy x, x)
17+
}
18+
fn foo(x: ~fn:Copy()) -> (~fn(), ~fn()) {
19+
bar(x)
20+
}
21+
fn main() {
22+
let v = ~[~[1,2,3],~[4,5,6]]; // shouldn't get double-freed
23+
let (f1,f2) = do foo {
24+
assert!(v.len() == 2);
25+
};
26+
f1();
27+
f2();
28+
}

0 commit comments

Comments
 (0)