Make ~fn non-copyable, make &fn copyable, split barefn/closure types,

correct handling of moves for struct-record update.

Part of #3678.  Fixes #2828, #3904, #4719.
This commit is contained in:
Niko Matsakis 2013-01-31 17:12:29 -08:00
parent 82d7396333
commit a32498d846
187 changed files with 2065 additions and 2373 deletions

View file

@ -9,6 +9,7 @@
// except according to those terms.
#[legacy_modes];
#[allow(deprecated_mode)];
/*!
@ -247,8 +248,13 @@ fn pbfs(&&graph: arc::ARC<graph>, key: node_id) -> bfs_result {
}
}
fn is_gray_factory() -> ~fn(c: &color) -> bool {
let r: ~fn(c: &color) -> bool = is_gray;
r
}
let mut i = 0;
while par::any(colors, is_gray) {
while par::any(colors, is_gray_factory) {
// Do the BFS.
log(info, fmt!("PBFS iteration %?", i));
i += 1;
@ -257,14 +263,13 @@ fn pbfs(&&graph: arc::ARC<graph>, key: node_id) -> bfs_result {
let color = arc::ARC(move colors);
let color_vec = arc::get(&color); // FIXME #3387 requires this temp
colors = do par::mapi_factory(*color_vec) {
colors = do par::mapi(*color_vec) {
let colors = arc::clone(&color);
let graph = arc::clone(&graph);
fn~(move graph, move colors, +i: uint, +c: color) -> color {
let c : color = c;
fn~(+i: uint, +c: &color) -> color {
let colors = arc::get(&colors);
let graph = arc::get(&graph);
match c {
match *c {
white => {
let i = i as node_id;
@ -290,11 +295,13 @@ fn pbfs(&&graph: arc::ARC<graph>, key: node_id) -> bfs_result {
}
// Convert the results.
do par::map(colors) |c| {
match *c {
white => { -1i64 }
black(parent) => { parent }
_ => { die!(~"Found remaining gray nodes in BFS") }
do par::map(colors) {
fn~(c: &color) -> i64 {
match *c {
white => { -1i64 }
black(parent) => { parent }
_ => { die!(~"Found remaining gray nodes in BFS") }
}
}
}
}
@ -377,14 +384,15 @@ fn validate(edges: ~[(node_id, node_id)],
log(info, ~"Verifying tree and graph edges...");
let edges = copy edges;
let status = do par::alli(tree) |u, v| {
let u = u as node_id;
if *v == -1i64 || u == root {
true
}
else {
edges.contains(&(u, *v)) || edges.contains(&(*v, u))
let status = do par::alli(tree) {
let edges = copy edges;
fn~(+u: uint, v: &i64) -> bool {
let u = u as node_id;
if *v == -1i64 || u == root {
true
} else {
edges.contains(&(u, *v)) || edges.contains(&(*v, u))
}
}
};

View file

@ -15,6 +15,10 @@ extern mod std;
use std::list::{List, Cons, Nil};
use std::time::precise_time_s;
enum UniqueList {
ULNil, ULCons(~UniqueList)
}
fn main() {
let (repeat, depth) = if os::getenv(~"RUST_BENCH").is_some() {
(50, 1000)
@ -43,7 +47,6 @@ struct State {
box: @nillist,
unique: ~nillist,
fn_box: fn@() -> @nillist,
fn_unique: fn~() -> ~nillist,
tuple: (@nillist, ~nillist),
vec: ~[@nillist],
res: r
@ -76,7 +79,6 @@ fn recurse_or_fail(depth: int, st: Option<State>) {
box: @Nil,
unique: ~Nil,
fn_box: fn@() -> @nillist { @Nil::<()> },
fn_unique: fn~() -> ~nillist { ~Nil::<()> },
tuple: (@Nil, ~Nil),
vec: ~[@Nil],
res: r(@Nil)
@ -84,14 +86,11 @@ fn recurse_or_fail(depth: int, st: Option<State>) {
}
Some(st) => {
let fn_box = st.fn_box;
let fn_unique = copy st.fn_unique;
State {
box: @Cons((), st.box),
unique: ~Cons((), @*st.unique),
fn_box: fn@() -> @nillist { @Cons((), fn_box()) },
fn_unique: fn~(move fn_unique) -> ~nillist
{ ~Cons((), @*fn_unique()) },
tuple: (@Cons((), st.tuple.first()),
~Cons((), @*st.tuple.second())),
vec: st.vec + ~[@Cons((), st.vec.last())],

View file

@ -1,17 +0,0 @@
// Copyright 2012 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.
fn main() {
let x = 3;
fn blah(_a: extern fn()) {}
blah(|| {
log(debug, x); //~ ERROR attempted dynamic environment capture
});
}

View file

@ -1,20 +0,0 @@
// Copyright 2012 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.
fn to_lambda1(f: fn@(uint) -> uint) -> fn@(uint) -> uint {
return f;
}
fn to_lambda2(b: fn(uint) -> uint) -> fn@(uint) -> uint {
return to_lambda1(|x| b(x)); //~ ERROR illegal move from argument `b`
}
fn main() {
}

View file

@ -1,31 +0,0 @@
// Copyright 2012 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.
struct Bar {
x: int,
}
impl Bar : Drop {
fn finalize(&self) {
io::println("Goodbye, cruel world");
}
}
struct Foo {
x: int,
y: Bar
}
fn main() {
let a = Foo { x: 1, y: Bar { x: 5 } };
let c = Foo { x: 4, .. a}; //~ ERROR cannot copy field `y` of base expression, which has a noncopyable type
io::println(fmt!("%?", c));
}

View file

@ -8,12 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: Non-function passed to a `do` function as its last argument, or wrong number of arguments passed to a `do` function
fn main() {
let needlesArr: ~[char] = ~['a', 'f'];
do vec::foldr(needlesArr) |x, y| {
//~^ ERROR 2 parameters were supplied (including the closure passed by the `do` keyword)
//~^^ ERROR Unconstrained region variable #2
//
// this last error is, um, non-ideal.
}
// for some reason if I use the new error syntax for the two error messages this generates,
// the test runner gets confused -- tjc
}

View file

@ -24,6 +24,6 @@ fn main() {
copy2(@&x); //~ ERROR missing `&static`
copy2(fn@() {});
copy2(fn~() {}); //~ WARNING instantiating copy type parameter with a not implicitly copyable type
copy2(fn&() {}); //~ ERROR missing `copy &static`
copy2(fn~() {}); //~ ERROR missing `copy`
copy2(fn&() {}); //~ ERROR missing `&static`
}

View file

@ -0,0 +1,27 @@
type Noncopyable = ~fn();
struct Foo {
copied: int,
moved: ~int,
noncopyable: Noncopyable
}
fn test0(f: Foo, g: Noncopyable, h: Noncopyable) {
// just copy implicitly copyable fields from `f`, no moves:
let _b = Foo {moved: ~1, noncopyable: g, ..f};
let _c = Foo {moved: ~2, noncopyable: h, ..f};
}
fn test1(f: Foo, g: Noncopyable, h: Noncopyable) {
// copying move-by-default fields from `f`, so move:
let _b = Foo {noncopyable: g, ..f};
let _c = Foo {noncopyable: h, ..f}; //~ ERROR use of moved value: `f`
}
fn test2(f: Foo, g: Noncopyable) {
// move non-copyable field
let _b = Foo {copied: 22, moved: ~23, ..f};
let _c = Foo {noncopyable: g, ..f}; //~ ERROR use of moved value: `f`
}
fn main() {}

View file

@ -1,17 +0,0 @@
// Copyright 2012 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.
fn ignore<T>(_x: T) {}
pub fn main() {
let f: fn@:Owned() = ||();
ignore(f);
}

View file

@ -29,11 +29,11 @@ fn calllink08() { unsafe { rustrt::get_task_id(); } }
fn calllink09() { unsafe { rustrt::rust_sched_threads(); } }
fn calllink10() { unsafe { rustrt::rust_get_task(); } }
fn runtest(f: fn~(), frame_backoff: u32) {
fn runtest(f: extern fn(), frame_backoff: u32) {
runtest2(f, frame_backoff, 0 as *u8);
}
fn runtest2(f: fn~(), frame_backoff: u32, last_stk: *u8) -> u32 {
fn runtest2(f: extern fn(), frame_backoff: u32, last_stk: *u8) -> u32 {
unsafe {
let curr_stk = rustrt::debug_get_stk_seg();
if (last_stk != curr_stk && last_stk != 0 as *u8) {
@ -67,6 +67,6 @@ pub fn main() {
let f = *f;
let sz = rng.next() % 256u32 + 256u32;
let frame_backoff = rng.next() % 10u32 + 1u32;
task::try(|move f| runtest(f, frame_backoff) );
task::try(|| runtest(f, frame_backoff) );
}
}

View file

@ -16,5 +16,6 @@ fn compute(i: mytype) -> int { return i.val + 20; }
pub fn main() {
let myval = mytype(Mytype{compute: compute, val: 30});
io::println(fmt!("%d", compute(myval)));
assert ((myval.compute)(myval) == 50);
}

View file

@ -1,36 +0,0 @@
// Copyright 2012 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.
pub fn main() { test05(); }
fn mk_counter<A:Copy>() -> fn~(A) -> (A,uint) {
// The only reason that the counter is generic is so that it closes
// over both a type descriptor and some data.
let v = ~[mut 0u];
return fn~(a: A) -> (A,uint) {
let n = v[0];
v[0] = n + 1u;
(a, n)
};
}
fn test05() {
let fp0 = mk_counter::<float>();
assert (5.3f, 0u) == fp0(5.3f);
assert (5.5f, 1u) == fp0(5.5f);
let fp1 = copy fp0;
assert (5.3f, 2u) == fp0(5.3f);
assert (5.3f, 2u) == fp1(5.3f);
assert (5.5f, 3u) == fp0(5.5f);
assert (5.5f, 3u) == fp1(5.5f);
}

View file

@ -28,11 +28,11 @@ fn checktests() {
// Pull the tests out of the secreturn test module
let tests = __test::tests();
let shouldignore = option::get(
vec::find(tests, |t| t.name == ~"shouldignore" ));
assert shouldignore.ignore == true;
assert vec::any(
tests,
|t| t.desc.name == ~"shouldignore" && t.desc.ignore);
let shouldnotignore = option::get(
vec::find(tests, |t| t.name == ~"shouldnotignore" ));
assert shouldnotignore.ignore == false;
assert vec::any(
tests,
|t| t.desc.name == ~"shouldnotignore" && !t.desc.ignore);
}