rollup merge of #22319: huonw/send-is-not-static
Conflicts: src/libstd/sync/task_pool.rs src/libstd/thread.rs src/libtest/lib.rs src/test/bench/shootout-reverse-complement.rs src/test/bench/shootout-spectralnorm.rs
This commit is contained in:
commit
ba8ce4c2c2
49 changed files with 231 additions and 297 deletions
|
@ -32,9 +32,19 @@ use clone::Clone;
|
||||||
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
||||||
#[lang="send"]
|
#[lang="send"]
|
||||||
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||||
|
#[cfg(stage0)] // SNAP ac134f7 remove after stage0
|
||||||
pub unsafe trait Send: 'static {
|
pub unsafe trait Send: 'static {
|
||||||
// empty.
|
// empty.
|
||||||
}
|
}
|
||||||
|
/// Types able to be transferred across thread boundaries.
|
||||||
|
#[unstable(feature = "core",
|
||||||
|
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
||||||
|
#[lang="send"]
|
||||||
|
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
pub unsafe trait Send {
|
||||||
|
// empty.
|
||||||
|
}
|
||||||
|
|
||||||
/// Types with a constant size known at compile-time.
|
/// Types with a constant size known at compile-time.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -424,3 +434,11 @@ pub struct NoCopy;
|
||||||
#[lang="managed_bound"]
|
#[lang="managed_bound"]
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Managed;
|
pub struct Managed;
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // SNAP ac134f7 remove this attribute after the next snapshot
|
||||||
|
mod impls {
|
||||||
|
use super::{Send, Sync, Sized};
|
||||||
|
|
||||||
|
unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
|
||||||
|
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ use self::EvaluationResult::*;
|
||||||
use super::{DerivedObligationCause};
|
use super::{DerivedObligationCause};
|
||||||
use super::{project};
|
use super::{project};
|
||||||
use super::project::Normalized;
|
use super::project::Normalized;
|
||||||
use super::{PredicateObligation, Obligation, TraitObligation, ObligationCause};
|
use super::{PredicateObligation, TraitObligation, ObligationCause};
|
||||||
use super::{ObligationCauseCode, BuiltinDerivedObligation};
|
use super::{ObligationCauseCode, BuiltinDerivedObligation};
|
||||||
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
|
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
|
||||||
use super::{Selection};
|
use super::{Selection};
|
||||||
|
@ -34,7 +34,7 @@ use super::{util};
|
||||||
use middle::fast_reject;
|
use middle::fast_reject;
|
||||||
use middle::mem_categorization::Typer;
|
use middle::mem_categorization::Typer;
|
||||||
use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace};
|
use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace};
|
||||||
use middle::ty::{self, AsPredicate, RegionEscape, ToPolyTraitRef, Ty};
|
use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
|
||||||
use middle::infer;
|
use middle::infer;
|
||||||
use middle::infer::{InferCtxt, TypeFreshener};
|
use middle::infer::{InferCtxt, TypeFreshener};
|
||||||
use middle::ty_fold::TypeFoldable;
|
use middle::ty_fold::TypeFoldable;
|
||||||
|
@ -1459,22 +1459,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
|
|
||||||
ty::BoundSync |
|
ty::BoundSync |
|
||||||
ty::BoundSend => {
|
ty::BoundSend => {
|
||||||
// Note: technically, a region pointer is only
|
|
||||||
// sendable if it has lifetime
|
|
||||||
// `'static`. However, we don't take regions
|
|
||||||
// into account when doing trait matching:
|
|
||||||
// instead, when we decide that `T : Send`, we
|
|
||||||
// will register a separate constraint with
|
|
||||||
// the region inferencer that `T : 'static`
|
|
||||||
// holds as well (because the trait `Send`
|
|
||||||
// requires it). This will ensure that there
|
|
||||||
// is no borrowed data in `T` (or else report
|
|
||||||
// an inference error). The reason we do it
|
|
||||||
// this way is that we do not yet *know* what
|
|
||||||
// lifetime the borrowed reference has, since
|
|
||||||
// we haven't finished running inference -- in
|
|
||||||
// other words, there's a kind of
|
|
||||||
// chicken-and-egg problem.
|
|
||||||
Ok(If(vec![referent_ty]))
|
Ok(If(vec![referent_ty]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1817,21 +1801,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}).collect::<Result<_, _>>();
|
}).collect::<Result<_, _>>();
|
||||||
let mut obligations = match obligations {
|
let obligations = match obligations {
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
Err(ErrorReported) => Vec::new()
|
Err(ErrorReported) => Vec::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
// as a special case, `Send` requires `'static`
|
|
||||||
if bound == ty::BoundSend {
|
|
||||||
obligations.push(Obligation {
|
|
||||||
cause: obligation.cause.clone(),
|
|
||||||
recursion_depth: obligation.recursion_depth+1,
|
|
||||||
predicate: ty::Binder(ty::OutlivesPredicate(obligation.self_ty(),
|
|
||||||
ty::ReStatic)).as_predicate(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
|
let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
|
||||||
|
|
||||||
debug!("vtable_builtin_data: obligations={}",
|
debug!("vtable_builtin_data: obligations={}",
|
||||||
|
|
|
@ -697,9 +697,8 @@ impl<'tcx> UserString<'tcx> for ty::TyTrait<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Region, if not obviously implied by builtin bounds.
|
// Region, if not obviously implied by builtin bounds.
|
||||||
if bounds.region_bound != ty::ReStatic ||
|
if bounds.region_bound != ty::ReStatic {
|
||||||
!bounds.builtin_bounds.contains(&ty::BoundSend)
|
// Region bound is implied by builtin bounds:
|
||||||
{ // Region bound is implied by builtin bounds:
|
|
||||||
components.push(bounds.region_bound.user_string(tcx));
|
components.push(bounds.region_bound.user_string(tcx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -287,7 +287,7 @@ mod tests {
|
||||||
|
|
||||||
pub fn smalltest<F,G>(server: F, client: G)
|
pub fn smalltest<F,G>(server: F, client: G)
|
||||||
where F : FnOnce(UnixStream), F : Send,
|
where F : FnOnce(UnixStream), F : Send,
|
||||||
G : FnOnce(UnixStream), G : Send
|
G : FnOnce(UnixStream), G : Send + 'static
|
||||||
{
|
{
|
||||||
let path1 = next_test_unix();
|
let path1 = next_test_unix();
|
||||||
let path2 = path1.clone();
|
let path2 = path1.clone();
|
||||||
|
|
|
@ -458,7 +458,7 @@ impl Child {
|
||||||
/// the parent waits for the child to exit.
|
/// the parent waits for the child to exit.
|
||||||
pub fn wait_with_output(mut self) -> io::Result<Output> {
|
pub fn wait_with_output(mut self) -> io::Result<Output> {
|
||||||
drop(self.stdin.take());
|
drop(self.stdin.take());
|
||||||
fn read<T: Read + Send>(stream: Option<T>) -> Receiver<io::Result<Vec<u8>>> {
|
fn read<T: Read + Send + 'static>(stream: Option<T>) -> Receiver<io::Result<Vec<u8>>> {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
match stream {
|
match stream {
|
||||||
Some(stream) => {
|
Some(stream) => {
|
||||||
|
|
|
@ -20,7 +20,7 @@ use mem;
|
||||||
use thunk::Thunk;
|
use thunk::Thunk;
|
||||||
use sys_common::mutex::{Mutex, MUTEX_INIT};
|
use sys_common::mutex::{Mutex, MUTEX_INIT};
|
||||||
|
|
||||||
type Queue = Vec<Thunk>;
|
type Queue = Vec<Thunk<'static>>;
|
||||||
|
|
||||||
// NB these are specifically not types from `std::sync` as they currently rely
|
// NB these are specifically not types from `std::sync` as they currently rely
|
||||||
// on poisoning and this module needs to operate at a lower level than requiring
|
// on poisoning and this module needs to operate at a lower level than requiring
|
||||||
|
@ -65,7 +65,7 @@ pub fn cleanup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(f: Thunk) {
|
pub fn push(f: Thunk<'static>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
LOCK.lock();
|
LOCK.lock();
|
||||||
init();
|
init();
|
||||||
|
|
|
@ -148,7 +148,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
|
||||||
///
|
///
|
||||||
/// It is forbidden for procedures to register more `at_exit` handlers when they
|
/// It is forbidden for procedures to register more `at_exit` handlers when they
|
||||||
/// are running, and doing so will lead to a process abort.
|
/// are running, and doing so will lead to a process abort.
|
||||||
pub fn at_exit<F:FnOnce()+Send>(f: F) {
|
pub fn at_exit<F:FnOnce()+Send+'static>(f: F) {
|
||||||
at_exit_imp::push(Thunk::new(f));
|
at_exit_imp::push(Thunk::new(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ use rt::libunwind as uw;
|
||||||
|
|
||||||
struct Exception {
|
struct Exception {
|
||||||
uwe: uw::_Unwind_Exception,
|
uwe: uw::_Unwind_Exception,
|
||||||
cause: Option<Box<Any + Send>>,
|
cause: Option<Box<Any + Send + 'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint);
|
pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint);
|
||||||
|
@ -161,7 +161,7 @@ pub fn panicking() -> bool {
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(private_no_mangle_fns)]
|
#[allow(private_no_mangle_fns)]
|
||||||
fn rust_panic(cause: Box<Any + Send>) -> ! {
|
fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
|
||||||
rtdebug!("begin_unwind()");
|
rtdebug!("begin_unwind()");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub struct Future<A> {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FutureState<A> {
|
enum FutureState<A> {
|
||||||
Pending(Thunk<(),A>),
|
Pending(Thunk<'static,(),A>),
|
||||||
Evaluating,
|
Evaluating,
|
||||||
Forced(A)
|
Forced(A)
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ impl<A> Future<A> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_fn<F>(f: F) -> Future<A>
|
pub fn from_fn<F>(f: F) -> Future<A>
|
||||||
where F : FnOnce() -> A, F : Send
|
where F : FnOnce() -> A, F : Send + 'static
|
||||||
{
|
{
|
||||||
/*!
|
/*!
|
||||||
* Create a future from a function.
|
* Create a future from a function.
|
||||||
|
@ -117,7 +117,7 @@ impl<A> Future<A> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A:Send> Future<A> {
|
impl<A:Send+'static> Future<A> {
|
||||||
pub fn from_receiver(rx: Receiver<A>) -> Future<A> {
|
pub fn from_receiver(rx: Receiver<A>) -> Future<A> {
|
||||||
/*!
|
/*!
|
||||||
* Create a future from a port
|
* Create a future from a port
|
||||||
|
@ -132,7 +132,7 @@ impl<A:Send> Future<A> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn<F>(blk: F) -> Future<A>
|
pub fn spawn<F>(blk: F) -> Future<A>
|
||||||
where F : FnOnce() -> A, F : Send
|
where F : FnOnce() -> A, F : Send + 'static
|
||||||
{
|
{
|
||||||
/*!
|
/*!
|
||||||
* Create a future from a unique closure.
|
* Create a future from a unique closure.
|
||||||
|
|
|
@ -345,7 +345,7 @@ pub struct Receiver<T> {
|
||||||
|
|
||||||
// The receiver port can be sent from place to place, so long as it
|
// The receiver port can be sent from place to place, so long as it
|
||||||
// is not used to receive non-sendable things.
|
// is not used to receive non-sendable things.
|
||||||
unsafe impl<T:Send> Send for Receiver<T> { }
|
unsafe impl<T: Send + 'static> Send for Receiver<T> { }
|
||||||
|
|
||||||
/// An iterator over messages on a receiver, this iterator will block
|
/// An iterator over messages on a receiver, this iterator will block
|
||||||
/// whenever `next` is called, waiting for a new message, and `None` will be
|
/// whenever `next` is called, waiting for a new message, and `None` will be
|
||||||
|
@ -364,7 +364,7 @@ pub struct Sender<T> {
|
||||||
|
|
||||||
// The send port can be sent from place to place, so long as it
|
// The send port can be sent from place to place, so long as it
|
||||||
// is not used to send non-sendable things.
|
// is not used to send non-sendable things.
|
||||||
unsafe impl<T:Send> Send for Sender<T> { }
|
unsafe impl<T: Send + 'static> Send for Sender<T> { }
|
||||||
|
|
||||||
/// The sending-half of Rust's synchronous channel type. This half can only be
|
/// The sending-half of Rust's synchronous channel type. This half can only be
|
||||||
/// owned by one task, but it can be cloned to send to other tasks.
|
/// owned by one task, but it can be cloned to send to other tasks.
|
||||||
|
@ -373,7 +373,7 @@ pub struct SyncSender<T> {
|
||||||
inner: Arc<UnsafeCell<sync::Packet<T>>>,
|
inner: Arc<UnsafeCell<sync::Packet<T>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T:Send> Send for SyncSender<T> {}
|
unsafe impl<T: Send + 'static> Send for SyncSender<T> {}
|
||||||
|
|
||||||
impl<T> !Sync for SyncSender<T> {}
|
impl<T> !Sync for SyncSender<T> {}
|
||||||
|
|
||||||
|
@ -485,7 +485,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
|
||||||
/// println!("{:?}", rx.recv().unwrap());
|
/// println!("{:?}", rx.recv().unwrap());
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
|
pub fn channel<T: Send + 'static>() -> (Sender<T>, Receiver<T>) {
|
||||||
let a = Arc::new(UnsafeCell::new(oneshot::Packet::new()));
|
let a = Arc::new(UnsafeCell::new(oneshot::Packet::new()));
|
||||||
(Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
|
(Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
|
||||||
}
|
}
|
||||||
|
@ -525,7 +525,7 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
|
||||||
/// assert_eq!(rx.recv().unwrap(), 2);
|
/// assert_eq!(rx.recv().unwrap(), 2);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
|
pub fn sync_channel<T: Send + 'static>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
|
||||||
let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound)));
|
let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound)));
|
||||||
(SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
|
(SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
|
||||||
}
|
}
|
||||||
|
@ -534,7 +534,7 @@ pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
|
||||||
// Sender
|
// Sender
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl<T: Send> Sender<T> {
|
impl<T: Send + 'static> Sender<T> {
|
||||||
fn new(inner: Flavor<T>) -> Sender<T> {
|
fn new(inner: Flavor<T>) -> Sender<T> {
|
||||||
Sender {
|
Sender {
|
||||||
inner: UnsafeCell::new(inner),
|
inner: UnsafeCell::new(inner),
|
||||||
|
@ -616,7 +616,7 @@ impl<T: Send> Sender<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Send> Clone for Sender<T> {
|
impl<T: Send + 'static> Clone for Sender<T> {
|
||||||
fn clone(&self) -> Sender<T> {
|
fn clone(&self) -> Sender<T> {
|
||||||
let (packet, sleeper, guard) = match *unsafe { self.inner() } {
|
let (packet, sleeper, guard) = match *unsafe { self.inner() } {
|
||||||
Flavor::Oneshot(ref p) => {
|
Flavor::Oneshot(ref p) => {
|
||||||
|
@ -662,7 +662,7 @@ impl<T: Send> Clone for Sender<T> {
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Send> Drop for Sender<T> {
|
impl<T: Send + 'static> Drop for Sender<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
match *unsafe { self.inner_mut() } {
|
match *unsafe { self.inner_mut() } {
|
||||||
Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
|
Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
|
||||||
|
@ -677,7 +677,7 @@ impl<T: Send> Drop for Sender<T> {
|
||||||
// SyncSender
|
// SyncSender
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl<T: Send> SyncSender<T> {
|
impl<T: Send + 'static> SyncSender<T> {
|
||||||
fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
|
fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
|
||||||
SyncSender { inner: inner }
|
SyncSender { inner: inner }
|
||||||
}
|
}
|
||||||
|
@ -717,7 +717,7 @@ impl<T: Send> SyncSender<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Send> Clone for SyncSender<T> {
|
impl<T: Send + 'static> Clone for SyncSender<T> {
|
||||||
fn clone(&self) -> SyncSender<T> {
|
fn clone(&self) -> SyncSender<T> {
|
||||||
unsafe { (*self.inner.get()).clone_chan(); }
|
unsafe { (*self.inner.get()).clone_chan(); }
|
||||||
return SyncSender::new(self.inner.clone());
|
return SyncSender::new(self.inner.clone());
|
||||||
|
@ -726,7 +726,7 @@ impl<T: Send> Clone for SyncSender<T> {
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Send> Drop for SyncSender<T> {
|
impl<T: Send + 'static> Drop for SyncSender<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { (*self.inner.get()).drop_chan(); }
|
unsafe { (*self.inner.get()).drop_chan(); }
|
||||||
}
|
}
|
||||||
|
@ -736,7 +736,7 @@ impl<T: Send> Drop for SyncSender<T> {
|
||||||
// Receiver
|
// Receiver
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl<T: Send> Receiver<T> {
|
impl<T: Send + 'static> Receiver<T> {
|
||||||
fn new(inner: Flavor<T>) -> Receiver<T> {
|
fn new(inner: Flavor<T>) -> Receiver<T> {
|
||||||
Receiver { inner: UnsafeCell::new(inner) }
|
Receiver { inner: UnsafeCell::new(inner) }
|
||||||
}
|
}
|
||||||
|
@ -855,7 +855,7 @@ impl<T: Send> Receiver<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Send> select::Packet for Receiver<T> {
|
impl<T: Send + 'static> select::Packet for Receiver<T> {
|
||||||
fn can_recv(&self) -> bool {
|
fn can_recv(&self) -> bool {
|
||||||
loop {
|
loop {
|
||||||
let new_port = match *unsafe { self.inner() } {
|
let new_port = match *unsafe { self.inner() } {
|
||||||
|
@ -942,7 +942,7 @@ impl<T: Send> select::Packet for Receiver<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, T: Send> Iterator for Iter<'a, T> {
|
impl<'a, T: Send + 'static> Iterator for Iter<'a, T> {
|
||||||
type Item = T;
|
type Item = T;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
|
fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
|
||||||
|
@ -950,7 +950,7 @@ impl<'a, T: Send> Iterator for Iter<'a, T> {
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Send> Drop for Receiver<T> {
|
impl<T: Send + 'static> Drop for Receiver<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
match *unsafe { self.inner_mut() } {
|
match *unsafe { self.inner_mut() } {
|
||||||
Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
|
Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
|
||||||
|
|
|
@ -78,7 +78,7 @@ pub struct Queue<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T:Send> Send for Queue<T> { }
|
unsafe impl<T:Send> Send for Queue<T> { }
|
||||||
unsafe impl<T:Send> Sync for Queue<T> { }
|
unsafe impl<T: Send + 'static> Sync for Queue<T> { }
|
||||||
|
|
||||||
impl<T> Node<T> {
|
impl<T> Node<T> {
|
||||||
unsafe fn new(v: Option<T>) -> *mut Node<T> {
|
unsafe fn new(v: Option<T>) -> *mut Node<T> {
|
||||||
|
@ -89,7 +89,7 @@ impl<T> Node<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Send> Queue<T> {
|
impl<T: Send + 'static> Queue<T> {
|
||||||
/// Creates a new queue that is safe to share among multiple producers and
|
/// Creates a new queue that is safe to share among multiple producers and
|
||||||
/// one consumer.
|
/// one consumer.
|
||||||
pub fn new() -> Queue<T> {
|
pub fn new() -> Queue<T> {
|
||||||
|
@ -140,7 +140,7 @@ impl<T: Send> Queue<T> {
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Send> Drop for Queue<T> {
|
impl<T: Send + 'static> Drop for Queue<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut cur = *self.tail.get();
|
let mut cur = *self.tail.get();
|
||||||
|
|
|
@ -88,7 +88,7 @@ enum MyUpgrade<T> {
|
||||||
GoUp(Receiver<T>),
|
GoUp(Receiver<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Send> Packet<T> {
|
impl<T: Send + 'static> Packet<T> {
|
||||||
pub fn new() -> Packet<T> {
|
pub fn new() -> Packet<T> {
|
||||||
Packet {
|
Packet {
|
||||||
data: None,
|
data: None,
|
||||||
|
@ -368,7 +368,7 @@ impl<T: Send> Packet<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl<T: Send> Drop for Packet<T> {
|
impl<T: Send + 'static> Drop for Packet<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
assert_eq!(self.state.load(Ordering::SeqCst), DISCONNECTED);
|
assert_eq!(self.state.load(Ordering::SeqCst), DISCONNECTED);
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ impl Select {
|
||||||
/// Creates a new handle into this receiver set for a new receiver. Note
|
/// Creates a new handle into this receiver set for a new receiver. Note
|
||||||
/// that this does *not* add the receiver to the receiver set, for that you
|
/// that this does *not* add the receiver to the receiver set, for that you
|
||||||
/// must call the `add` method on the handle itself.
|
/// must call the `add` method on the handle itself.
|
||||||
pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
|
pub fn handle<'a, T: Send + 'static>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
|
||||||
let id = self.next_id.get();
|
let id = self.next_id.get();
|
||||||
self.next_id.set(id + 1);
|
self.next_id.set(id + 1);
|
||||||
Handle {
|
Handle {
|
||||||
|
@ -251,7 +251,7 @@ impl Select {
|
||||||
fn iter(&self) -> Packets { Packets { cur: self.head } }
|
fn iter(&self) -> Packets { Packets { cur: self.head } }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'rx, T: Send> Handle<'rx, T> {
|
impl<'rx, T: Send + 'static> Handle<'rx, T> {
|
||||||
/// Retrieve the id of this handle.
|
/// Retrieve the id of this handle.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id(&self) -> uint { self.id }
|
pub fn id(&self) -> uint { self.id }
|
||||||
|
@ -322,7 +322,7 @@ impl Drop for Select {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl<'rx, T: Send> Drop for Handle<'rx, T> {
|
impl<'rx, T: Send + 'static> Drop for Handle<'rx, T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { self.remove() }
|
unsafe { self.remove() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ pub enum Failure {
|
||||||
Disconnected,
|
Disconnected,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Send> Packet<T> {
|
impl<T: Send + 'static> Packet<T> {
|
||||||
// Creation of a packet *must* be followed by a call to postinit_lock
|
// Creation of a packet *must* be followed by a call to postinit_lock
|
||||||
// and later by inherit_blocker
|
// and later by inherit_blocker
|
||||||
pub fn new() -> Packet<T> {
|
pub fn new() -> Packet<T> {
|
||||||
|
@ -474,7 +474,7 @@ impl<T: Send> Packet<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl<T: Send> Drop for Packet<T> {
|
impl<T: Send + 'static> Drop for Packet<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Note that this load is not only an assert for correctness about
|
// Note that this load is not only an assert for correctness about
|
||||||
// disconnection, but also a proper fence before the read of
|
// disconnection, but also a proper fence before the read of
|
||||||
|
|
|
@ -74,11 +74,11 @@ pub struct Queue<T> {
|
||||||
cache_subtractions: AtomicUsize,
|
cache_subtractions: AtomicUsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T: Send> Send for Queue<T> { }
|
unsafe impl<T: Send + 'static> Send for Queue<T> { }
|
||||||
|
|
||||||
unsafe impl<T: Send> Sync for Queue<T> { }
|
unsafe impl<T: Send + 'static> Sync for Queue<T> { }
|
||||||
|
|
||||||
impl<T: Send> Node<T> {
|
impl<T: Send + 'static> Node<T> {
|
||||||
fn new() -> *mut Node<T> {
|
fn new() -> *mut Node<T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
mem::transmute(box Node {
|
mem::transmute(box Node {
|
||||||
|
@ -89,7 +89,7 @@ impl<T: Send> Node<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Send> Queue<T> {
|
impl<T: Send + 'static> Queue<T> {
|
||||||
/// Creates a new queue.
|
/// Creates a new queue.
|
||||||
///
|
///
|
||||||
/// This is unsafe as the type system doesn't enforce a single
|
/// This is unsafe as the type system doesn't enforce a single
|
||||||
|
@ -227,7 +227,7 @@ impl<T: Send> Queue<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl<T: Send> Drop for Queue<T> {
|
impl<T: Send + 'static> Drop for Queue<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut cur = *self.first.get();
|
let mut cur = *self.first.get();
|
||||||
|
|
|
@ -74,7 +74,7 @@ enum Message<T> {
|
||||||
GoUp(Receiver<T>),
|
GoUp(Receiver<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Send> Packet<T> {
|
impl<T: Send + 'static> Packet<T> {
|
||||||
pub fn new() -> Packet<T> {
|
pub fn new() -> Packet<T> {
|
||||||
Packet {
|
Packet {
|
||||||
queue: unsafe { spsc::Queue::new(128) },
|
queue: unsafe { spsc::Queue::new(128) },
|
||||||
|
@ -472,7 +472,7 @@ impl<T: Send> Packet<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl<T: Send> Drop for Packet<T> {
|
impl<T: Send + 'static> Drop for Packet<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Note that this load is not only an assert for correctness about
|
// Note that this load is not only an assert for correctness about
|
||||||
// disconnection, but also a proper fence before the read of
|
// disconnection, but also a proper fence before the read of
|
||||||
|
|
|
@ -55,9 +55,9 @@ pub struct Packet<T> {
|
||||||
lock: Mutex<State<T>>,
|
lock: Mutex<State<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T:Send> Send for Packet<T> { }
|
unsafe impl<T: Send + 'static> Send for Packet<T> { }
|
||||||
|
|
||||||
unsafe impl<T:Send> Sync for Packet<T> { }
|
unsafe impl<T: Send + 'static> Sync for Packet<T> { }
|
||||||
|
|
||||||
struct State<T> {
|
struct State<T> {
|
||||||
disconnected: bool, // Is the channel disconnected yet?
|
disconnected: bool, // Is the channel disconnected yet?
|
||||||
|
@ -75,7 +75,7 @@ struct State<T> {
|
||||||
canceled: Option<&'static mut bool>,
|
canceled: Option<&'static mut bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T: Send> Send for State<T> {}
|
unsafe impl<T: Send + 'static> Send for State<T> {}
|
||||||
|
|
||||||
/// Possible flavors of threads who can be blocked on this channel.
|
/// Possible flavors of threads who can be blocked on this channel.
|
||||||
enum Blocker {
|
enum Blocker {
|
||||||
|
@ -113,7 +113,7 @@ pub enum Failure {
|
||||||
|
|
||||||
/// Atomically blocks the current thread, placing it into `slot`, unlocking `lock`
|
/// Atomically blocks the current thread, placing it into `slot`, unlocking `lock`
|
||||||
/// in the meantime. This re-locks the mutex upon returning.
|
/// in the meantime. This re-locks the mutex upon returning.
|
||||||
fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>,
|
fn wait<'a, 'b, T: Send + 'static>(lock: &'a Mutex<State<T>>,
|
||||||
mut guard: MutexGuard<'b, State<T>>,
|
mut guard: MutexGuard<'b, State<T>>,
|
||||||
f: fn(SignalToken) -> Blocker)
|
f: fn(SignalToken) -> Blocker)
|
||||||
-> MutexGuard<'a, State<T>>
|
-> MutexGuard<'a, State<T>>
|
||||||
|
@ -136,7 +136,7 @@ fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
|
||||||
token.signal();
|
token.signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Send> Packet<T> {
|
impl<T: Send + 'static> Packet<T> {
|
||||||
pub fn new(cap: uint) -> Packet<T> {
|
pub fn new(cap: uint) -> Packet<T> {
|
||||||
Packet {
|
Packet {
|
||||||
channels: AtomicUsize::new(1),
|
channels: AtomicUsize::new(1),
|
||||||
|
@ -412,7 +412,7 @@ impl<T: Send> Packet<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl<T: Send> Drop for Packet<T> {
|
impl<T: Send + 'static> Drop for Packet<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
assert_eq!(self.channels.load(Ordering::SeqCst), 0);
|
assert_eq!(self.channels.load(Ordering::SeqCst), 0);
|
||||||
let mut guard = self.lock.lock().unwrap();
|
let mut guard = self.lock.lock().unwrap();
|
||||||
|
|
|
@ -120,9 +120,9 @@ pub struct Mutex<T> {
|
||||||
data: UnsafeCell<T>,
|
data: UnsafeCell<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T:Send> Send for Mutex<T> { }
|
unsafe impl<T: Send + 'static> Send for Mutex<T> { }
|
||||||
|
|
||||||
unsafe impl<T:Send> Sync for Mutex<T> { }
|
unsafe impl<T: Send + 'static> Sync for Mutex<T> { }
|
||||||
|
|
||||||
/// The static mutex type is provided to allow for static allocation of mutexes.
|
/// The static mutex type is provided to allow for static allocation of mutexes.
|
||||||
///
|
///
|
||||||
|
@ -180,7 +180,7 @@ pub const MUTEX_INIT: StaticMutex = StaticMutex {
|
||||||
poison: poison::FLAG_INIT,
|
poison: poison::FLAG_INIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<T: Send> Mutex<T> {
|
impl<T: Send + 'static> Mutex<T> {
|
||||||
/// Creates a new mutex in an unlocked state ready for use.
|
/// Creates a new mutex in an unlocked state ready for use.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn new(t: T) -> Mutex<T> {
|
pub fn new(t: T) -> Mutex<T> {
|
||||||
|
@ -243,7 +243,7 @@ impl<T: Send> Mutex<T> {
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Send> Drop for Mutex<T> {
|
impl<T: Send + 'static> Drop for Mutex<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// This is actually safe b/c we know that there is no further usage of
|
// This is actually safe b/c we know that there is no further usage of
|
||||||
// this mutex (it's up to the user to arrange for a mutex to get
|
// this mutex (it's up to the user to arrange for a mutex to get
|
||||||
|
|
|
@ -24,12 +24,12 @@ use thread;
|
||||||
use thunk::Thunk;
|
use thunk::Thunk;
|
||||||
|
|
||||||
struct Sentinel<'a> {
|
struct Sentinel<'a> {
|
||||||
jobs: &'a Arc<Mutex<Receiver<Thunk>>>,
|
jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
|
||||||
active: bool
|
active: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Sentinel<'a> {
|
impl<'a> Sentinel<'a> {
|
||||||
fn new(jobs: &Arc<Mutex<Receiver<Thunk>>>) -> Sentinel {
|
fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>) -> Sentinel<'a> {
|
||||||
Sentinel {
|
Sentinel {
|
||||||
jobs: jobs,
|
jobs: jobs,
|
||||||
active: true
|
active: true
|
||||||
|
@ -80,7 +80,7 @@ pub struct TaskPool {
|
||||||
//
|
//
|
||||||
// This is the only such Sender, so when it is dropped all subthreads will
|
// This is the only such Sender, so when it is dropped all subthreads will
|
||||||
// quit.
|
// quit.
|
||||||
jobs: Sender<Thunk>
|
jobs: Sender<Thunk<'static>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaskPool {
|
impl TaskPool {
|
||||||
|
@ -105,13 +105,13 @@ impl TaskPool {
|
||||||
|
|
||||||
/// Executes the function `job` on a thread in the pool.
|
/// Executes the function `job` on a thread in the pool.
|
||||||
pub fn execute<F>(&self, job: F)
|
pub fn execute<F>(&self, job: F)
|
||||||
where F : FnOnce(), F : Send
|
where F : FnOnce(), F : Send + 'static
|
||||||
{
|
{
|
||||||
self.jobs.send(Thunk::new(job)).unwrap();
|
self.jobs.send(Thunk::new(job)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) {
|
fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>) {
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
// Will spawn a new thread on panic unless it is cancelled.
|
// Will spawn a new thread on panic unless it is cancelled.
|
||||||
let sentinel = Sentinel::new(&jobs);
|
let sentinel = Sentinel::new(&jobs);
|
||||||
|
|
|
@ -81,7 +81,7 @@ impl<M: Send> Helper<M> {
|
||||||
///
|
///
|
||||||
/// This function is safe to be called many times.
|
/// This function is safe to be called many times.
|
||||||
pub fn boot<T, F>(&'static self, f: F, helper: fn(helper_signal::signal, Receiver<M>, T)) where
|
pub fn boot<T, F>(&'static self, f: F, helper: fn(helper_signal::signal, Receiver<M>, T)) where
|
||||||
T: Send,
|
T: Send + 'static,
|
||||||
F: FnOnce() -> T,
|
F: FnOnce() -> T,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -172,9 +172,9 @@ pub struct Builder {
|
||||||
// The size of the stack for the spawned thread
|
// The size of the stack for the spawned thread
|
||||||
stack_size: Option<uint>,
|
stack_size: Option<uint>,
|
||||||
// Thread-local stdout
|
// Thread-local stdout
|
||||||
stdout: Option<Box<Writer + Send>>,
|
stdout: Option<Box<Writer + Send + 'static>>,
|
||||||
// Thread-local stderr
|
// Thread-local stderr
|
||||||
stderr: Option<Box<Writer + Send>>,
|
stderr: Option<Box<Writer + Send + 'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
|
@ -208,7 +208,7 @@ impl Builder {
|
||||||
/// Redirect thread-local stdout.
|
/// Redirect thread-local stdout.
|
||||||
#[unstable(feature = "std_misc",
|
#[unstable(feature = "std_misc",
|
||||||
reason = "Will likely go away after proc removal")]
|
reason = "Will likely go away after proc removal")]
|
||||||
pub fn stdout(mut self, stdout: Box<Writer + Send>) -> Builder {
|
pub fn stdout(mut self, stdout: Box<Writer + Send + 'static>) -> Builder {
|
||||||
self.stdout = Some(stdout);
|
self.stdout = Some(stdout);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ impl Builder {
|
||||||
/// Redirect thread-local stderr.
|
/// Redirect thread-local stderr.
|
||||||
#[unstable(feature = "std_misc",
|
#[unstable(feature = "std_misc",
|
||||||
reason = "Will likely go away after proc removal")]
|
reason = "Will likely go away after proc removal")]
|
||||||
pub fn stderr(mut self, stderr: Box<Writer + Send>) -> Builder {
|
pub fn stderr(mut self, stderr: Box<Writer + Send + 'static>) -> Builder {
|
||||||
self.stderr = Some(stderr);
|
self.stderr = Some(stderr);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -565,11 +565,11 @@ impl thread_info::NewThread for Thread {
|
||||||
///
|
///
|
||||||
/// A thread that completes without panicking is considered to exit successfully.
|
/// A thread that completes without panicking is considered to exit successfully.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub type Result<T> = ::result::Result<T, Box<Any + Send>>;
|
pub type Result<T> = ::result::Result<T, Box<Any + Send + 'static>>;
|
||||||
|
|
||||||
struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
|
struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
|
||||||
|
|
||||||
unsafe impl<T:'static+Send> Send for Packet<T> {}
|
unsafe impl<T:Send> Send for Packet<T> {}
|
||||||
unsafe impl<T> Sync for Packet<T> {}
|
unsafe impl<T> Sync for Packet<T> {}
|
||||||
|
|
||||||
/// Inner representation for JoinHandle and JoinGuard
|
/// Inner representation for JoinHandle and JoinGuard
|
||||||
|
@ -804,7 +804,7 @@ mod test {
|
||||||
rx.recv().unwrap();
|
rx.recv().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk) {
|
fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk<'static>) {
|
||||||
let (tx, rx) = channel::<uint>();
|
let (tx, rx) = channel::<uint>();
|
||||||
|
|
||||||
let x = box 1;
|
let x = box 1;
|
||||||
|
@ -851,7 +851,7 @@ mod test {
|
||||||
// (well, it would if the constant were 8000+ - I lowered it to be more
|
// (well, it would if the constant were 8000+ - I lowered it to be more
|
||||||
// valgrind-friendly. try this at home, instead..!)
|
// valgrind-friendly. try this at home, instead..!)
|
||||||
static GENERATIONS: uint = 16;
|
static GENERATIONS: uint = 16;
|
||||||
fn child_no(x: uint) -> Thunk {
|
fn child_no(x: uint) -> Thunk<'static> {
|
||||||
return Thunk::new(move|| {
|
return Thunk::new(move|| {
|
||||||
if x < GENERATIONS {
|
if x < GENERATIONS {
|
||||||
thread::spawn(move|| child_no(x+1).invoke(()));
|
thread::spawn(move|| child_no(x+1).invoke(()));
|
||||||
|
|
|
@ -16,21 +16,24 @@ use alloc::boxed::Box;
|
||||||
use core::marker::Send;
|
use core::marker::Send;
|
||||||
use core::ops::FnOnce;
|
use core::ops::FnOnce;
|
||||||
|
|
||||||
pub struct Thunk<A=(),R=()> {
|
pub struct Thunk<'a, A=(),R=()> {
|
||||||
invoke: Box<Invoke<A,R>+Send>
|
#[cfg(stage0)] // // SNAP ac134f7 remove after stage0
|
||||||
|
invoke: Box<Invoke<A,R>+Send>,
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
invoke: Box<Invoke<A,R>+Send + 'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> Thunk<(),R> {
|
impl<'a, R> Thunk<'a,(),R> {
|
||||||
pub fn new<F>(func: F) -> Thunk<(),R>
|
pub fn new<F>(func: F) -> Thunk<'a,(),R>
|
||||||
where F : FnOnce() -> R, F : Send
|
where F : FnOnce() -> R, F : Send + 'a
|
||||||
{
|
{
|
||||||
Thunk::with_arg(move|()| func())
|
Thunk::with_arg(move|()| func())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A,R> Thunk<A,R> {
|
impl<'a,A,R> Thunk<'a,A,R> {
|
||||||
pub fn with_arg<F>(func: F) -> Thunk<A,R>
|
pub fn with_arg<F>(func: F) -> Thunk<'a,A,R>
|
||||||
where F : FnOnce(A) -> R, F : Send
|
where F : FnOnce(A) -> R, F : Send + 'a
|
||||||
{
|
{
|
||||||
Thunk {
|
Thunk {
|
||||||
invoke: box func
|
invoke: box func
|
||||||
|
|
|
@ -72,7 +72,7 @@ pub struct TerminfoTerminal<T> {
|
||||||
ti: Box<TermInfo>
|
ti: Box<TermInfo>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
|
impl<T: Writer+Send+'static> Terminal<T> for TerminfoTerminal<T> {
|
||||||
fn fg(&mut self, color: color::Color) -> IoResult<bool> {
|
fn fg(&mut self, color: color::Color) -> IoResult<bool> {
|
||||||
let color = self.dim_if_necessary(color);
|
let color = self.dim_if_necessary(color);
|
||||||
if self.num_colors > color {
|
if self.num_colors > color {
|
||||||
|
@ -164,11 +164,11 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
|
||||||
fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.out }
|
fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.out }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Writer+Send> UnwrappableTerminal<T> for TerminfoTerminal<T> {
|
impl<T: Writer+Send+'static> UnwrappableTerminal<T> for TerminfoTerminal<T> {
|
||||||
fn unwrap(self) -> T { self.out }
|
fn unwrap(self) -> T { self.out }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Writer+Send> TerminfoTerminal<T> {
|
impl<T: Writer+Send+'static> TerminfoTerminal<T> {
|
||||||
/// Returns `None` whenever the terminal cannot be created for some
|
/// Returns `None` whenever the terminal cannot be created for some
|
||||||
/// reason.
|
/// reason.
|
||||||
pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
|
pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
|
||||||
|
@ -229,4 +229,3 @@ impl<T: Writer> Writer for TerminfoTerminal<T> {
|
||||||
self.out.flush()
|
self.out.flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ fn bits_to_color(bits: u16) -> color::Color {
|
||||||
color | (bits & 0x8) // copy the hi-intensity bit
|
color | (bits & 0x8) // copy the hi-intensity bit
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Writer+Send> WinConsole<T> {
|
impl<T: Writer+Send+'static> WinConsole<T> {
|
||||||
fn apply(&mut self) {
|
fn apply(&mut self) {
|
||||||
let _unused = self.buf.flush();
|
let _unused = self.buf.flush();
|
||||||
let mut accum: libc::WORD = 0;
|
let mut accum: libc::WORD = 0;
|
||||||
|
@ -139,7 +139,7 @@ impl<T: Writer> Writer for WinConsole<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Writer+Send> Terminal<T> for WinConsole<T> {
|
impl<T: Writer+Send+'static> Terminal<T> for WinConsole<T> {
|
||||||
fn fg(&mut self, color: color::Color) -> IoResult<bool> {
|
fn fg(&mut self, color: color::Color) -> IoResult<bool> {
|
||||||
self.foreground = color;
|
self.foreground = color;
|
||||||
self.apply();
|
self.apply();
|
||||||
|
@ -192,6 +192,6 @@ impl<T: Writer+Send> Terminal<T> for WinConsole<T> {
|
||||||
fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
|
fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Writer+Send> UnwrappableTerminal<T> for WinConsole<T> {
|
impl<T: Writer+Send+'static> UnwrappableTerminal<T> for WinConsole<T> {
|
||||||
fn unwrap(self) -> T { self.buf }
|
fn unwrap(self) -> T { self.buf }
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ pub enum TestFn {
|
||||||
StaticTestFn(fn()),
|
StaticTestFn(fn()),
|
||||||
StaticBenchFn(fn(&mut Bencher)),
|
StaticBenchFn(fn(&mut Bencher)),
|
||||||
StaticMetricFn(fn(&mut MetricMap)),
|
StaticMetricFn(fn(&mut MetricMap)),
|
||||||
DynTestFn(Thunk),
|
DynTestFn(Thunk<'static>),
|
||||||
DynMetricFn(Box<for<'a> Invoke<&'a mut MetricMap>+'static>),
|
DynMetricFn(Box<for<'a> Invoke<&'a mut MetricMap>+'static>),
|
||||||
DynBenchFn(Box<TDynBenchFn+'static>)
|
DynBenchFn(Box<TDynBenchFn+'static>)
|
||||||
}
|
}
|
||||||
|
@ -878,7 +878,7 @@ pub fn run_test(opts: &TestOpts,
|
||||||
fn run_test_inner(desc: TestDesc,
|
fn run_test_inner(desc: TestDesc,
|
||||||
monitor_ch: Sender<MonitorMsg>,
|
monitor_ch: Sender<MonitorMsg>,
|
||||||
nocapture: bool,
|
nocapture: bool,
|
||||||
testfn: Thunk) {
|
testfn: Thunk<'static>) {
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let mut reader = ChanReader::new(rx);
|
let mut reader = ChanReader::new(rx);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::sync::mpsc::{Receiver, channel};
|
use std::sync::mpsc::{Receiver, channel};
|
||||||
|
|
||||||
pub fn foo<T:Send + Clone>(x: T) -> Receiver<T> {
|
pub fn foo<T:'static + Send + Clone>(x: T) -> Receiver<T> {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
thread::spawn(move|| {
|
thread::spawn(move|| {
|
||||||
tx.send(x.clone());
|
tx.send(x.clone());
|
||||||
|
|
|
@ -229,21 +229,12 @@ unsafe impl<T: 'static> Send for Racy<T> {}
|
||||||
|
|
||||||
/// Executes a closure in parallel over the given iterator over mutable slice.
|
/// Executes a closure in parallel over the given iterator over mutable slice.
|
||||||
/// The closure `f` is run in parallel with an element of `iter`.
|
/// The closure `f` is run in parallel with an element of `iter`.
|
||||||
fn parallel<'a, I, T, F>(iter: I, f: F)
|
fn parallel<'a, I: Iterator, F>(iter: I, ref f: F)
|
||||||
where T: 'a+Send + Sync,
|
where I::Item: Send + 'a,
|
||||||
I: Iterator<Item=&'a mut [T]>,
|
F: Fn(I::Item) + Sync + 'a {
|
||||||
F: Fn(&mut [T]) + Sync {
|
iter.map(|x| {
|
||||||
use std::mem;
|
thread::scoped(move|| {
|
||||||
use std::raw::Repr;
|
f(x)
|
||||||
|
|
||||||
iter.map(|chunk| {
|
|
||||||
// Need to convert `f` and `chunk` to something that can cross the task
|
|
||||||
// boundary.
|
|
||||||
let f = Racy(&f as *const F as *const uint);
|
|
||||||
let raw = Racy(chunk.repr());
|
|
||||||
thread::spawn(move|| {
|
|
||||||
let f = f.0 as *const F;
|
|
||||||
unsafe { (*f)(mem::transmute(raw.0)) }
|
|
||||||
})
|
})
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,26 +112,16 @@ fn dot(v: &[f64], u: &[f64]) -> f64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Racy<T>(T);
|
|
||||||
|
|
||||||
unsafe impl<T: 'static> Send for Racy<T> {}
|
|
||||||
|
|
||||||
// Executes a closure in parallel over the given mutable slice. The closure `f`
|
// Executes a closure in parallel over the given mutable slice. The closure `f`
|
||||||
// is run in parallel and yielded the starting index within `v` as well as a
|
// is run in parallel and yielded the starting index within `v` as well as a
|
||||||
// sub-slice of `v`.
|
// sub-slice of `v`.
|
||||||
fn parallel<T, F>(v: &mut [T], f: F)
|
fn parallel<'a,T, F>(v: &mut [T], ref f: F)
|
||||||
where T: Send + Sync,
|
where T: Send + Sync + 'a,
|
||||||
F: Fn(uint, &mut [T]) + Sync {
|
F: Fn(uint, &mut [T]) + Sync + 'a {
|
||||||
let size = v.len() / os::num_cpus() + 1;
|
let size = v.len() / os::num_cpus() + 1;
|
||||||
|
|
||||||
v.chunks_mut(size).enumerate().map(|(i, chunk)| {
|
v.chunks_mut(size).enumerate().map(|(i, chunk)| {
|
||||||
// Need to convert `f` and `chunk` to something that can cross the task
|
thread::scoped(move|| {
|
||||||
// boundary.
|
f(i * size, chunk)
|
||||||
let f = Racy(&f as *const _ as *const uint);
|
|
||||||
let raw = Racy(chunk.repr());
|
|
||||||
thread::spawn(move|| {
|
|
||||||
let f = f.0 as *const F;
|
|
||||||
unsafe { (*f)(i * size, mem::transmute(raw.0)) }
|
|
||||||
})
|
})
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
trait Foo : Send { }
|
trait Foo : Send { }
|
||||||
|
|
||||||
impl <'a> Foo for &'a mut () { }
|
impl Foo for std::rc::Rc<i8> { }
|
||||||
//~^ ERROR the type `&'a mut ()` does not fulfill the required lifetime
|
//~^ ERROR the trait `core::marker::Send` is not implemented
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(optin_builtin_traits)]
|
||||||
|
|
||||||
use std::marker::Send;
|
use std::marker::Send;
|
||||||
|
|
||||||
enum TestE {
|
enum TestE {
|
||||||
|
@ -16,18 +18,21 @@ enum TestE {
|
||||||
|
|
||||||
struct MyType;
|
struct MyType;
|
||||||
|
|
||||||
|
struct NotSync;
|
||||||
|
impl !Sync for NotSync {}
|
||||||
|
|
||||||
unsafe impl Send for TestE {}
|
unsafe impl Send for TestE {}
|
||||||
unsafe impl Send for MyType {}
|
unsafe impl Send for MyType {}
|
||||||
unsafe impl Send for (MyType, MyType) {}
|
unsafe impl Send for (MyType, MyType) {}
|
||||||
//~^ ERROR builtin traits can only be implemented on structs or enums
|
//~^ ERROR builtin traits can only be implemented on structs or enums
|
||||||
|
|
||||||
unsafe impl Send for &'static MyType {}
|
unsafe impl Send for &'static NotSync {}
|
||||||
//~^ ERROR builtin traits can only be implemented on structs or enums
|
//~^ ERROR builtin traits can only be implemented on structs or enums
|
||||||
|
|
||||||
unsafe impl Send for [MyType] {}
|
unsafe impl Send for [MyType] {}
|
||||||
//~^ ERROR builtin traits can only be implemented on structs or enums
|
//~^ ERROR builtin traits can only be implemented on structs or enums
|
||||||
|
|
||||||
unsafe impl Send for &'static [MyType] {}
|
unsafe impl Send for &'static [NotSync] {}
|
||||||
//~^ ERROR builtin traits can only be implemented on structs or enums
|
//~^ ERROR builtin traits can only be implemented on structs or enums
|
||||||
|
|
||||||
fn is_send<T: Send>() {}
|
fn is_send<T: Send>() {}
|
||||||
|
|
|
@ -17,7 +17,7 @@ struct S<T>;
|
||||||
|
|
||||||
trait Gettable<T> {}
|
trait Gettable<T> {}
|
||||||
|
|
||||||
impl<T: Send + Copy> Gettable<T> for S<T> {}
|
impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
|
||||||
|
|
||||||
fn f<T>(val: T) {
|
fn f<T>(val: T) {
|
||||||
let t: S<T> = S;
|
let t: S<T> = S;
|
||||||
|
|
|
@ -20,7 +20,7 @@ trait Message : Send { }
|
||||||
|
|
||||||
fn object_ref_with_static_bound_not_ok() {
|
fn object_ref_with_static_bound_not_ok() {
|
||||||
assert_send::<&'static (Dummy+'static)>();
|
assert_send::<&'static (Dummy+'static)>();
|
||||||
//~^ ERROR the trait `core::marker::Send` is not implemented
|
//~^ ERROR the trait `core::marker::Sync` is not implemented
|
||||||
}
|
}
|
||||||
|
|
||||||
fn box_object_with_no_bound_not_ok<'a>() {
|
fn box_object_with_no_bound_not_ok<'a>() {
|
||||||
|
@ -28,7 +28,7 @@ fn box_object_with_no_bound_not_ok<'a>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn object_with_send_bound_ok() {
|
fn object_with_send_bound_ok() {
|
||||||
assert_send::<&'static (Dummy+Send)>();
|
assert_send::<&'static (Dummy+Sync)>();
|
||||||
assert_send::<Box<Dummy+Send>>();
|
assert_send::<Box<Dummy+Send>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,22 +12,22 @@
|
||||||
// is broken into two parts because some errors occur in distinct
|
// is broken into two parts because some errors occur in distinct
|
||||||
// phases in the compiler. See kindck-send-object2.rs as well!
|
// phases in the compiler. See kindck-send-object2.rs as well!
|
||||||
|
|
||||||
fn assert_send<T:Send>() { }
|
fn assert_send<T:Send+'static>() { }
|
||||||
trait Dummy { }
|
trait Dummy { }
|
||||||
|
|
||||||
// careful with object types, who knows what they close over...
|
// careful with object types, who knows what they close over...
|
||||||
fn test51<'a>() {
|
fn test51<'a>() {
|
||||||
assert_send::<&'a Dummy>();
|
assert_send::<&'a Dummy>();
|
||||||
//~^ ERROR the trait `core::marker::Send` is not implemented
|
//~^ ERROR the trait `core::marker::Sync` is not implemented
|
||||||
}
|
}
|
||||||
fn test52<'a>() {
|
fn test52<'a>() {
|
||||||
assert_send::<&'a (Dummy+Send)>();
|
assert_send::<&'a (Dummy+Sync)>();
|
||||||
//~^ ERROR does not fulfill the required lifetime
|
//~^ ERROR does not fulfill the required lifetime
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...unless they are properly bounded
|
// ...unless they are properly bounded
|
||||||
fn test60() {
|
fn test60() {
|
||||||
assert_send::<&'static (Dummy+Send)>();
|
assert_send::<&'static (Dummy+Sync)>();
|
||||||
}
|
}
|
||||||
fn test61() {
|
fn test61() {
|
||||||
assert_send::<Box<Dummy+Send>>();
|
assert_send::<Box<Dummy+Send>>();
|
||||||
|
|
|
@ -14,7 +14,7 @@ fn assert_send<T:Send>() { }
|
||||||
trait Dummy { }
|
trait Dummy { }
|
||||||
|
|
||||||
fn test50() {
|
fn test50() {
|
||||||
assert_send::<&'static Dummy>(); //~ ERROR the trait `core::marker::Send` is not implemented
|
assert_send::<&'static Dummy>(); //~ ERROR the trait `core::marker::Sync` is not implemented
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test53() {
|
fn test53() {
|
||||||
|
@ -23,7 +23,7 @@ fn test53() {
|
||||||
|
|
||||||
// ...unless they are properly bounded
|
// ...unless they are properly bounded
|
||||||
fn test60() {
|
fn test60() {
|
||||||
assert_send::<&'static (Dummy+Send)>();
|
assert_send::<&'static (Dummy+Sync)>();
|
||||||
}
|
}
|
||||||
fn test61() {
|
fn test61() {
|
||||||
assert_send::<Box<Dummy+Send>>();
|
assert_send::<Box<Dummy+Send>>();
|
||||||
|
|
|
@ -18,8 +18,8 @@ fn test31() { assert_send::<String>(); }
|
||||||
fn test32() { assert_send::<Vec<isize> >(); }
|
fn test32() { assert_send::<Vec<isize> >(); }
|
||||||
|
|
||||||
// but not if they own a bad thing
|
// but not if they own a bad thing
|
||||||
fn test40<'a>(_: &'a isize) {
|
fn test40() {
|
||||||
assert_send::<Box<&'a isize>>(); //~ ERROR does not fulfill the required lifetime
|
assert_send::<Box<*mut u8>>(); //~ ERROR `core::marker::Send` is not implemented
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
// Copyright 2014 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.
|
|
||||||
|
|
||||||
// Test that borrowed pointers are not sendable unless 'static.
|
|
||||||
|
|
||||||
fn assert_send<T:Send>() { }
|
|
||||||
|
|
||||||
// lifetime pointers with 'static lifetime are ok
|
|
||||||
fn test01() { assert_send::<&'static isize>(); }
|
|
||||||
fn test02() { assert_send::<&'static str>(); }
|
|
||||||
fn test03() { assert_send::<&'static [isize]>(); }
|
|
||||||
|
|
||||||
// whether or not they are mutable
|
|
||||||
fn test10() { assert_send::<&'static mut isize>(); }
|
|
||||||
|
|
||||||
// otherwise lifetime pointers are not ok
|
|
||||||
fn test20<'a>(_: &'a isize) {
|
|
||||||
assert_send::<&'a isize>(); //~ ERROR does not fulfill the required lifetime
|
|
||||||
}
|
|
||||||
fn test21<'a>(_: &'a isize) {
|
|
||||||
assert_send::<&'a str>(); //~ ERROR does not fulfill the required lifetime
|
|
||||||
}
|
|
||||||
fn test22<'a>(_: &'a isize) {
|
|
||||||
assert_send::<&'a [isize]>(); //~ ERROR does not fulfill the required lifetime
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() { }
|
|
|
@ -1,83 +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.
|
|
||||||
|
|
||||||
// Test which of the builtin types are considered sendable. The tests
|
|
||||||
// in this file all test region bound and lifetime violations that are
|
|
||||||
// detected during type check.
|
|
||||||
|
|
||||||
extern crate core;
|
|
||||||
use core::ptr::Unique;
|
|
||||||
|
|
||||||
fn assert_send<T:Send>() { }
|
|
||||||
trait Dummy:Send { }
|
|
||||||
|
|
||||||
// lifetime pointers with 'static lifetime are ok
|
|
||||||
|
|
||||||
fn static_lifime_ok<'a,T,U:Send>(_: &'a isize) {
|
|
||||||
assert_send::<&'static isize>();
|
|
||||||
assert_send::<&'static str>();
|
|
||||||
assert_send::<&'static [isize]>();
|
|
||||||
|
|
||||||
// whether or not they are mutable
|
|
||||||
assert_send::<&'static mut isize>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise lifetime pointers are not ok
|
|
||||||
|
|
||||||
fn param_not_ok<'a>(x: &'a isize) {
|
|
||||||
assert_send::<&'a isize>(); //~ ERROR does not fulfill the required lifetime
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_not_ok1<'a>(_: &'a isize) {
|
|
||||||
assert_send::<&'a str>(); //~ ERROR does not fulfill the required lifetime
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_not_ok2<'a>(_: &'a isize) {
|
|
||||||
assert_send::<&'a [isize]>(); //~ ERROR does not fulfill the required lifetime
|
|
||||||
}
|
|
||||||
|
|
||||||
// boxes are ok
|
|
||||||
|
|
||||||
fn box_ok() {
|
|
||||||
assert_send::<Box<isize>>();
|
|
||||||
assert_send::<String>();
|
|
||||||
assert_send::<Vec<isize>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// but not if they own a bad thing
|
|
||||||
|
|
||||||
fn box_with_region_not_ok<'a>() {
|
|
||||||
assert_send::<Box<&'a isize>>(); //~ ERROR does not fulfill the required lifetime
|
|
||||||
}
|
|
||||||
|
|
||||||
// objects with insufficient bounds no ok
|
|
||||||
|
|
||||||
fn object_with_random_bound_not_ok<'a>() {
|
|
||||||
assert_send::<&'a (Dummy+'a)>();
|
|
||||||
//~^ ERROR reference has a longer lifetime
|
|
||||||
}
|
|
||||||
|
|
||||||
fn object_with_send_bound_not_ok<'a>() {
|
|
||||||
assert_send::<&'a (Dummy+Send)>();
|
|
||||||
//~^ ERROR does not fulfill the required lifetime
|
|
||||||
}
|
|
||||||
|
|
||||||
// unsafe pointers are ok unless they point at unsendable things
|
|
||||||
|
|
||||||
struct UniqueUnsafePtr(Unique<*const isize>);
|
|
||||||
|
|
||||||
unsafe impl Send for UniqueUnsafePtr {}
|
|
||||||
|
|
||||||
fn unsafe_ok1<'a>(_: &'a isize) {
|
|
||||||
assert_send::<UniqueUnsafePtr>();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
}
|
|
|
@ -8,11 +8,11 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
fn assert_send<T: Send>(_t: T) {}
|
fn assert_static<T: 'static>(_t: T) {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let line = String::new();
|
let line = String::new();
|
||||||
match [&*line] { //~ ERROR `line` does not live long enough
|
match [&*line] { //~ ERROR `line` does not live long enough
|
||||||
[ word ] => { assert_send(word); }
|
[ word ] => { assert_static(word); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
src/test/compile-fail/send-is-not-static-ensures-scoping.rs
Executable file
25
src/test/compile-fail/send-is-not-static-ensures-scoping.rs
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
#![feature(core, std_misc)]
|
||||||
|
use std::thread::Thread;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let bad = {
|
||||||
|
let x = 1;
|
||||||
|
let y = &x;
|
||||||
|
|
||||||
|
Thread::scoped(|| { //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
let _z = y;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
bad.join().ok().unwrap();
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ fn c(x: Box<Foo+Sync+Send>) {
|
||||||
fn d(x: Box<Foo>) {
|
fn d(x: Box<Foo>) {
|
||||||
a(x); //~ ERROR mismatched types
|
a(x); //~ ERROR mismatched types
|
||||||
//~| expected `Box<Foo + Send>`
|
//~| expected `Box<Foo + Send>`
|
||||||
//~| found `Box<Foo + 'static>`
|
//~| found `Box<Foo>`
|
||||||
//~| expected bounds `Send`
|
//~| expected bounds `Send`
|
||||||
//~| found no bounds
|
//~| found no bounds
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ trait Foo : Bar { }
|
||||||
impl <T: Send> Foo for T { }
|
impl <T: Send> Foo for T { }
|
||||||
impl <T: Send> Bar for T { }
|
impl <T: Send> Bar for T { }
|
||||||
|
|
||||||
fn foo<T: Foo>(val: T, chan: Sender<T>) {
|
fn foo<T: Foo + 'static>(val: T, chan: Sender<T>) {
|
||||||
chan.send(val).unwrap();
|
chan.send(val).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ struct X<T>(T);
|
||||||
impl <T: Sync> RequiresShare for X<T> { }
|
impl <T: Sync> RequiresShare for X<T> { }
|
||||||
impl <T: Sync+Send> RequiresRequiresShareAndSend for X<T> { }
|
impl <T: Sync+Send> RequiresRequiresShareAndSend for X<T> { }
|
||||||
|
|
||||||
fn foo<T: RequiresRequiresShareAndSend>(val: T, chan: Sender<T>) {
|
fn foo<T: RequiresRequiresShareAndSend + 'static>(val: T, chan: Sender<T>) {
|
||||||
chan.send(val).unwrap();
|
chan.send(val).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ trait Foo : Send { }
|
||||||
|
|
||||||
impl <T: Send> Foo for T { }
|
impl <T: Send> Foo for T { }
|
||||||
|
|
||||||
fn foo<T: Foo>(val: T, chan: Sender<T>) {
|
fn foo<T: Foo + 'static>(val: T, chan: Sender<T>) {
|
||||||
chan.send(val).unwrap();
|
chan.send(val).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
|
|
||||||
use std::sync::mpsc::{Sender, channel};
|
use std::sync::mpsc::{Sender, channel};
|
||||||
|
|
||||||
trait Foo : Send + Sized {
|
trait Foo : Send + Sized + 'static {
|
||||||
fn foo(self, tx: Sender<Self>) {
|
fn foo(self, tx: Sender<Self>) {
|
||||||
tx.send(self).unwrap();
|
tx.send(self).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: Send> Foo for T { }
|
impl <T: Send + 'static> Foo for T { }
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
|
|
|
@ -14,12 +14,12 @@ use std::thunk::Thunk;
|
||||||
|
|
||||||
pub trait Promisable: Send + Sync {}
|
pub trait Promisable: Send + Sync {}
|
||||||
impl<T: Send + Sync> Promisable for T {}
|
impl<T: Send + Sync> Promisable for T {}
|
||||||
pub fn propagate<T, E, F, G>(action: F) -> Thunk<Result<T, E>, Result<T, E>>
|
pub fn propagate<'a, T, E, F, G>(action: F) -> Thunk<'a,Result<T, E>, Result<T, E>>
|
||||||
where
|
where
|
||||||
T: Promisable + Clone,
|
T: Promisable + Clone + 'a,
|
||||||
E: Promisable + Clone,
|
E: Promisable + Clone + 'a,
|
||||||
F: FnOnce(&T) -> Result<T, E> + Send,
|
F: FnOnce(&T) -> Result<T, E> + Send + 'a,
|
||||||
G: FnOnce(Result<T, E>) -> Result<T, E> {
|
G: FnOnce(Result<T, E>) -> Result<T, E> + 'a {
|
||||||
Thunk::with_arg(move |result: Result<T, E>| {
|
Thunk::with_arg(move |result: Result<T, E>| {
|
||||||
match result {
|
match result {
|
||||||
Ok(ref t) => action(t),
|
Ok(ref t) => action(t),
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct DST { a: u32, b: str }
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// get_tydesc should support unsized types
|
// get_tydesc should support unsized types
|
||||||
assert!(unsafe {(
|
assert_eq!(unsafe {(
|
||||||
// Slice
|
// Slice
|
||||||
(*std::intrinsics::get_tydesc::<[u8]>()).name,
|
(*std::intrinsics::get_tydesc::<[u8]>()).name,
|
||||||
// str
|
// str
|
||||||
|
@ -25,5 +25,5 @@ fn main() {
|
||||||
(*std::intrinsics::get_tydesc::<NT>()).name,
|
(*std::intrinsics::get_tydesc::<NT>()).name,
|
||||||
// DST
|
// DST
|
||||||
(*std::intrinsics::get_tydesc::<DST>()).name
|
(*std::intrinsics::get_tydesc::<DST>()).name
|
||||||
)} == ("[u8]", "str", "core::marker::Copy + 'static", "NT", "DST"));
|
)}, ("[u8]", "str", "core::marker::Copy", "NT", "DST"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,11 @@ use std::thunk::Thunk;
|
||||||
|
|
||||||
static generations: uint = 1024+256+128+49;
|
static generations: uint = 1024+256+128+49;
|
||||||
|
|
||||||
fn spawn(f: Thunk) {
|
fn spawn(f: Thunk<'static>) {
|
||||||
Builder::new().stack_size(32 * 1024).spawn(move|| f.invoke(()));
|
Builder::new().stack_size(32 * 1024).spawn(move|| f.invoke(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn child_no(x: uint) -> Thunk {
|
fn child_no(x: uint) -> Thunk<'static> {
|
||||||
Thunk::new(move|| {
|
Thunk::new(move|| {
|
||||||
if x < generations {
|
if x < generations {
|
||||||
spawn(child_no(x+1));
|
spawn(child_no(x+1));
|
||||||
|
|
47
src/test/run-pass/send-is-not-static-par-for.rs
Executable file
47
src/test/run-pass/send-is-not-static-par-for.rs
Executable file
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
#![feature(core, std_misc)]
|
||||||
|
use std::thread::Thread;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
fn par_for<I, F>(iter: I, f: F)
|
||||||
|
where I: Iterator,
|
||||||
|
<I as Iterator>::Item: Send,
|
||||||
|
F: Fn(<I as Iterator>::Item) + Sync
|
||||||
|
{
|
||||||
|
let f = &f;
|
||||||
|
let _guards: Vec<_> = iter.map(|elem| {
|
||||||
|
Thread::scoped(move || {
|
||||||
|
f(elem)
|
||||||
|
})
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sum(x: &[i32]) {
|
||||||
|
let sum_lengths = Mutex::new(0);
|
||||||
|
par_for(x.windows(4), |x| {
|
||||||
|
*sum_lengths.lock().unwrap() += x.len()
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(*sum_lengths.lock().unwrap(), (x.len() - 3) * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut elements = [0; 20];
|
||||||
|
|
||||||
|
// iterators over references into this stack frame
|
||||||
|
par_for(elements.iter_mut().enumerate(), |(i, x)| {
|
||||||
|
*x = i as i32
|
||||||
|
});
|
||||||
|
|
||||||
|
sum(&elements)
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ struct Command<K, V> {
|
||||||
val: V
|
val: V
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cache_server<K:Send,V:Send>(mut tx: Sender<Sender<Command<K, V>>>) {
|
fn cache_server<K:Send+'static,V:Send+'static>(mut tx: Sender<Sender<Command<K, V>>>) {
|
||||||
let (tx1, _rx) = channel();
|
let (tx1, _rx) = channel();
|
||||||
tx.send(tx1);
|
tx.send(tx1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue