Send is no longer a subkind of copy. This allows for sendable, but non-copyable resources. Closes #2420.
This commit is contained in:
parent
f213c1f3a8
commit
0b2f2cabbe
@ -28,7 +28,7 @@ enum future<A> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[doc = "Methods on the `future` type"]
|
#[doc = "Methods on the `future` type"]
|
||||||
impl future<A:send> for future<A> {
|
impl future<A:copy send> for future<A> {
|
||||||
|
|
||||||
fn get() -> A {
|
fn get() -> A {
|
||||||
#[doc = "Get the value of the future"];
|
#[doc = "Get the value of the future"];
|
||||||
|
@ -20,7 +20,7 @@ for *at least* that period of time.
|
|||||||
* ch - a channel of type T to send a `val` on
|
* ch - a channel of type T to send a `val` on
|
||||||
* val - a value of type T to send over the provided `ch`
|
* val - a value of type T to send over the provided `ch`
|
||||||
"]
|
"]
|
||||||
fn delayed_send<T: send>(msecs: uint, ch: comm::chan<T>, val: T) {
|
fn delayed_send<T: copy send>(msecs: uint, ch: comm::chan<T>, val: T) {
|
||||||
task::spawn() {||
|
task::spawn() {||
|
||||||
unsafe {
|
unsafe {
|
||||||
let timer_done_po = comm::port::<()>();
|
let timer_done_po = comm::port::<()>();
|
||||||
@ -94,7 +94,9 @@ An `option<T>` representing the outcome of the call. If the call `recv`'d on
|
|||||||
the provided port in the allotted timeout period, then the result will be a
|
the provided port in the allotted timeout period, then the result will be a
|
||||||
`some(T)`. If not, then `none` will be returned.
|
`some(T)`. If not, then `none` will be returned.
|
||||||
"]
|
"]
|
||||||
fn recv_timeout<T: send>(msecs: uint, wait_po: comm::port<T>) -> option<T> {
|
fn recv_timeout<T: copy send>(msecs: uint, wait_po: comm::port<T>)
|
||||||
|
-> option<T> {
|
||||||
|
|
||||||
let timeout_po = comm::port::<()>();
|
let timeout_po = comm::port::<()>();
|
||||||
let timeout_ch = comm::chan(timeout_po);
|
let timeout_ch = comm::chan(timeout_po);
|
||||||
delayed_send(msecs, timeout_ch, ());
|
delayed_send(msecs, timeout_ch, ());
|
||||||
|
@ -24,10 +24,12 @@ import freevars::freevar_entry;
|
|||||||
// types.
|
// types.
|
||||||
|
|
||||||
fn kind_to_str(k: kind) -> str {
|
fn kind_to_str(k: kind) -> str {
|
||||||
if k == kind_sendable() { "sendable" }
|
alt (ty::kind_can_be_copied(k), ty::kind_can_be_sent(k)) {
|
||||||
else if k == kind_copyable() { "copyable" }
|
(false, false) { "noncopyable" }
|
||||||
else if k == kind_noncopyable() { "noncopyable" }
|
(false, true) { "sendable" }
|
||||||
else { fail "unknown kind" }
|
(true, false) { "copyable" }
|
||||||
|
(true, true) { "copy-sendable" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type rval_map = std::map::hashmap<node_id, ()>;
|
type rval_map = std::map::hashmap<node_id, ()>;
|
||||||
|
@ -425,9 +425,9 @@ fn param_bounds_to_kind(bounds: param_bounds) -> kind {
|
|||||||
for vec::each(*bounds) {|bound|
|
for vec::each(*bounds) {|bound|
|
||||||
alt bound {
|
alt bound {
|
||||||
bound_copy {
|
bound_copy {
|
||||||
if kind != kind_sendable() { kind = kind_copyable(); }
|
kind = lower_kind(kind, kind_copyable());
|
||||||
}
|
}
|
||||||
bound_send { kind = kind_sendable(); }
|
bound_send { kind = lower_kind(kind, kind_send_only()); }
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1277,6 +1277,10 @@ fn kind_sendable() -> kind {
|
|||||||
kind_(KIND_MASK_COPY | KIND_MASK_SEND)
|
kind_(KIND_MASK_COPY | KIND_MASK_SEND)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn kind_send_only() -> kind {
|
||||||
|
kind_(KIND_MASK_SEND)
|
||||||
|
}
|
||||||
|
|
||||||
// Using these query functons is preferable to direct comparison or matching
|
// Using these query functons is preferable to direct comparison or matching
|
||||||
// against the kind constants, as we may modify the kind hierarchy in the
|
// against the kind constants, as we may modify the kind hierarchy in the
|
||||||
// future.
|
// future.
|
||||||
@ -1303,7 +1307,7 @@ fn kind_lteq(a: kind, b: kind) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lower_kind(a: kind, b: kind) -> kind {
|
fn lower_kind(a: kind, b: kind) -> kind {
|
||||||
if kind_lteq(a, b) { a } else { b }
|
kind_(*a | *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1402,7 +1406,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
|
|||||||
}
|
}
|
||||||
lowest
|
lowest
|
||||||
}
|
}
|
||||||
ty_res(did, inner, tps) { kind_noncopyable() }
|
ty_res(did, inner, tps) { kind_send_only() }
|
||||||
ty_param(_, did) {
|
ty_param(_, did) {
|
||||||
param_bounds_to_kind(cx.ty_param_bounds.get(did.node))
|
param_bounds_to_kind(cx.ty_param_bounds.get(did.node))
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ fn mk_fold<T:copy>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_any_fold<T:send>(ctxt: T) -> fold<T> {
|
fn default_any_fold<T:send copy>(ctxt: T) -> fold<T> {
|
||||||
mk_fold(
|
mk_fold(
|
||||||
ctxt,
|
ctxt,
|
||||||
{|f, d| default_seq_fold_doc(f, d)},
|
{|f, d| default_seq_fold_doc(f, d)},
|
||||||
@ -121,7 +121,7 @@ fn default_seq_fold<T:copy>(ctxt: T) -> fold<T> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_par_fold<T:send>(ctxt: T) -> fold<T> {
|
fn default_par_fold<T:send copy>(ctxt: T) -> fold<T> {
|
||||||
mk_fold(
|
mk_fold(
|
||||||
ctxt,
|
ctxt,
|
||||||
{|f, d| default_seq_fold_doc(f, d)},
|
{|f, d| default_seq_fold_doc(f, d)},
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
fn foo(_x: r) {}
|
|
||||||
|
|
||||||
resource r(_x: ()) {}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let x = r(());
|
|
||||||
let _ = fn~() {
|
|
||||||
// Error even though this is the last use:
|
|
||||||
foo(x); //! ERROR not a sendable value
|
|
||||||
};
|
|
||||||
|
|
||||||
let x = r(());
|
|
||||||
let _ = fn@() {
|
|
||||||
// OK in fn@ because this is the last use:
|
|
||||||
foo(x);
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
// error-pattern: copying a noncopyable value
|
|
||||||
|
|
||||||
resource r(i: @mut int) {
|
|
||||||
*i = *i + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let i = @mut 0;
|
|
||||||
{
|
|
||||||
// Can't do this copy
|
|
||||||
let x = ~~~{y: r(i)};
|
|
||||||
let z = x;
|
|
||||||
log(debug, x);
|
|
||||||
}
|
|
||||||
log(error, *i);
|
|
||||||
}
|
|
@ -13,7 +13,7 @@ fn make_cycle<A:copy>(a: A) {
|
|||||||
g.rec = some(g);
|
g.rec = some(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn f<A:send,B:send>(a: A, b: B) -> fn@() -> (A, B) {
|
fn f<A:send copy, B:send copy>(a: A, b: B) -> fn@() -> (A, B) {
|
||||||
fn@() -> (A, B) { (a, b) }
|
fn@() -> (A, B) { (a, b) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
fn id<T: send>(t: T) -> T { ret t; }
|
fn id<T: copy send>(t: T) -> T { ret t; }
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let expected = ~100;
|
let expected = ~100;
|
||||||
|
20
src/test/run-pass/send-resource.rs
Normal file
20
src/test/run-pass/send-resource.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import task::*;
|
||||||
|
import comm::*;
|
||||||
|
|
||||||
|
resource test(_f: int) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let p = port();
|
||||||
|
let c = chan(p);
|
||||||
|
|
||||||
|
spawn() {||
|
||||||
|
let p = port();
|
||||||
|
c.send(chan(p));
|
||||||
|
|
||||||
|
let _r = p.recv();
|
||||||
|
}
|
||||||
|
|
||||||
|
p.recv().send(test(42));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user