summary refs log tree commit diff
path: root/src/libstd/io
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/io
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/io')
-rw-r--r--src/libstd/io/buffered.rs18
1 files changed, 9 insertions, 9 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;