Skip to content

Commit

Permalink
rollup merge of rust-lang#22319: huonw/send-is-not-static
Browse files Browse the repository at this point in the history
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
  • Loading branch information
alexcrichton committed Feb 18, 2015
2 parents 6ac3799 + 7a14f49 commit ba8ce4c
Show file tree
Hide file tree
Showing 49 changed files with 231 additions and 297 deletions.
18 changes: 18 additions & 0 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,19 @@ use clone::Clone;
reason = "will be overhauled with new lifetime rules; see RFC 458")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[cfg(stage0)] // SNAP ac134f7 remove after stage0
pub unsafe trait Send: 'static {
// 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.
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -424,3 +434,11 @@ pub struct NoCopy;
#[lang="managed_bound"]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
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 {}
}
32 changes: 3 additions & 29 deletions src/librustc/middle/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use self::EvaluationResult::*;
use super::{DerivedObligationCause};
use super::{project};
use super::project::Normalized;
use super::{PredicateObligation, Obligation, TraitObligation, ObligationCause};
use super::{PredicateObligation, TraitObligation, ObligationCause};
use super::{ObligationCauseCode, BuiltinDerivedObligation};
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
use super::{Selection};
Expand All @@ -34,7 +34,7 @@ use super::{util};
use middle::fast_reject;
use middle::mem_categorization::Typer;
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::{InferCtxt, TypeFreshener};
use middle::ty_fold::TypeFoldable;
Expand Down Expand Up @@ -1459,22 +1459,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

ty::BoundSync |
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]))
}
}
Expand Down Expand Up @@ -1817,21 +1801,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
})
}).collect::<Result<_, _>>();
let mut obligations = match obligations {
let obligations = match obligations {
Ok(o) => o,
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());

debug!("vtable_builtin_data: obligations={}",
Expand Down
5 changes: 2 additions & 3 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,9 +697,8 @@ impl<'tcx> UserString<'tcx> for ty::TyTrait<'tcx> {
}

// Region, if not obviously implied by builtin bounds.
if bounds.region_bound != ty::ReStatic ||
!bounds.builtin_bounds.contains(&ty::BoundSend)
{ // Region bound is implied by builtin bounds:
if bounds.region_bound != ty::ReStatic {
// Region bound is implied by builtin bounds:
components.push(bounds.region_bound.user_string(tcx));
}

Expand Down
2 changes: 1 addition & 1 deletion src/libstd/old_io/net/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ mod tests {

pub fn smalltest<F,G>(server: F, client: G)
where F : FnOnce(UnixStream), F : Send,
G : FnOnce(UnixStream), G : Send
G : FnOnce(UnixStream), G : Send + 'static
{
let path1 = next_test_unix();
let path2 = path1.clone();
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ impl Child {
/// the parent waits for the child to exit.
pub fn wait_with_output(mut self) -> io::Result<Output> {
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();
match stream {
Some(stream) => {
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/rt/at_exit_imp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use mem;
use thunk::Thunk;
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
// on poisoning and this module needs to operate at a lower level than requiring
Expand Down Expand Up @@ -65,7 +65,7 @@ pub fn cleanup() {
}
}

pub fn push(f: Thunk) {
pub fn push(f: Thunk<'static>) {
unsafe {
LOCK.lock();
init();
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/rt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
/// 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));
}

Expand Down
4 changes: 2 additions & 2 deletions src/libstd/rt/unwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ use rt::libunwind as uw;

struct 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);
Expand Down Expand Up @@ -161,7 +161,7 @@ pub fn panicking() -> bool {
#[inline(never)]
#[no_mangle]
#[allow(private_no_mangle_fns)]
fn rust_panic(cause: Box<Any + Send>) -> ! {
fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
rtdebug!("begin_unwind()");

unsafe {
Expand Down
8 changes: 4 additions & 4 deletions src/libstd/sync/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub struct Future<A> {
}

enum FutureState<A> {
Pending(Thunk<(),A>),
Pending(Thunk<'static,(),A>),
Evaluating,
Forced(A)
}
Expand Down Expand Up @@ -103,7 +103,7 @@ impl<A> 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.
Expand All @@ -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> {
/*!
* Create a future from a port
Expand All @@ -132,7 +132,7 @@ impl<A:Send> 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.
Expand Down
30 changes: 15 additions & 15 deletions src/libstd/sync/mpsc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ pub struct Receiver<T> {

// The receiver port can be sent from place to place, so long as it
// 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
/// whenever `next` is called, waiting for a new message, and `None` will be
Expand All @@ -364,7 +364,7 @@ pub struct Sender<T> {

// The send port can be sent from place to place, so long as it
// 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
/// owned by one task, but it can be cloned to send to other tasks.
Expand All @@ -373,7 +373,7 @@ pub struct SyncSender<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> {}

Expand Down Expand Up @@ -485,7 +485,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
/// println!("{:?}", rx.recv().unwrap());
/// ```
#[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()));
(Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
}
Expand Down Expand Up @@ -525,7 +525,7 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
/// assert_eq!(rx.recv().unwrap(), 2);
/// ```
#[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)));
(SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
}
Expand All @@ -534,7 +534,7 @@ pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
// Sender
////////////////////////////////////////////////////////////////////////////////

impl<T: Send> Sender<T> {
impl<T: Send + 'static> Sender<T> {
fn new(inner: Flavor<T>) -> Sender<T> {
Sender {
inner: UnsafeCell::new(inner),
Expand Down Expand Up @@ -616,7 +616,7 @@ impl<T: Send> Sender<T> {
}

#[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> {
let (packet, sleeper, guard) = match *unsafe { self.inner() } {
Flavor::Oneshot(ref p) => {
Expand Down Expand Up @@ -662,7 +662,7 @@ impl<T: Send> Clone for Sender<T> {

#[unsafe_destructor]
#[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) {
match *unsafe { self.inner_mut() } {
Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
Expand All @@ -677,7 +677,7 @@ impl<T: Send> Drop for Sender<T> {
// SyncSender
////////////////////////////////////////////////////////////////////////////////

impl<T: Send> SyncSender<T> {
impl<T: Send + 'static> SyncSender<T> {
fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
SyncSender { inner: inner }
}
Expand Down Expand Up @@ -717,7 +717,7 @@ impl<T: Send> SyncSender<T> {
}

#[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> {
unsafe { (*self.inner.get()).clone_chan(); }
return SyncSender::new(self.inner.clone());
Expand All @@ -726,7 +726,7 @@ impl<T: Send> Clone for SyncSender<T> {

#[unsafe_destructor]
#[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) {
unsafe { (*self.inner.get()).drop_chan(); }
}
Expand All @@ -736,7 +736,7 @@ impl<T: Send> Drop for SyncSender<T> {
// Receiver
////////////////////////////////////////////////////////////////////////////////

impl<T: Send> Receiver<T> {
impl<T: Send + 'static> Receiver<T> {
fn new(inner: Flavor<T>) -> Receiver<T> {
Receiver { inner: UnsafeCell::new(inner) }
}
Expand Down Expand Up @@ -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 {
loop {
let new_port = match *unsafe { self.inner() } {
Expand Down Expand Up @@ -942,15 +942,15 @@ impl<T: Send> select::Packet for Receiver<T> {
}

#[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;

fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
}

#[unsafe_destructor]
#[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) {
match *unsafe { self.inner_mut() } {
Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
Expand Down
6 changes: 3 additions & 3 deletions src/libstd/sync/mpsc/mpsc_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub struct 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> {
unsafe fn new(v: Option<T>) -> *mut Node<T> {
Expand All @@ -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
/// one consumer.
pub fn new() -> Queue<T> {
Expand Down Expand Up @@ -140,7 +140,7 @@ impl<T: Send> Queue<T> {

#[unsafe_destructor]
#[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) {
unsafe {
let mut cur = *self.tail.get();
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/sync/mpsc/oneshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ enum MyUpgrade<T> {
GoUp(Receiver<T>),
}

impl<T: Send> Packet<T> {
impl<T: Send + 'static> Packet<T> {
pub fn new() -> Packet<T> {
Packet {
data: None,
Expand Down Expand Up @@ -368,7 +368,7 @@ impl<T: Send> Packet<T> {
}

#[unsafe_destructor]
impl<T: Send> Drop for Packet<T> {
impl<T: Send + 'static> Drop for Packet<T> {
fn drop(&mut self) {
assert_eq!(self.state.load(Ordering::SeqCst), DISCONNECTED);
}
Expand Down
Loading

0 comments on commit ba8ce4c

Please sign in to comment.