about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-03-24 15:27:14 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-03-24 15:27:14 -0700
commit3b13b9c2b4e72d08cb1c68024ccc4f50001f4878 (patch)
treed4efd6426beeeee1f0c543cfe345b9625285f46e /src/libstd
parent91b633aa038008fdbee658a10182afdd794d2aa6 (diff)
parent1955e052675d4457432da85a00db0ae55be64e83 (diff)
downloadrust-3b13b9c2b4e72d08cb1c68024ccc4f50001f4878.tar.gz
rust-3b13b9c2b4e72d08cb1c68024ccc4f50001f4878.zip
rollup merge of #23638: pnkfelix/fsk-reject-specialized-drops
Reject specialized Drop impls.

See Issue #8142 for discussion.

This makes it illegal for a Drop impl to be more specialized than the original item.

So for example, all of the following are now rejected (when they would have been blindly accepted before):

```rust
struct S<A> { ... };
impl Drop for S<i8> { ... } // error: specialized to concrete type

struct T<'a> { ... };
impl Drop for T<'static> { ... } // error: specialized to concrete region

struct U<A> { ... };
impl<A:Clone> Drop for U<A> { ... } // error: added extra type requirement

struct V<'a,'b>;
impl<'a,'b:a> Drop for V<'a,'b> { ... } // error: added extra region requirement
```

Due to examples like the above, this is a [breaking-change].

