]> git.lizzy.rs Git - rust.git/commitdiff
Remove `'static` bound from sync::mpsc, Mutex and RwLock.
authorHuon Wilson <dbau.pp+github@gmail.com>
Fri, 20 Feb 2015 06:33:11 +0000 (17:33 +1100)
committerHuon Wilson <dbau.pp+github@gmail.com>
Sat, 21 Feb 2015 05:51:49 +0000 (16:51 +1100)
Adds some basic tests to check that the types still catch the most
glaring errors that could occur.

cc #22444.

12 files changed:
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/mpsc_queue.rs
src/libstd/sync/mpsc/oneshot.rs
src/libstd/sync/mpsc/select.rs
src/libstd/sync/mpsc/shared.rs
src/libstd/sync/mpsc/spsc_queue.rs
src/libstd/sync/mpsc/stream.rs
src/libstd/sync/mpsc/sync.rs
src/libstd/sync/mutex.rs
src/libstd/sync/rwlock.rs
src/test/compile-fail/send-is-not-static-std-sync-2.rs [new file with mode: 0644]
src/test/compile-fail/send-is-not-static-std-sync.rs [new file with mode: 0644]

index 21993e51669d359789f04767c4911391c36350cb..b437549a044920a7b923fba757d4c2634576ba1e 100644 (file)
@@ -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 + 'static> Send for Receiver<T> { }
+unsafe impl<T: Send> 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
@@ -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 + 'static> Send for Sender<T> { }
+unsafe impl<T: Send> 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.
@@ -373,7 +373,7 @@ pub struct SyncSender<T> {
     inner: Arc<UnsafeCell<sync::Packet<T>>>,
 }
 
-unsafe impl<T: Send + 'static> Send for SyncSender<T> {}
+unsafe impl<T: Send> Send for SyncSender<T> {}
 
 impl<T> !Sync for SyncSender<T> {}
 
@@ -485,7 +485,7 @@ fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
 /// println!("{:?}", rx.recv().unwrap());
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn channel<T: Send + 'static>() -> (Sender<T>, Receiver<T>) {
+pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
     let a = Arc::new(UnsafeCell::new(oneshot::Packet::new()));
     (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
 }
@@ -525,7 +525,7 @@ pub fn channel<T: Send + 'static>() -> (Sender<T>, Receiver<T>) {
 /// assert_eq!(rx.recv().unwrap(), 2);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn sync_channel<T: Send + 'static>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
+pub fn sync_channel<T: Send>(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)))
 }
@@ -534,7 +534,7 @@ pub fn sync_channel<T: Send + 'static>(bound: uint) -> (SyncSender<T>, Receiver<
 // Sender
 ////////////////////////////////////////////////////////////////////////////////
 