(The fix is to either remove the specialization from the `Drop` impl, or to transcribe the requirements into the struct/enum definition; examples of both are shown in the PR's fixed to `libstd`.)

----

This is likely to be the last thing blocking the removal of the `#[unsafe_destructor]` attribute.

Fix #8142
Fix #23584
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/io/buffered.rs18
-rw-r--r--src/libstd/old_io/buffered.rs18
-rw-r--r--src/libstd/sync/mpsc/mod.rs16
-rw-r--r--src/libstd/sync/mpsc/mpsc_queue.rs2
-rw-r--r--src/libstd/sync/mpsc/oneshot.rs8
-rw-r--r--src/libstd/sync/mpsc/select.rs2
-rw-r--r--src/libstd/sync/mpsc/shared.rs2
-rw-r--r--src/libstd/sync/mpsc/spsc_queue.rs2
-rw-r--r--src/libstd/sync/mpsc/stream.rs8
-rw-r--r--src/libstd/sync/mpsc/sync.rs2
-rw-r--r--src/libstd/sync/mutex.rs4
-rw-r--r--src/libstd/sys/common/helper_thread.rs2
-rw-r--r--src/libstd/thread/mod.rs2
13 files changed, 43 insertions, 43 deletions
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 4def601f1c0..2a1294f23b2 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -120,7 +120,7 @@ impl<R> fmt::Debug for BufReader<R> where R: fmt::Debug {
 ///
 /// The buffer will be written out when the writer is dropped.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct BufWriter<W> {
+pub struct BufWriter<W: Write> {
     inner: Option<W>,
     buf: Vec<u8>,
 }
@@ -220,7 +220,7 @@ impl<W: Write> Write for BufWriter<W> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for BufWriter<W> where W: fmt::Debug {
+impl<W: Write> fmt::Debug for BufWriter<W> where W: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "BufWriter {{ writer: {:?}, buffer: {}/{} }}",
                self.inner.as_ref().unwrap(), self.buf.len(), self.buf.capacity())
@@ -276,7 +276,7 @@ impl<W> fmt::Display for IntoInnerError<W> {
 ///
 /// The buffer will be written out when the writer is dropped.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct LineWriter<W> {
+pub struct LineWriter<W: Write> {
     inner: BufWriter<W>,
 }
 
@@ -335,7 +335,7 @@ impl<W: Write> Write for LineWriter<W> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for LineWriter<W> where W: fmt::Debug {
+impl<W: Write> fmt::Debug for LineWriter<W> where W: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "LineWriter {{ writer: {:?}, buffer: {}/{} }}",
                self.inner.inner, self.inner.buf.len(),
@@ -343,16 +343,16 @@ impl<W> fmt::Debug for LineWriter<W> where W: fmt::Debug {
     }
 }
 
-struct InternalBufWriter<W>(BufWriter<W>);
+struct InternalBufWriter<W: Write>(BufWriter<W>);
 
-impl<W> InternalBufWriter<W> {
+impl<W: Read + Write> InternalBufWriter<W> {
     fn get_mut(&mut self) -> &mut BufWriter<W> {
         let InternalBufWriter(ref mut w) = *self;
         return w;
     }
 }
 
-impl<W: Read> Read for InternalBufWriter<W> {
+impl<W: Read + Write> Read for InternalBufWriter<W> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.get_mut().inner.as_mut().unwrap().read(buf)
     }
@@ -367,7 +367,7 @@ impl<W: Read> Read for InternalBufWriter<W> {
 ///
 /// The output buffer will be written out when this stream is dropped.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct BufStream<S> {
+pub struct BufStream<S: Write> {
     inner: BufReader<InternalBufWriter<S>>
 }
 
@@ -448,7 +448,7 @@ impl<S: Read + Write> Write for BufStream<S> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<S> fmt::Debug for BufStream<S> where S: fmt::Debug {
+impl<S: Write> fmt::Debug for BufStream<S> where S: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let reader = &self.inner;
         let writer = &self.inner.inner.0;
diff --git a/src/libstd/old_io/buffered.rs b/src/libstd/old_io/buffered.rs
index cb67d709a14..9a9d421dfe1 100644
--- a/src/libstd/old_io/buffered.rs
+++ b/src/libstd/old_io/buffered.rs
@@ -148,14 +148,14 @@ impl<R: Reader> Reader for BufferedReader<R> {
 /// writer.write_str("hello, world").unwrap();
 /// writer.flush().unwrap();
 /// ```
-pub struct BufferedWriter<W> {
+pub struct BufferedWriter<W: Writer> {
     inner: Option<W>,
     buf: Vec<u8>,
     pos: uint
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for BufferedWriter<W> where W: fmt::Debug {
+impl<W: Writer> fmt::Debug for BufferedWriter<W> where W: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "BufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
                self.inner.as_ref().unwrap(), self.pos, self.buf.len())
@@ -250,12 +250,12 @@ impl<W: Writer> Drop for BufferedWriter<W> {
 /// `'\n'`) is detected.
 ///
 /// This writer will be flushed when it is dropped.
-pub struct LineBufferedWriter<W> {
+pub struct LineBufferedWriter<W: Writer> {
     inner: BufferedWriter<W>,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for LineBufferedWriter<W> where W: fmt::Debug {
+impl<W: Writer> fmt::Debug for LineBufferedWriter<W> where W: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "LineBufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
                self.inner.inner, self.inner.pos, self.inner.buf.len())
@@ -299,16 +299,16 @@ impl<W: Writer> Writer for LineBufferedWriter<W> {
     fn flush(&mut self) -> IoResult<()> { self.inner.flush() }
 }
 
-struct InternalBufferedWriter<W>(BufferedWriter<W>);
+struct InternalBufferedWriter<W: Writer>(BufferedWriter<W>);
 
-impl<W> InternalBufferedWriter<W> {
+impl<W: Writer> InternalBufferedWriter<W> {
     fn get_mut<'a>(&'a mut self) -> &'a mut BufferedWriter<W> {
         let InternalBufferedWriter(ref mut w) = *self;
         return w;
     }
 }
 
-impl<W: Reader> Reader for InternalBufferedWriter<W> {
+impl<W: Reader + Writer> Reader for InternalBufferedWriter<W> {
     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         self.get_mut().inner.as_mut().unwrap().read(buf)
     }
@@ -343,12 +343,12 @@ impl<W: Reader> Reader for InternalBufferedWriter<W> {
 ///     Err(e) => println!("error reading: {}", e)
 /// }
 /// ```
-pub struct BufferedStream<S> {
+pub struct BufferedStream<S: Writer> {
     inner: BufferedReader<InternalBufferedWriter<S>>
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<S> fmt::Debug for BufferedStream<S> where S: fmt::Debug {
+impl<S: Writer> fmt::Debug for BufferedStream<S> where S: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let reader = &self.inner;
         let writer = &self.inner.inner.0;
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index 7adfd9154ac..eb421fe55a4 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -342,7 +342,7 @@ mod spsc_queue;
 /// The receiving-half of Rust's channel type. This half can only be owned by
 /// one task
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Receiver<T> {
+pub struct Receiver<T:Send> {
     inner: UnsafeCell<Flavor<T>>,
 }
 
@@ -354,14 +354,14 @@ unsafe impl<T: Send> Send for Receiver<T> { }
 /// whenever `next` is called, waiting for a new message, and `None` will be
 /// returned when the corresponding channel has hung up.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Iter<'a, T:'a> {
+pub struct Iter<'a, T:Send+'a> {
     rx: &'a Receiver<T>
 }
 
 /// The sending-half of Rust's asynchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Sender<T> {
+pub struct Sender<T:Send> {
     inner: UnsafeCell<Flavor<T>>,
 }
 
@@ -372,7 +372,7 @@ 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.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct SyncSender<T> {
+pub struct SyncSender<T: Send> {
     inner: Arc<UnsafeCell<sync::Packet<T>>>,
 }
 
@@ -433,7 +433,7 @@ pub enum TrySendError<T> {
     Disconnected(T),
 }
 
-enum Flavor<T> {
+enum Flavor<T:Send> {
     Oneshot(Arc<UnsafeCell<oneshot::Packet<T>>>),
     Stream(Arc<UnsafeCell<stream::Packet<T>>>),
     Shared(Arc<UnsafeCell<shared::Packet<T>>>),
@@ -441,7 +441,7 @@ enum Flavor<T> {
 }
 
 #[doc(hidden)]
-trait UnsafeFlavor<T> {
+trait UnsafeFlavor<T:Send> {
     fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>>;
     unsafe fn inner_mut<'a>(&'a self) -> &'a mut Flavor<T> {
         &mut *self.inner_unsafe().get()
@@ -450,12 +450,12 @@ trait UnsafeFlavor<T> {
         &*self.inner_unsafe().get()
     }
 }
-impl<T> UnsafeFlavor<T> for Sender<T> {
+impl<T:Send> UnsafeFlavor<T> for Sender<T> {
     fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
         &self.inner
     }
 }
-impl<T> UnsafeFlavor<T> for Receiver<T> {
+impl<T:Send> UnsafeFlavor<T> for Receiver<T> {
     fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
         &self.inner
     }
diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs
index 14ed253d8e2..1be8b0dd862 100644
--- a/src/libstd/sync/mpsc/mpsc_queue.rs
+++ b/src/libstd/sync/mpsc/mpsc_queue.rs
@@ -72,7 +72,7 @@ struct Node<T> {
 /// The multi-producer single-consumer structure. This is not cloneable, but it
 /// may be safely shared so long as it is guaranteed that there is only one
 /// popper at a time (many pushers are allowed).
-pub struct Queue<T> {
+pub struct Queue<T: Send> {
     head: AtomicPtr<Node<T>>,
     tail: UnsafeCell<*mut Node<T>>,
 }
diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs
index f287712d9d4..13578ce0517 100644
--- a/src/libstd/sync/mpsc/oneshot.rs
+++ b/src/libstd/sync/mpsc/oneshot.rs
@@ -54,7 +54,7 @@ const DISCONNECTED: usize = 2;   // channel is disconnected OR upgraded
 // moves *from* a pointer, ownership of the token is transferred to
 // whoever changed the state.
 
-pub struct Packet<T> {
+pub struct Packet<T:Send> {
     // Internal state of the chan/port pair (stores the blocked task as well)
     state: AtomicUsize,
     // One-shot data slot location
@@ -64,7 +64,7 @@ pub struct Packet<T> {
     upgrade: MyUpgrade<T>,
 }
 
-pub enum Failure<T> {
+pub enum Failure<T:Send> {
     Empty,
     Disconnected,
     Upgraded(Receiver<T>),
@@ -76,13 +76,13 @@ pub enum UpgradeResult {
     UpWoke(SignalToken),
 }
 
-pub enum SelectionResult<T> {
+pub enum SelectionResult<T:Send> {
     SelCanceled,
     SelUpgraded(SignalToken, Receiver<T>),
     SelSuccess,
 }
 
-enum MyUpgrade<T> {
+enum MyUpgrade<T:Send> {
     NothingSent,
     SendUsed,
     GoUp(Receiver<T>),
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
index 0f936641cdc..b509b3472ee 100644
--- a/src/libstd/sync/mpsc/select.rs
+++ b/src/libstd/sync/mpsc/select.rs
@@ -80,7 +80,7 @@ impl !marker::Send for Select {}
 /// A handle to a receiver which is currently a member of a `Select` set of
 /// receivers.  This handle is used to keep the receiver in the set as well as
 /// interact with the underlying receiver.
-pub struct Handle<'rx, T:'rx> {
+pub struct Handle<'rx, T:Send+'rx> {
     /// The ID of this handle, used to compare against the return value of
     /// `Select::wait()`
     id: usize,
diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs
index 8d14824d37f..f3930a8a5d6 100644
--- a/src/libstd/sync/mpsc/shared.rs
+++ b/src/libstd/sync/mpsc/shared.rs
@@ -40,7 +40,7 @@ const MAX_STEALS: isize = 5;
 #[cfg(not(test))]
 const MAX_STEALS: isize = 1 << 20;
 
-pub struct Packet<T> {
+pub struct Packet<T: Send> {
     queue: mpsc::Queue<T>,
     cnt: AtomicIsize, // How many items are on this channel
     steals: isize, // How many times has a port received without blocking?
diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs
index 3fb13739aa7..cd6d1ee05c7 100644
--- a/src/libstd/sync/mpsc/spsc_queue.rs
+++ b/src/libstd/sync/mpsc/spsc_queue.rs
@@ -57,7 +57,7 @@ struct Node<T> {
 /// but it can be safely shared in an Arc if it is guaranteed that there
 /// is only one popper and one pusher touching the queue at any one point in
 /// time.
-pub struct Queue<T> {
+pub struct Queue<T: Send> {
     // consumer fields
     tail: UnsafeCell<*mut Node<T>>, // where to pop from
     tail_prev: AtomicPtr<Node<T>>, // where to pop from
diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs
index 5a1e05f9c15..a5a73314a6d 100644
--- a/src/libstd/sync/mpsc/stream.rs
+++ b/src/libstd/sync/mpsc/stream.rs
@@ -39,7 +39,7 @@ const MAX_STEALS: isize = 5;
 #[cfg(not(test))]
 const MAX_STEALS: isize = 1 << 20;
 
-pub struct Packet<T> {
+pub struct Packet<T:Send> {
     queue: spsc::Queue<Message<T>>, // internal queue for all message
 
     cnt: AtomicIsize, // How many items are on this channel
@@ -49,7 +49,7 @@ pub struct Packet<T> {
     port_dropped: AtomicBool, // flag if the channel has been destroyed.
 }
 
-pub enum Failure<T> {
+pub enum Failure<T:Send> {
     Empty,
     Disconnected,
     Upgraded(Receiver<T>),
@@ -61,7 +61,7 @@ pub enum UpgradeResult {
     UpWoke(SignalToken),
 }
 
-pub enum SelectionResult<T> {
+pub enum SelectionResult<T:Send> {
     SelSuccess,
     SelCanceled,
     SelUpgraded(SignalToken, Receiver<T>),
@@ -69,7 +69,7 @@ pub enum SelectionResult<T> {
 
 // Any message could contain an "upgrade request" to a new shared port, so the
 // internal queue it's a queue of T, but rather Message<T>
-enum Message<T> {
+enum Message<T:Send> {
     Data(T),
     GoUp(Receiver<T>),
 }
diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs
index 33c1614e1b2..71236269487 100644
--- a/src/libstd/sync/mpsc/sync.rs
+++ b/src/libstd/sync/mpsc/sync.rs
@@ -47,7 +47,7 @@ use sync::mpsc::blocking::{self, WaitToken, SignalToken};
 use sync::mpsc::select::StartResult::{self, Installed, Abort};
 use sync::{Mutex, MutexGuard};
 
-pub struct Packet<T> {
+pub struct Packet<T: Send> {
     /// Only field outside of the mutex. Just done for kicks, but mainly because
     /// the other shared channel already had the code implemented
     channels: AtomicUsize,
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 2bf75cf1d37..b24cfbb6899 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -112,7 +112,7 @@ use fmt;
 /// *guard += 1;
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Mutex<T> {
+pub struct Mutex<T: Send> {
     // Note that this static mutex is in a *box*, not inlined into the struct
     // itself. Once a native mutex has been used once, its address can never
     // change (it can't be moved). This mutex type can be safely moved at any
@@ -366,7 +366,7 @@ mod test {
     use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar};
     use thread;
 
-    struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
+    struct Packet<T: Send>(Arc<(Mutex<T>, Condvar)>);
 
     unsafe impl<T: Send> Send for Packet<T> {}
     unsafe impl<T> Sync for Packet<T> {}
diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs
index 53f18a57325..10077dfd1b8 100644
--- a/src/libstd/sys/common/helper_thread.rs
+++ b/src/libstd/sys/common/helper_thread.rs
@@ -38,7 +38,7 @@ use thread;
 ///
 /// The fields of this helper are all public, but they should not be used, this
 /// is for static initialization.
-pub struct Helper<M> {
+pub struct Helper<M:Send> {
     /// Internal lock which protects the remaining fields
     pub lock: StaticMutex,
     pub cond: StaticCondvar,
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 57baeb1fb74..27b50fc9aaa 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -698,7 +698,7 @@ impl Drop for JoinHandle {
 /// permission.
 #[must_use = "thread will be immediately joined if `JoinGuard` is not used"]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct JoinGuard<'a, T: 'a> {
+pub struct JoinGuard<'a, T: Send + 'a> {
     inner: JoinInner<T>,
     _marker: PhantomData<&'a T>,
 }