-impl<T: Send + 'static> Sender<T> {
+impl<T: Send> Sender<T> {
     fn new(inner: Flavor<T>) -> Sender<T> {
         Sender {
             inner: UnsafeCell::new(inner),
@@ -616,7 +616,7 @@ pub fn send(&self, t: T) -> Result<(), SendError<T>> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Clone for Sender<T> {
+impl<T: Send> Clone for Sender<T> {
     fn clone(&self) -> Sender<T> {
         let (packet, sleeper, guard) = match *unsafe { self.inner() } {
             Flavor::Oneshot(ref p) => {
@@ -662,7 +662,7 @@ fn clone(&self) -> Sender<T> {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Drop for Sender<T> {
+impl<T: Send> Drop for Sender<T> {
     fn drop(&mut self) {
         match *unsafe { self.inner_mut() } {
             Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
@@ -677,7 +677,7 @@ fn drop(&mut self) {
 // SyncSender
 ////////////////////////////////////////////////////////////////////////////////
 
-impl<T: Send + 'static> SyncSender<T> {
+impl<T: Send> SyncSender<T> {
     fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
         SyncSender { inner: inner }
     }
@@ -717,7 +717,7 @@ pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Clone for SyncSender<T> {
+impl<T: Send> Clone for SyncSender<T> {
     fn clone(&self) -> SyncSender<T> {
         unsafe { (*self.inner.get()).clone_chan(); }
         return SyncSender::new(self.inner.clone());
@@ -726,7 +726,7 @@ fn clone(&self) -> SyncSender<T> {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Drop for SyncSender<T> {
+impl<T: Send> Drop for SyncSender<T> {
     fn drop(&mut self) {
         unsafe { (*self.inner.get()).drop_chan(); }
     }
@@ -736,7 +736,7 @@ fn drop(&mut self) {
 // Receiver
 ////////////////////////////////////////////////////////////////////////////////
 
-impl<T: Send + 'static> Receiver<T> {
+impl<T: Send> Receiver<T> {
     fn new(inner: Flavor<T>) -> Receiver<T> {
         Receiver { inner: UnsafeCell::new(inner) }
     }
@@ -855,7 +855,7 @@ pub fn iter(&self) -> Iter<T> {
     }
 }
 
-impl<T: Send + 'static> select::Packet for Receiver<T> {
+impl<T: Send> select::Packet for Receiver<T> {
     fn can_recv(&self) -> bool {
         loop {
             let new_port = match *unsafe { self.inner() } {
@@ -942,7 +942,7 @@ fn abort_selection(&self) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: Send + 'static> Iterator for Iter<'a, T> {
+impl<'a, T: Send> Iterator for Iter<'a, T> {
     type Item = T;
 
     fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
@@ -950,7 +950,7 @@ fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Drop for Receiver<T> {
+impl<T: Send> Drop for Receiver<T> {
     fn drop(&mut self) {
         match *unsafe { self.inner_mut() } {
             Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
index a2accb128c310c2298ca6c277bee6792ad57b57d..6eb7c8c5961e326dae5c75841ee560df688909be 100644 (file)
@@ -78,7 +78,7 @@ pub struct Queue<T> {
 }
 
 unsafe impl<T:Send> Send for Queue<T> { }
-unsafe impl<T: Send + 'static> Sync for Queue<T> { }
+unsafe impl<T: Send> Sync for Queue<T> { }
 
 impl<T> Node<T> {
     unsafe fn new(v: Option<T>) -> *mut Node<T> {
@@ -89,7 +89,7 @@ unsafe fn new(v: Option<T>) -> *mut Node<T> {
     }
 }
 
-impl<T: Send + 'static> Queue<T> {
+impl<T: Send> Queue<T> {
     /// Creates a new queue that is safe to share among multiple producers and
     /// one consumer.
     pub fn new() -> Queue<T> {
@@ -140,7 +140,7 @@ pub fn pop(&self) -> PopResult<T> {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Drop for Queue<T> {
+impl<T: Send> Drop for Queue<T> {
     fn drop(&mut self) {
         unsafe {
             let mut cur = *self.tail.get();
index 55b2caf7c6d4cccea53aa2331ea3defaf0113524..eb45681fa626d6e3018447c676efe23b688ce478 100644 (file)
@@ -88,7 +88,7 @@ enum MyUpgrade<T> {
     GoUp(Receiver<T>),
 }
 
-impl<T: Send + 'static> Packet<T> {
+impl<T: Send> Packet<T> {
     pub fn new() -> Packet<T> {
         Packet {
             data: None,
@@ -368,7 +368,7 @@ pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
 }
 
 #[unsafe_destructor]
-impl<T: Send + 'static> Drop for Packet<T> {
+impl<T: Send> Drop for Packet<T> {
     fn drop(&mut self) {
         assert_eq!(self.state.load(Ordering::SeqCst), DISCONNECTED);
     }
index 8fcedd2ab5796cbd0d955ec65c73257c01186a80..db8efe19dc1df973e3f37968c5ca138c47c46d9f 100644 (file)
@@ -134,7 +134,7 @@ pub fn new() -> Select {
     /// 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
     /// must call the `add` method on the handle itself.
-    pub fn handle<'a, T: Send + 'static>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
+    pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
         let id = self.next_id.get();
         self.next_id.set(id + 1);
         Handle {
@@ -251,7 +251,7 @@ fn wait2(&self, do_preflight_checks: bool) -> uint {
     fn iter(&self) -> Packets { Packets { cur: self.head } }
 }
 
-impl<'rx, T: Send + 'static> Handle<'rx, T> {
+impl<'rx, T: Send> Handle<'rx, T> {
     /// Retrieve the id of this handle.
     #[inline]
     pub fn id(&self) -> uint { self.id }
@@ -322,7 +322,7 @@ fn drop(&mut self) {
 }
 
 #[unsafe_destructor]
-impl<'rx, T: Send + 'static> Drop for Handle<'rx, T> {
+impl<'rx, T: Send> Drop for Handle<'rx, T> {
     fn drop(&mut self) {
         unsafe { self.remove() }
     }
index bc9c73585c21fe86ff9ec4e5630191f6330289e9..729e7991f97cfb2cb03c97c2854c253ee8dd0f7d 100644 (file)
@@ -64,7 +64,7 @@ pub enum Failure {
     Disconnected,
 }
 
-impl<T: Send + 'static> Packet<T> {
+impl<T: Send> Packet<T> {
     // Creation of a packet *must* be followed by a call to postinit_lock
     // and later by inherit_blocker
     pub fn new() -> Packet<T> {
@@ -474,7 +474,7 @@ pub fn abort_selection(&mut self, _was_upgrade: bool) -> bool {
 }
 
 #[unsafe_destructor]
-impl<T: Send + 'static> Drop for Packet<T> {
+impl<T: Send> Drop for Packet<T> {
     fn drop(&mut self) {
         // Note that this load is not only an assert for correctness about
         // disconnection, but also a proper fence before the read of
index e1a897065092af2ca1485b6354a70c355561b78e..f111e13975ff700a4712b33dcd43fbd5b349134b 100644 (file)
@@ -74,11 +74,11 @@ pub struct Queue<T> {
     cache_subtractions: AtomicUsize,
 }
 
-unsafe impl<T: Send + 'static> Send for Queue<T> { }
+unsafe impl<T: Send> Send for Queue<T> { }
 
-unsafe impl<T: Send + 'static> Sync for Queue<T> { }
+unsafe impl<T: Send> Sync for Queue<T> { }
 
-impl<T: Send + 'static> Node<T> {
+impl<T: Send> Node<T> {
     fn new() -> *mut Node<T> {
         unsafe {
             mem::transmute(box Node {
@@ -89,7 +89,7 @@ fn new() -> *mut Node<T> {
     }
 }
 
-impl<T: Send + 'static> Queue<T> {
+impl<T: Send> Queue<T> {
     /// Creates a new queue.
     ///
     /// This is unsafe as the type system doesn't enforce a single
@@ -227,7 +227,7 @@ pub fn peek<'a>(&'a self) -> Option<&'a mut T> {
 }
 
 #[unsafe_destructor]
-impl<T: Send + 'static> Drop for Queue<T> {
+impl<T: Send> Drop for Queue<T> {
     fn drop(&mut self) {
         unsafe {
             let mut cur = *self.first.get();
index a194c99669263e356e1ad1bf46f160a6c212f8cf..2d528662f64fc9dd3fa2f725cb7934bcaf3303c2 100644 (file)
@@ -74,7 +74,7 @@ enum Message<T> {
     GoUp(Receiver<T>),
 }
 
-impl<T: Send + 'static> Packet<T> {
+impl<T: Send> Packet<T> {
     pub fn new() -> Packet<T> {
         Packet {
             queue: unsafe { spsc::Queue::new(128) },
@@ -472,7 +472,7 @@ pub fn abort_selection(&mut self,
 }
 
 #[unsafe_destructor]
-impl<T: Send + 'static> Drop for Packet<T> {
+impl<T: Send> Drop for Packet<T> {
     fn drop(&mut self) {
         // Note that this load is not only an assert for correctness about
         // disconnection, but also a proper fence before the read of
index ae96a2491dc267ee06066c369ee6cfb838e3c204..36b50b0d4af01fcad7a80b771e56e00a5b70fa79 100644 (file)
@@ -55,9 +55,9 @@ pub struct Packet<T> {
     lock: Mutex<State<T>>,
 }
 
-unsafe impl<T: Send + 'static> Send for Packet<T> { }
+unsafe impl<T: Send> Send for Packet<T> { }
 
-unsafe impl<T: Send + 'static> Sync for Packet<T> { }
+unsafe impl<T: Send> Sync for Packet<T> { }
 
 struct State<T> {
     disconnected: bool, // Is the channel disconnected yet?
@@ -75,7 +75,7 @@ struct State<T> {
     canceled: Option<&'static mut bool>,
 }
 
-unsafe impl<T: Send + 'static> Send for State<T> {}
+unsafe impl<T: Send> Send for State<T> {}
 
 /// Possible flavors of threads who can be blocked on this channel.
 enum Blocker {
@@ -113,7 +113,7 @@ pub enum Failure {
 
 /// Atomically blocks the current thread, placing it into `slot`, unlocking `lock`
 /// in the meantime. This re-locks the mutex upon returning.
-fn wait<'a, 'b, T: Send + 'static>(lock: &'a Mutex<State<T>>,
+fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>,
                          mut guard: MutexGuard<'b, State<T>>,
                          f: fn(SignalToken) -> Blocker)
                          -> MutexGuard<'a, State<T>>
@@ -136,7 +136,7 @@ fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
     token.signal();
 }
 
-impl<T: Send + 'static> Packet<T> {
+impl<T: Send> Packet<T> {
     pub fn new(cap: uint) -> Packet<T> {
         Packet {
             channels: AtomicUsize::new(1),
@@ -412,7 +412,7 @@ pub fn abort_selection(&self) -> bool {
 }
 
 #[unsafe_destructor]
-impl<T: Send + 'static> Drop for Packet<T> {
+impl<T: Send> Drop for Packet<T> {
     fn drop(&mut self) {
         assert_eq!(self.channels.load(Ordering::SeqCst), 0);
         let mut guard = self.lock.lock().unwrap();
index e77c4d2e5ebd4ec7ed498335eb1a3a3a67abe284..b71cc0c26536474db76f2501e061da337ff8b23c 100644 (file)
@@ -120,9 +120,9 @@ pub struct Mutex<T> {
     data: UnsafeCell<T>,
 }
 
-unsafe impl<T: Send + 'static> Send for Mutex<T> { }
+unsafe impl<T: Send> Send for Mutex<T> { }
 
-unsafe impl<T: Send + 'static> Sync for Mutex<T> { }
+unsafe impl<T: Send> Sync for Mutex<T> { }
 
 /// The static mutex type is provided to allow for static allocation of mutexes.
 ///
@@ -180,7 +180,7 @@ impl<'a, T> !marker::Send for MutexGuard<'a, T> {}
     poison: poison::FLAG_INIT,
 };
 
-impl<T: Send + 'static> Mutex<T> {
+impl<T: Send> Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(t: T) -> Mutex<T> {
@@ -243,7 +243,7 @@ pub fn is_poisoned(&self) -> bool {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Drop for Mutex<T> {
+impl<T: Send> Drop for Mutex<T> {
     fn drop(&mut self) {
         // 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
@@ -354,7 +354,7 @@ mod test {
 
     struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
 
-    unsafe impl<T:'static+Send> Send for Packet<T> {}
+    unsafe impl<T: Send> Send for Packet<T> {}
     unsafe impl<T> Sync for Packet<T> {}
 
     #[test]
index cd833b17867106baa763e5ab4c1defe3fddb2a01..6fd2a6ed77d264c754e19e5ae46873ce274cb117 100644 (file)
@@ -64,8 +64,8 @@ pub struct RwLock<T> {
     data: UnsafeCell<T>,
 }
 
-unsafe impl<T:'static+Send> Send for RwLock<T> {}
-unsafe impl<T> Sync for RwLock<T> {}
+unsafe impl<T: Send + Sync> Send for RwLock<T> {}
+unsafe impl<T: Send + Sync> Sync for RwLock<T> {}
 
 /// Structure representing a statically allocated RwLock.
 ///
diff --git a/src/test/compile-fail/send-is-not-static-std-sync-2.rs b/src/test/compile-fail/send-is-not-static-std-sync-2.rs
new file mode 100644 (file)
index 0000000..d9d3706
--- /dev/null
@@ -0,0 +1,46 @@
+// 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.
+
+// basic tests to see that certain "obvious" errors are caught by
+// these types no longer requiring `'static` (RFC 458)
+
+#![allow(dead_code)]
+
+use std::sync::{Mutex, RwLock, mpsc};
+
+fn mutex() {
+    let lock = {
+        let x = 1;
+        Mutex::new(&x) //~ ERROR does not live long enough
+    };
+
+    let _dangling = *lock.lock().unwrap();
+}
+
+fn rwlock() {
+    let lock = {
+        let x = 1;
+        RwLock::new(&x) //~ ERROR does not live long enough
+    };
+    let _dangling = *lock.read().unwrap();
+}
+
+fn channel() {
+    let (_tx, rx) = {
+        let x = 1;
+        let (tx, rx) = mpsc::channel();
+        let _ = tx.send(&x); //~ ERROR does not live long enough
+        (tx, rx)
+    };
+
+    let _dangling = rx.recv();
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/send-is-not-static-std-sync.rs b/src/test/compile-fail/send-is-not-static-std-sync.rs
new file mode 100644 (file)
index 0000000..8ec2fe8
--- /dev/null
@@ -0,0 +1,56 @@
+// 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.
+
+// basic tests to see that certain "obvious" errors are caught by
+// these types no longer requiring `'static` (RFC 458)
+
+#![allow(dead_code)]
+
+use std::sync::{Mutex, RwLock, mpsc};
+
+fn mutex() {
+    let x = 1;
+    let y = Box::new(1);
+    let lock = Mutex::new(&x);
+    *lock.lock().unwrap() = &*y;
+    drop(y); //~ ERROR cannot move out
+    {
+        let z = 2;
+        *lock.lock().unwrap() = &z; //~ ERROR does not live long enough
+    }
+}
+
+fn rwlock() {
+    let x = 1;
+    let y = Box::new(1);
+    let lock = RwLock::new(&x);
+    *lock.write().unwrap() = &*y;
+    drop(y); //~ ERROR cannot move out
+    {
+        let z = 2;
+        *lock.write().unwrap() = &z; //~ ERROR does not live long enough
+    }
+}
+
+fn channel() {
+    let x = 1;
+    let y = Box::new(1);
+    let (tx, rx) = mpsc::channel();
+
+    tx.send(&x).unwrap();
+    tx.send(&*y);
+    drop(y); //~ ERROR cannot move out
+    {
+        let z = 2;
+        tx.send(&z).unwrap(); //~ ERROR does not live long enough
+    }
+}
+
+fn main() {}