From 29938fff3802243bdfe9a12860384d8eade20a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Krasnoborski?= Date: Wed, 4 Mar 2015 22:24:38 +0100 Subject: [PATCH 01/37] Fix struct stat on arm linux --- src/liblibc/lib.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 42143b06ca0e..04898d90ad07 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -386,7 +386,8 @@ pub mod types { target_arch = "mips", target_arch = "mipsel", target_arch = "powerpc", - target_arch = "le32"))] + target_arch = "le32", + all(target_arch = "arm", not(target_os = "android"))))] pub mod posix88 { pub type off_t = i32; pub type dev_t = u64; @@ -398,7 +399,7 @@ pub mod types { pub type mode_t = u32; pub type ssize_t = i32; } - #[cfg(target_arch = "arm")] + #[cfg(all(target_arch = "arm", target_os = "android"))] pub mod posix88 { pub type off_t = i32; pub type dev_t = u32; @@ -412,7 +413,8 @@ pub mod types { } #[cfg(any(target_arch = "x86", target_arch = "le32", - target_arch = "powerpc"))] + target_arch = "powerpc", + all(target_arch = "arm", not(target_os = "android"))))] pub mod posix01 { use types::os::arch::c95::{c_short, c_long, time_t}; use types::os::arch::posix88::{dev_t, gid_t, ino_t}; @@ -458,7 +460,7 @@ pub mod types { pub __size: [u32; 9] } } - #[cfg(target_arch = "arm")] + #[cfg(all(target_arch = "arm", target_os = "android"))] pub mod posix01 { use types::os::arch::c95::{c_uchar, c_uint, c_ulong, time_t}; use types::os::arch::c99::{c_longlong, c_ulonglong}; From 61a2766136536f9993ae095075ec766cfc729f8b Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Wed, 4 Mar 2015 16:27:18 -0500 Subject: [PATCH 02/37] Note the alternate form of vec in trpl --- src/doc/trpl/arrays-vectors-and-slices.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/doc/trpl/arrays-vectors-and-slices.md b/src/doc/trpl/arrays-vectors-and-slices.md index d4e2ad5cd5f6..f1b5ecf4ff03 100644 --- a/src/doc/trpl/arrays-vectors-and-slices.md +++ b/src/doc/trpl/arrays-vectors-and-slices.md @@ -60,6 +60,12 @@ let v = vec![1, 2, 3]; // v: Vec brackets `[]` with `vec!`. Rust allows you to use either in either situation, this is just convention.) +There's an alternate form of `vec!` for repeating an initial value: + +``` +let v = vec![0; 10]; // ten zeroes +``` + You can get the length of, iterate over, and subscript vectors just like arrays. In addition, (mutable) vectors can grow automatically: From b1e0dfb25c5a3878a27eb3cc15606306f2d3a7bd Mon Sep 17 00:00:00 2001 From: Camille TJHOA Date: Wed, 4 Mar 2015 23:09:03 +0100 Subject: [PATCH 03/37] docs(path.rs): fix ends_with method --- src/libstd/path.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index b85a0dcec818..4fd263f96c47 100755 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1193,7 +1193,7 @@ impl Path { iter_after(self.components(), base.as_path().components()).is_some() } - /// Determines whether `base` is a suffix of `self`. + /// Determines whether `child` is a suffix of `self`. pub fn ends_with(&self, child: &P) -> bool where P: AsPath { iter_after(self.components().rev(), child.as_path().components().rev()).is_some() } From a037cdfcf159a6db80ddd95acd99a61b8441bbe6 Mon Sep 17 00:00:00 2001 From: David King Date: Wed, 4 Mar 2015 23:18:24 +0000 Subject: [PATCH 04/37] Fix broken link in old rust guide Having come back to rust recently after > 6months I was looking for docs on tasks and stumbled upon this broken link. --- src/doc/guide-tasks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md index 197559bef040..21217bf54d76 100644 --- a/src/doc/guide-tasks.md +++ b/src/doc/guide-tasks.md @@ -1,4 +1,4 @@ % The (old) Rust Threads and Communication Guide This content has moved into -[the Rust Programming Language book](book/tasks.html). +[the Rust Programming Language book](book/concurrency.html). From 0dfa9978cc57efc8eb51485fc3a333eafd1aa392 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Mar 2015 14:49:03 -0800 Subject: [PATCH 05/37] std: Stabilize portions of the `io` module The new `io` module has had some time to bake and this commit stabilizes some of the utilities associated with it. This commit also deprecates a number of `std::old_io::util` functions and structures. These items are now `#[stable]` * `Cursor` * `Cursor::{new, into_inner, get_ref, get_mut, position, set_position}` * Implementations of I/O traits for `Cursor` * Delegating implementations of I/O traits for references and `Box` pointers * Implementations of I/O traits for primitives like slices and `Vec` * `ReadExt::bytes` * `Bytes` (and impls) * `ReadExt::chain` * `Chain` (and impls) * `ReadExt::take` (and impls) * `BufReadExt::lines` * `Lines` (and impls) * `io::copy` * `io::{empty, Empty}` (and impls) * `io::{sink, Sink}` (and impls) * `io::{repeat, Repeat}` (and impls) These items remain `#[unstable]` * Core I/O traits. These may want a little bit more time to bake along with the commonly used methods like `read_to_end`. * `BufReadExt::split` - this function may be renamed to not conflict with `SliceExt::split`. * `Error` - there are a number of questions about its representation, `ErrorKind`, and usability. These items are now `#[deprecated]` in `old_io` * `LimitReader` - use `take` instead * `NullWriter` - use `io::sink` instead * `ZeroReader` - use `io::repeat` instead * `NullReader` - use `io::empty` instead * `MultiWriter` - use `broadcast` instead * `ChainedReader` - use `chain` instead * `TeeReader` - use `tee` instead * `copy` - use `io::copy` instead [breaking-change] --- src/librustc_driver/lib.rs | 1 + src/librustdoc/test.rs | 1 + src/libstd/io/cursor.rs | 20 ++++++++++-- src/libstd/io/impls.rs | 64 +++++++++++++++++++++++++++++--------- src/libstd/io/mod.rs | 32 +++++++++++++++++++ src/libstd/io/util.rs | 17 +++++++++- src/libstd/old_io/util.rs | 50 +++++++++++++++++++++++++++++ 7 files changed, 167 insertions(+), 18 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 15fae351ddbf..294899927848 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -769,6 +769,7 @@ fn parse_crate_attrs(sess: &Session, input: &Input) -> /// /// The diagnostic emitter yielded to the procedure should be used for reporting /// errors of the compiler. +#[allow(deprecated)] pub fn monitor(f: F) { const STACK_SIZE: uint = 8 * 1024 * 1024; // 8MB diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 43e8f44244e7..afe117961ff8 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -106,6 +106,7 @@ pub fn run(input: &str, 0 } +#[allow(deprecated)] fn runtest(test: &str, cratename: &str, libs: SearchPaths, externs: core::Externs, should_fail: bool, no_run: bool, as_test_harness: bool) { diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index b1779587528c..78f9222bde7a 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(missing_copy_implementations)] - use prelude::v1::*; use io::prelude::*; @@ -32,6 +30,7 @@ use slice; /// Implementations of the I/O traits for `Cursor` are not currently generic /// over `T` itself. Instead, specific implementations are provided for various /// in-memory buffer types like `Vec` and `&[u8]`. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Cursor { inner: T, pos: u64, @@ -39,26 +38,32 @@ pub struct Cursor { impl Cursor { /// Create a new cursor wrapping the provided underlying I/O object. + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: T) -> Cursor { Cursor { pos: 0, inner: inner } } /// Consume this cursor, returning the underlying value. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> T { self.inner } /// Get a reference to the underlying value in this cursor. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &T { &self.inner } /// Get a mutable reference to the underlying value in this cursor. /// /// Care should be taken to avoid modifying the internal I/O state of the /// underlying value as it may corrupt this cursor's position. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut T { &mut self.inner } /// Returns the current value of this cursor + #[stable(feature = "rust1", since = "1.0.0")] pub fn position(&self) -> u64 { self.pos } /// Sets the value of this cursor + #[stable(feature = "rust1", since = "1.0.0")] pub fn set_position(&mut self, pos: u64) { self.pos = pos; } } @@ -83,8 +88,11 @@ macro_rules! seek { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> io::Seek for Cursor<&'a [u8]> { seek!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> io::Seek for Cursor<&'a mut [u8]> { seek!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl io::Seek for Cursor> { seek!(); } macro_rules! read { @@ -97,8 +105,11 @@ macro_rules! read { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for Cursor<&'a [u8]> { read!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for Cursor<&'a mut [u8]> { read!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Cursor> { read!(); } macro_rules! buffer { @@ -111,10 +122,14 @@ macro_rules! buffer { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for Cursor<&'a [u8]> { buffer!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for Cursor<&'a mut [u8]> { buffer!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for Cursor> { buffer!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for Cursor<&'a mut [u8]> { fn write(&mut self, data: &[u8]) -> io::Result { let pos = cmp::min(self.pos, self.inner.len() as u64); @@ -125,6 +140,7 @@ impl<'a> Write for Cursor<&'a mut [u8]> { fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Cursor> { fn write(&mut self, buf: &[u8]) -> io::Result { // Make sure the internal buffer is as least as big as where we diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index 82b69ddebff6..c968415d3efd 100644 --- a/src/libstd/io/impls.rs +++ b/src/libstd/io/impls.rs @@ -22,57 +22,88 @@ use vec::Vec; // ============================================================================= // Forwarding implementations +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, R: Read + ?Sized> Read for &'a mut R { - fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } - - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result<()> { (**self).read_to_end(buf) } - + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (**self).read(buf) + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result<()> { + (**self).read_to_end(buf) + } fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> { (**self).read_to_string(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, W: Write + ?Sized> Write for &'a mut W { fn write(&mut self, buf: &[u8]) -> io::Result { (**self).write(buf) } - - fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { (**self).write_all(buf) } - - fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { (**self).write_fmt(fmt) } - fn flush(&mut self) -> io::Result<()> { (**self).flush() } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + (**self).write_all(buf) + } + fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { + (**self).write_fmt(fmt) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, S: Seek + ?Sized> Seek for &'a mut S { fn seek(&mut self, pos: SeekFrom) -> io::Result { (**self).seek(pos) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B { fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } - fn consume(&mut self, amt: usize) { (**self).consume(amt) } - fn read_until(&mut self, byte: u8, buf: &mut Vec) -> io::Result<()> { (**self).read_until(byte, buf) } - - fn read_line(&mut self, buf: &mut String) -> io::Result<()> { (**self).read_line(buf) } + fn read_line(&mut self, buf: &mut String) -> io::Result<()> { + (**self).read_line(buf) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Box { - fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (**self).read(buf) + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result<()> { + (**self).read_to_end(buf) + } + fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> { + (**self).read_to_string(buf) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Box { fn write(&mut self, buf: &[u8]) -> io::Result { (**self).write(buf) } fn flush(&mut self) -> io::Result<()> { (**self).flush() } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + (**self).write_all(buf) + } + fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { + (**self).write_fmt(fmt) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl Seek for Box { fn seek(&mut self, pos: SeekFrom) -> io::Result { (**self).seek(pos) } } +#[stable(feature = "rust1", since = "1.0.0")] impl BufRead for Box { fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } fn consume(&mut self, amt: usize) { (**self).consume(amt) } + fn read_until(&mut self, byte: u8, buf: &mut Vec) -> io::Result<()> { + (**self).read_until(byte, buf) + } + fn read_line(&mut self, buf: &mut String) -> io::Result<()> { + (**self).read_line(buf) + } } // ============================================================================= // In-memory buffer implementations +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a [u8] { fn read(&mut self, buf: &mut [u8]) -> io::Result { let amt = cmp::min(buf.len(), self.len()); @@ -83,11 +114,13 @@ impl<'a> Read for &'a [u8] { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for &'a [u8] { fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) } fn consume(&mut self, amt: usize) { *self = &self[amt..]; } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for &'a mut [u8] { fn write(&mut self, data: &[u8]) -> io::Result { let amt = cmp::min(data.len(), self.len()); @@ -108,6 +141,7 @@ impl<'a> Write for &'a mut [u8] { fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Vec { fn write(&mut self, buf: &[u8]) -> io::Result { self.push_all(buf); @@ -115,7 +149,7 @@ impl Write for Vec { } fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - try!(self.write(buf)); + self.push_all(buf); Ok(()) } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 5510c0203e6c..a91ab57c7e9a 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -237,11 +237,13 @@ pub trait Read { /// Extension methods for all instances of `Read`, typically imported through /// `std::io::prelude::*`. +#[unstable(feature = "io", reason = "may merge into the Read trait")] pub trait ReadExt: Read + Sized { /// Create a "by reference" adaptor for this instance of `Read`. /// /// The returned adaptor also implements `Read` and will simply borrow this /// current reader. + #[stable(feature = "rust1", since = "1.0.0")] fn by_ref(&mut self) -> &mut Self { self } /// Transform this `Read` instance to an `Iterator` over its bytes. @@ -250,6 +252,7 @@ pub trait ReadExt: Read + Sized { /// R::Err>`. The yielded item is `Ok` if a byte was successfully read and /// `Err` otherwise for I/O errors. EOF is mapped to returning `None` from /// this iterator. + #[stable(feature = "rust1", since = "1.0.0")] fn bytes(self) -> Bytes { Bytes { inner: self } } @@ -264,6 +267,9 @@ pub trait ReadExt: Read + Sized { /// /// Currently this adaptor will discard intermediate data read, and should /// be avoided if this is not desired. + #[unstable(feature = "io", reason = "the semantics of a partial read/write \ + of where errors happen is currently \ + unclear and may change")] fn chars(self) -> Chars { Chars { inner: self } } @@ -273,6 +279,7 @@ pub trait ReadExt: Read + Sized { /// The returned `Read` instance will first read all bytes from this object /// until EOF is encountered. Afterwards the output is equivalent to the /// output of `next`. + #[stable(feature = "rust1", since = "1.0.0")] fn chain(self, next: R) -> Chain { Chain { first: self, second: next, done_first: false } } @@ -283,6 +290,7 @@ pub trait ReadExt: Read + Sized { /// `limit` bytes, after which it will always return EOF (`Ok(0)`). Any /// read errors will not count towards the number of bytes read and future /// calls to `read` may succeed. + #[stable(feature = "rust1", since = "1.0.0")] fn take(self, limit: u64) -> Take { Take { inner: self, limit: limit } } @@ -293,6 +301,9 @@ pub trait ReadExt: Read + Sized { /// Whenever the returned `Read` instance is read it will write the read /// data to `out`. The current semantics of this implementation imply that /// a `write` error will not report how much data was initially read. + #[unstable(feature = "io", reason = "the semantics of a partial read/write \ + of where errors happen is currently \ + unclear and may change")] fn tee(self, out: W) -> Tee { Tee { reader: self, writer: out } } @@ -415,11 +426,13 @@ pub trait Write { /// Extension methods for all instances of `Write`, typically imported through /// `std::io::prelude::*`. +#[unstable(feature = "io", reason = "may merge into the Read trait")] pub trait WriteExt: Write + Sized { /// Create a "by reference" adaptor for this instance of `Write`. /// /// The returned adaptor also implements `Write` and will simply borrow this /// current writer. + #[stable(feature = "rust1", since = "1.0.0")] fn by_ref(&mut self) -> &mut Self { self } /// Creates a new writer which will write all data to both this writer and @@ -430,11 +443,15 @@ pub trait WriteExt: Write + Sized { /// implementation do not precisely track where errors happen. For example /// an error on the second call to `write` will not report that the first /// call to `write` succeeded. + #[unstable(feature = "io", reason = "the semantics of a partial read/write \ + of where errors happen is currently \ + unclear and may change")] fn broadcast(self, other: W) -> Broadcast { Broadcast { first: self, second: other } } } +#[stable(feature = "rust1", since = "1.0.0")] impl WriteExt for T {} /// An object implementing `Seek` internally has some form of cursor which can @@ -592,6 +609,8 @@ pub trait BufReadExt: BufRead + Sized { /// /// This function will yield errors whenever `read_until` would have also /// yielded an error. + #[unstable(feature = "io", reason = "may be renamed to not conflict with \ + SliceExt::split")] fn split(self, byte: u8) -> Split { Split { buf: self, delim: byte } } @@ -604,11 +623,13 @@ pub trait BufReadExt: BufRead + Sized { /// /// This function will yield errors whenever `read_string` would have also /// yielded an error. + #[stable(feature = "rust1", since = "1.0.0")] fn lines(self) -> Lines { Lines { buf: self } } } +#[stable(feature = "rust1", since = "1.0.0")] impl BufReadExt for T {} /// A `Write` adaptor which will write data to multiple locations. @@ -635,12 +656,14 @@ impl Write for Broadcast { /// Adaptor to chain together two instances of `Read`. /// /// For more information, see `ReadExt::chain`. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Chain { first: T, second: U, done_first: bool, } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Chain { fn read(&mut self, buf: &mut [u8]) -> Result { if !self.done_first { @@ -656,11 +679,13 @@ impl Read for Chain { /// Reader adaptor which limits the bytes read from an underlying reader. /// /// For more information, see `ReadExt::take`. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Take { inner: T, limit: u64, } +#[stable(feature = "rust1", since = "1.0.0")] impl Take { /// Returns the number of bytes that can be read before this instance will /// return EOF. @@ -669,9 +694,11 @@ impl Take { /// /// This instance may reach EOF after reading fewer bytes than indicated by /// this method if the underlying `Read` instance reaches EOF. + #[stable(feature = "rust1", since = "1.0.0")] pub fn limit(&self) -> u64 { self.limit } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Take { fn read(&mut self, buf: &mut [u8]) -> Result { // Don't call into inner reader at all at EOF because it may still block @@ -686,6 +713,7 @@ impl Read for Take { } } +#[stable(feature = "rust1", since = "1.0.0")] impl BufRead for Take { fn fill_buf(&mut self) -> Result<&[u8]> { let buf = try!(self.inner.fill_buf()); @@ -721,10 +749,12 @@ impl Read for Tee { /// A bridge from implementations of `Read` to an `Iterator` of `u8`. /// /// See `ReadExt::bytes` for more information. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Bytes { inner: R, } +#[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Bytes { type Item = Result; @@ -845,10 +875,12 @@ impl Iterator for Split { /// byte. /// /// See `BufReadExt::lines` for more information. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Lines { buf: B, } +#[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Lines { type Item = Result; diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 3d342137c62d..20426025257c 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -12,7 +12,7 @@ use prelude::v1::*; -use io::{self, Read, Write, ErrorKind}; +use io::{self, Read, Write, ErrorKind, BufRead}; /// Copies the entire contents of a reader into a writer. /// @@ -27,6 +27,7 @@ use io::{self, Read, Write, ErrorKind}; /// This function will return an error immediately if any call to `read` or /// `write` returns an error. All instances of `ErrorKind::Interrupted` are /// handled by this function and the underlying operation is retried. +#[stable(feature = "rust1", since = "1.0.0")] pub fn copy(r: &mut R, w: &mut W) -> io::Result { let mut buf = [0; super::DEFAULT_BUF_SIZE]; let mut written = 0; @@ -43,26 +44,37 @@ pub fn copy(r: &mut R, w: &mut W) -> io::Result { } /// A reader which is always at EOF. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Empty { _priv: () } /// Creates an instance of an empty reader. /// /// All reads from the returned reader will return `Ok(0)`. +#[stable(feature = "rust1", since = "1.0.0")] pub fn empty() -> Empty { Empty { _priv: () } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Empty { fn read(&mut self, _buf: &mut [u8]) -> io::Result { Ok(0) } } +#[stable(feature = "rust1", since = "1.0.0")] +impl BufRead for Empty { + fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } + fn consume(&mut self, _n: usize) {} +} /// A reader which infinitely yields one byte. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Repeat { byte: u8 } /// Creates an instance of a reader that infinitely repeats one byte. /// /// All reads from this reader will succeed by filling the specified buffer with /// the given byte. +#[stable(feature = "rust1", since = "1.0.0")] pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Repeat { fn read(&mut self, buf: &mut [u8]) -> io::Result { for slot in buf.iter_mut() { @@ -73,14 +85,17 @@ impl Read for Repeat { } /// A writer which will move data into the void. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Sink { _priv: () } /// Creates an instance of a writer which will successfully consume all data. /// /// All calls to `write` on the returned instance will return `Ok(buf.len())` /// and the contents of the buffer will not be inspected. +#[stable(feature = "rust1", since = "1.0.0")] pub fn sink() -> Sink { Sink { _priv: () } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Sink { fn write(&mut self, buf: &[u8]) -> io::Result { Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } diff --git a/src/libstd/old_io/util.rs b/src/libstd/old_io/util.rs index 8e49335ed546..839d2e7057b0 100644 --- a/src/libstd/old_io/util.rs +++ b/src/libstd/old_io/util.rs @@ -10,6 +10,8 @@ //! Utility implementations of Reader and Writer +#![allow(deprecated)] + use prelude::v1::*; use cmp; use old_io; @@ -17,13 +19,19 @@ use slice::bytes::MutableByteVector; /// Wraps a `Reader`, limiting the number of bytes that can be read from it. #[derive(Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::Take")] +#[unstable(feature = "old_io")] pub struct LimitReader { limit: uint, inner: R } +#[deprecated(since = "1.0.0", reason = "use std::io::Take")] +#[unstable(feature = "old_io")] impl LimitReader { /// Creates a new `LimitReader` + #[deprecated(since = "1.0.0", reason = "use std::io's take method instead")] + #[unstable(feature = "old_io")] pub fn new(r: R, limit: uint) -> LimitReader { LimitReader { limit: limit, inner: r } } @@ -41,6 +49,8 @@ impl LimitReader { pub fn limit(&self) -> uint { self.limit } } +#[deprecated(since = "1.0.0", reason = "use std::io's take method instead")] +#[unstable(feature = "old_io")] impl Reader for LimitReader { fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { if self.limit == 0 { @@ -57,6 +67,8 @@ impl Reader for LimitReader { } } +#[deprecated(since = "1.0.0", reason = "use std::io's take method instead")] +#[unstable(feature = "old_io")] impl Buffer for LimitReader { fn fill_buf<'a>(&'a mut self) -> old_io::IoResult<&'a [u8]> { let amt = try!(self.inner.fill_buf()); @@ -79,8 +91,12 @@ impl Buffer for LimitReader { /// A `Writer` which ignores bytes written to it, like /dev/null. #[derive(Copy, Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::sink() instead")] +#[unstable(feature = "old_io")] pub struct NullWriter; +#[deprecated(since = "1.0.0", reason = "use std::io::sink() instead")] +#[unstable(feature = "old_io")] impl Writer for NullWriter { #[inline] fn write_all(&mut self, _buf: &[u8]) -> old_io::IoResult<()> { Ok(()) } @@ -88,8 +104,12 @@ impl Writer for NullWriter { /// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero. #[derive(Copy, Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::repeat(0) instead")] +#[unstable(feature = "old_io")] pub struct ZeroReader; +#[deprecated(since = "1.0.0", reason = "use std::io::repeat(0) instead")] +#[unstable(feature = "old_io")] impl Reader for ZeroReader { #[inline] fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { @@ -98,6 +118,8 @@ impl Reader for ZeroReader { } } +#[deprecated(since = "1.0.0", reason = "use std::io::repeat(0) instead")] +#[unstable(feature = "old_io")] impl Buffer for ZeroReader { fn fill_buf<'a>(&'a mut self) -> old_io::IoResult<&'a [u8]> { static DATA: [u8; 64] = [0; 64]; @@ -109,8 +131,12 @@ impl Buffer for ZeroReader { /// A `Reader` which is always at EOF, like /dev/null. #[derive(Copy, Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::empty() instead")] +#[unstable(feature = "old_io")] pub struct NullReader; +#[deprecated(since = "1.0.0", reason = "use std::io::empty() instead")] +#[unstable(feature = "old_io")] impl Reader for NullReader { #[inline] fn read(&mut self, _buf: &mut [u8]) -> old_io::IoResult { @@ -118,6 +144,8 @@ impl Reader for NullReader { } } +#[deprecated(since = "1.0.0", reason = "use std::io::empty() instead")] +#[unstable(feature = "old_io")] impl Buffer for NullReader { fn fill_buf<'a>(&'a mut self) -> old_io::IoResult<&'a [u8]> { Err(old_io::standard_error(old_io::EndOfFile)) @@ -130,17 +158,23 @@ impl Buffer for NullReader { /// The `Writer`s are delegated to in order. If any `Writer` returns an error, /// that error is returned immediately and remaining `Writer`s are not called. #[derive(Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::Broadcast instead")] +#[unstable(feature = "old_io")] pub struct MultiWriter { writers: Vec } impl MultiWriter where W: Writer { /// Creates a new `MultiWriter` + #[deprecated(since = "1.0.0", reason = "use std::io's broadcast method instead")] + #[unstable(feature = "old_io")] pub fn new(writers: Vec) -> MultiWriter { MultiWriter { writers: writers } } } +#[deprecated(since = "1.0.0", reason = "use std::io::Broadcast instead")] +#[unstable(feature = "old_io")] impl Writer for MultiWriter where W: Writer { #[inline] fn write_all(&mut self, buf: &[u8]) -> old_io::IoResult<()> { @@ -162,6 +196,8 @@ impl Writer for MultiWriter where W: Writer { /// A `Reader` which chains input from multiple `Reader`s, reading each to /// completion before moving onto the next. #[derive(Clone, Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::Chain instead")] +#[unstable(feature = "old_io")] pub struct ChainedReader { readers: I, cur_reader: Option, @@ -169,12 +205,16 @@ pub struct ChainedReader { impl> ChainedReader { /// Creates a new `ChainedReader` + #[deprecated(since = "1.0.0", reason = "use std::io's chain method instead")] + #[unstable(feature = "old_io")] pub fn new(mut readers: I) -> ChainedReader { let r = readers.next(); ChainedReader { readers: readers, cur_reader: r } } } +#[deprecated(since = "1.0.0", reason = "use std::io::Chain instead")] +#[unstable(feature = "old_io")] impl> Reader for ChainedReader { fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { loop { @@ -201,13 +241,19 @@ impl> Reader for ChainedReader { /// A `Reader` which forwards input from another `Reader`, passing it along to /// a `Writer` as well. Similar to the `tee(1)` command. #[derive(Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::Tee instead")] +#[unstable(feature = "old_io")] pub struct TeeReader { reader: R, writer: W, } +#[deprecated(since = "1.0.0", reason = "use std::io::Tee instead")] +#[unstable(feature = "old_io")] impl TeeReader { /// Creates a new `TeeReader` + #[deprecated(since = "1.0.0", reason = "use std::io's tee method instead")] + #[unstable(feature = "old_io")] pub fn new(r: R, w: W) -> TeeReader { TeeReader { reader: r, writer: w } } @@ -220,6 +266,8 @@ impl TeeReader { } } +#[deprecated(since = "1.0.0", reason = "use std::io::Tee instead")] +#[unstable(feature = "old_io")] impl Reader for TeeReader { fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { self.reader.read(buf).and_then(|len| { @@ -229,6 +277,8 @@ impl Reader for TeeReader { } /// Copies all data from a `Reader` to a `Writer`. +#[deprecated(since = "1.0.0", reason = "use std::io's copy function instead")] +#[unstable(feature = "old_io")] pub fn copy(r: &mut R, w: &mut W) -> old_io::IoResult<()> { let mut buf = [0; super::DEFAULT_BUF_SIZE]; loop { From 9e28156551c1a2af3c47a0937290176ccc457703 Mon Sep 17 00:00:00 2001 From: Kang Seonghoon Date: Thu, 5 Mar 2015 16:35:43 +0900 Subject: [PATCH 06/37] rustdoc: Move sidebar items into shared JavaScript. It had been a source of huge bloat in rustdoc outputs. Of course, we can simply disable compiler docs (as `rustc` generates over 90M of HTML) but this approach fares better even after such decision. Each directory now has `sidebar-items.js`, which immediately calls `initSidebarItems` with a JSON sidebar data. This file is shared throughout every item in the sidebar. The current item is highlighted via a separate JS snippet (`window.sidebarCurrent`). The JS file is designed to be loaded asynchronously, as the sidebar is rendered before the content and slow sidebar loading blocks the entire rendering. For the minimal accessibility without JS, links to the parent items are left in HTML. In the future, it might also be possible to integrate crates data with the same fashion: `sidebar-items.js` at the root path will do that. (Currently rustdoc skips writing JS in that case.) This has a huge impact on the size of rustdoc outputs. Originally it was 326MB uncompressed (37.7MB gzipped, 6.1MB xz compressed); it is 169MB uncompressed (11.9MB gzipped, 5.9MB xz compressed) now. The sidebar JS only takes 10MB uncompressed & 0.3MB gzipped. --- src/librustdoc/html/render.rs | 85 ++++++++++++----------------- src/librustdoc/html/static/main.js | 86 ++++++++++++++++++++++-------- 2 files changed, 99 insertions(+), 72 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 735487611dc5..a9a9d0f76948 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -65,12 +65,10 @@ use html::item_type::ItemType; use html::layout; use html::markdown::Markdown; use html::markdown; -use html::escape::Escape; use stability_summary; /// A pair of name and its optional document. -#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)] -pub struct NameDoc(String, Option); +pub type NameDoc = (String, Option); /// Major driving force in all rustdoc rendering. This contains information /// about where in the tree-like hierarchy rendering is occurring and controls @@ -96,12 +94,6 @@ pub struct Context { /// This describes the layout of each page, and is not modified after /// creation of the context (contains info like the favicon and added html). pub layout: layout::Layout, - /// This map is a list of what should be displayed on the sidebar of the - /// current page. The key is the section header (traits, modules, - /// functions), and the value is the list of containers belonging to this - /// header. This map will change depending on the surrounding context of the - /// page. - pub sidebar: HashMap>, /// This flag indicates whether [src] links should be generated or not. If /// the source files are present in the html rendering, then this will be /// `true`. @@ -265,7 +257,6 @@ pub fn run(mut krate: clean::Crate, passes: passes, current: Vec::new(), root_path: String::new(), - sidebar: HashMap::new(), layout: layout::Layout { logo: "".to_string(), favicon: "".to_string(), @@ -1227,7 +1218,16 @@ impl Context { clean::ModuleItem(m) => m, _ => unreachable!() }; - this.sidebar = this.build_sidebar(&m); + + // render sidebar-items.js used throughout this module + { + let items = this.build_sidebar_items(&m); + let js_dst = this.dst.join("sidebar-items.js"); + let mut js_out = BufferedWriter::new(try!(File::create(&js_dst))); + try!(write!(&mut js_out, "initSidebarItems({});", + json::as_json(&items))); + } + for item in m.items { f(this,item); } @@ -1247,15 +1247,11 @@ impl Context { } } - fn build_sidebar(&self, m: &clean::Module) -> HashMap> { + fn build_sidebar_items(&self, m: &clean::Module) -> HashMap> { let mut map = HashMap::new(); for item in &m.items { if self.ignore_private_item(item) { continue } - // avoid putting foreign items to the sidebar. - if let &clean::ForeignFunctionItem(..) = &item.inner { continue } - if let &clean::ForeignStaticItem(..) = &item.inner { continue } - let short = shortty(item).to_static_str(); let myname = match item.name { None => continue, @@ -1264,7 +1260,7 @@ impl Context { let short = short.to_string(); let v = map.entry(short).get().unwrap_or_else( |vacant_entry| vacant_entry.insert(Vec::with_capacity(1))); - v.push(NameDoc(myname, Some(shorter_line(item.doc_value())))); + v.push((myname, Some(shorter_line(item.doc_value())))); } for (_, items) in &mut map { @@ -2211,9 +2207,11 @@ impl<'a> fmt::Display for Sidebar<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let cx = self.cx; let it = self.item; + let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; + + // this is not rendered via JS, as that would hamper the accessibility try!(write!(fmt, "

")); - let len = cx.current.len() - if it.is_mod() {1} else {0}; - for (i, name) in cx.current.iter().take(len).enumerate() { + for (i, name) in cx.current.iter().take(parentlen).enumerate() { if i > 0 { try!(write!(fmt, "::")); } @@ -2223,40 +2221,25 @@ impl<'a> fmt::Display for Sidebar<'a> { } try!(write!(fmt, "

")); - fn block(w: &mut fmt::Formatter, short: &str, longty: &str, - cur: &clean::Item, cx: &Context) -> fmt::Result { - let items = match cx.sidebar.get(short) { - Some(items) => items, - None => return Ok(()) - }; - try!(write!(w, "

{}

", short, longty)); - for &NameDoc(ref name, ref doc) in items { - let curty = shortty(cur).to_static_str(); - let class = if cur.name.as_ref().unwrap() == name && - short == curty { "current" } else { "" }; - try!(write!(w, "{name}", - ty = short, - class = class, - href = if curty == "mod" {"../"} else {""}, - path = if short == "mod" { - format!("{}/index.html", name) - } else { - format!("{}.{}.html", short, name) - }, - title = Escape(doc.as_ref().unwrap()), - name = name)); - } - try!(write!(w, "
")); - Ok(()) + // sidebar refers to the enclosing module, not this module + let relpath = if shortty(it) == ItemType::Module { "../" } else { "" }; + try!(write!(fmt, + "", + name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), + ty = shortty(it).to_static_str(), + path = relpath)); + if parentlen == 0 { + // there is no sidebar-items.js beyond the crate root path + // FIXME maybe dynamic crate loading can be merged here + } else { + try!(write!(fmt, "", + path = relpath)); } - try!(block(fmt, "mod", "Modules", it, cx)); - try!(block(fmt, "struct", "Structs", it, cx)); - try!(block(fmt, "enum", "Enums", it, cx)); - try!(block(fmt, "trait", "Traits", it, cx)); - try!(block(fmt, "fn", "Functions", it, cx)); - try!(block(fmt, "macro", "Macros", it, cx)); Ok(()) } } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index aac3985f0cc9..a9b233dd128d 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -15,6 +15,27 @@ "use strict"; var resizeTimeout, interval; + // This mapping table should match the discriminants of + // `rustdoc::html::item_type::ItemType` type in Rust. + var itemTypes = ["mod", + "externcrate", + "import", + "struct", + "enum", + "fn", + "type", + "static", + "trait", + "impl", + "tymethod", + "method", + "structfield", + "variant", + "macro", + "primitive", + "associatedtype", + "constant"]; + $('.js-only').removeClass('js-only'); function getQueryStringParams() { @@ -552,27 +573,6 @@ showResults(results); } - // This mapping table should match the discriminants of - // `rustdoc::html::item_type::ItemType` type in Rust. - var itemTypes = ["mod", - "externcrate", - "import", - "struct", - "enum", - "fn", - "type", - "static", - "trait", - "impl", - "tymethod", - "method", - "structfield", - "variant", - "macro", - "primitive", - "associatedtype", - "constant"]; - function itemTypeFromName(typename) { for (var i = 0; i < itemTypes.length; ++i) { if (itemTypes[i] === typename) return i; @@ -708,6 +708,50 @@ window.initSearch = initSearch; + // delayed sidebar rendering. + function initSidebarItems(items) { + var sidebar = $('.sidebar'); + var current = window.sidebarCurrent; + + function block(shortty, longty) { + var filtered = items[shortty]; + if (!filtered) return; + + var div = $('
').attr('class', 'block ' + shortty); + div.append($('

').text(longty)); + + for (var i = 0; i < filtered.length; ++i) { + var item = filtered[i]; + var name = item[0]; + var desc = item[1]; // can be null + + var klass = shortty; + if (name === current.name && shortty == current.ty) { + klass += ' current'; + } + var path; + if (shortty === 'mod') { + path = name + '/index.html'; + } else { + path = shortty + '.' + name + '.html'; + } + div.append($('', {'href': current.relpath + path, + 'title': desc, + 'class': klass}).text(name)); + } + sidebar.append(div); + } + + block("mod", "Modules"); + block("struct", "Structs"); + block("enum", "Enums"); + block("trait", "Traits"); + block("fn", "Functions"); + block("macro", "Macros"); + } + + window.initSidebarItems = initSidebarItems; + window.register_implementors = function(imp) { var list = $('#implementors-list'); var libs = Object.getOwnPropertyNames(imp); From 3f4181a6e5c41a8d9d8ee434e6b75e7bef315998 Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Thu, 26 Feb 2015 20:26:36 +0200 Subject: [PATCH 07/37] iOS: open file on aarch64 breaks permissions According to Apple arm64 calling convention varargs always are passed through stack. Since `open` is actually a vararg function on Darwin's, it means that older declaration caused permissions to be taken from stack, while passed through register => it set file permissions to garbage and it was simply impossible to read/delete files after they were created. They way this commit handles it is to preserve compatibility with existing code - it simply creates a shim unsafe function so all existing callers continue work as nothing happened. --- src/liblibc/lib.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 74a95b3aba05..1a5000161759 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -5003,9 +5003,36 @@ pub mod funcs { use types::os::arch::c95::{c_char, c_int}; use types::os::arch::posix88::mode_t; + mod open_shim { + extern { + #[cfg(any(target_os = "macos", + target_os = "ios"))] + pub fn open(path: *const ::c_char, oflag: ::c_int, ...) + -> ::c_int; + + #[cfg(not(any(target_os = "macos", + target_os = "ios")))] + pub fn open(path: *const ::c_char, oflag: ::c_int, mode: ::mode_t) + -> ::c_int; + } + } + + #[cfg(any(target_os = "macos", + target_os = "ios"))] + #[inline] + pub unsafe extern fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int { + use types::os::arch::c95::c_uint; + open_shim::open(path, oflag, mode as c_uint) + } + + #[cfg(not(any(target_os = "macos", + target_os = "ios")))] + #[inline] + pub unsafe extern fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int { + open_shim::open(path, oflag, mode) + } + extern { - pub fn open(path: *const c_char, oflag: c_int, mode: mode_t) - -> c_int; pub fn creat(path: *const c_char, mode: mode_t) -> c_int; pub fn fcntl(fd: c_int, cmd: c_int, ...) -> c_int; } From 7bcf7fb5009b5dbdfa1a611fe464ca0de43c5a49 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Wed, 4 Mar 2015 21:32:33 +1100 Subject: [PATCH 08/37] Use more associated types in core::iter. This concretely improves type inference of some cases (see included test). I assume the compiler struggles to reason about multiple layers of generic type parameters (even with associated-type equalities) but *can* understand pure associated types, since they are always directly computable from the input types. --- src/libcore/iter.rs | 94 ++++++++++--------- .../run-pass/iter-cloned-type-inference.rs | 25 +++++ 2 files changed, 73 insertions(+), 46 deletions(-) create mode 100644 src/test/run-pass/iter-cloned-type-inference.rs diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 9495bc2e19d6..07203ad7d194 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -1279,14 +1279,14 @@ pub struct Cloned { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Cloned where - T: Clone, - D: Deref, - I: Iterator, +impl Iterator for Cloned where + I: Iterator, + I::Item: Deref, + ::Target: Clone { - type Item = T; + type Item = ::Target; - fn next(&mut self) -> Option { + fn next(&mut self) -> Option<::Item> { self.it.next().cloned() } @@ -1296,28 +1296,28 @@ impl Iterator for Cloned where } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Cloned where - T: Clone, - D: Deref, - I: DoubleEndedIterator, +impl DoubleEndedIterator for Cloned where + I: DoubleEndedIterator, + I::Item: Deref, + ::Target: Clone { - fn next_back(&mut self) -> Option { + fn next_back(&mut self) -> Option<::Item> { self.it.next_back().cloned() } } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Cloned where - T: Clone, - D: Deref, - I: ExactSizeIterator, +impl ExactSizeIterator for Cloned where + I: ExactSizeIterator, + I::Item: Deref, + ::Target: Clone {} #[unstable(feature = "core", reason = "trait is experimental")] -impl RandomAccessIterator for Cloned where - T: Clone, - D: Deref, - I: RandomAccessIterator +impl RandomAccessIterator for Cloned where + I: RandomAccessIterator, + I::Item: Deref, + ::Target: Clone { #[inline] fn indexable(&self) -> usize { @@ -1325,7 +1325,7 @@ impl RandomAccessIterator for Cloned where } #[inline] - fn idx(&mut self, index: usize) -> Option { + fn idx(&mut self, index: usize) -> Option<::Item> { self.it.idx(index).cloned() } } @@ -1400,11 +1400,14 @@ pub struct Chain { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Chain where A: Iterator, B: Iterator { - type Item = T; +impl Iterator for Chain where + A: Iterator, + B: Iterator +{ + type Item = A::Item; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { if self.flag { self.b.next() } else { @@ -1434,12 +1437,12 @@ impl Iterator for Chain where A: Iterator, B: Iterator DoubleEndedIterator for Chain where - A: DoubleEndedIterator, - B: DoubleEndedIterator, +impl DoubleEndedIterator for Chain where + A: DoubleEndedIterator, + B: DoubleEndedIterator, { #[inline] - fn next_back(&mut self) -> Option { + fn next_back(&mut self) -> Option { match self.b.next_back() { Some(x) => Some(x), None => self.a.next_back() @@ -1448,9 +1451,9 @@ impl DoubleEndedIterator for Chain where } #[unstable(feature = "core", reason = "trait is experimental")] -impl RandomAccessIterator for Chain where - A: RandomAccessIterator, - B: RandomAccessIterator, +impl RandomAccessIterator for Chain where + A: RandomAccessIterator, + B: RandomAccessIterator, { #[inline] fn indexable(&self) -> usize { @@ -1459,7 +1462,7 @@ impl RandomAccessIterator for Chain where } #[inline] - fn idx(&mut self, index: usize) -> Option { + fn idx(&mut self, index: usize) -> Option { let len = self.a.indexable(); if index < len { self.a.idx(index) @@ -1479,14 +1482,12 @@ pub struct Zip { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Zip where - A: Iterator, - B: Iterator, +impl Iterator for Zip where A: Iterator, B: Iterator { - type Item = (T, U); + type Item = (A::Item, B::Item); #[inline] - fn next(&mut self) -> Option<(T, U)> { + fn next(&mut self) -> Option<(A::Item, B::Item)> { match self.a.next() { None => None, Some(x) => match self.b.next() { @@ -1515,12 +1516,12 @@ impl Iterator for Zip where } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Zip where - A: DoubleEndedIterator + ExactSizeIterator, - B: DoubleEndedIterator + ExactSizeIterator, +impl DoubleEndedIterator for Zip where + A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator, { #[inline] - fn next_back(&mut self) -> Option<(T, U)> { + fn next_back(&mut self) -> Option<(A::Item, B::Item)> { let a_sz = self.a.len(); let b_sz = self.b.len(); if a_sz != b_sz { @@ -1540,9 +1541,9 @@ impl DoubleEndedIterator for Zip where } #[unstable(feature = "core", reason = "trait is experimental")] -impl RandomAccessIterator for Zip where - A: RandomAccessIterator, - B: RandomAccessIterator, +impl RandomAccessIterator for Zip where + A: RandomAccessIterator, + B: RandomAccessIterator { #[inline] fn indexable(&self) -> usize { @@ -1550,7 +1551,7 @@ impl RandomAccessIterator for Zip where } #[inline] - fn idx(&mut self, index: usize) -> Option<(T, U)> { + fn idx(&mut self, index: usize) -> Option<(A::Item, B::Item)> { match self.a.idx(index) { None => None, Some(x) => match self.b.idx(index) { @@ -2071,8 +2072,9 @@ pub struct Scan { } #[stable(feature = "rust1", since = "1.0.0")] -impl, St, F> Iterator for Scan where - F: FnMut(&mut St, A) -> Option, +impl Iterator for Scan where + I: Iterator, + F: FnMut(&mut St, I::Item) -> Option, { type Item = B; diff --git a/src/test/run-pass/iter-cloned-type-inference.rs b/src/test/run-pass/iter-cloned-type-inference.rs new file mode 100644 index 000000000000..6ce226bbecac --- /dev/null +++ b/src/test/run-pass/iter-cloned-type-inference.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test to see that the element type of .cloned() can be inferred +// properly. Previously this would fail to deduce the type of `sum`. + +#![feature(core)] + +use std::iter::AdditiveIterator; + +fn square_sum(v: &[i64]) -> i64 { + let sum = v.iter().cloned().sum(); + sum * sum +} + +fn main() { + assert_eq!(36, square_sum(&[1,2,3])); +} From 18f1e40eaaf7ccde1333fbdfc9f15c4cf462a2a4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 5 Mar 2015 13:30:30 +0100 Subject: [PATCH 09/37] doc example does nothing --- src/libcollections/str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 599b92d05ddd..f37f93a3e519 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1083,7 +1083,7 @@ pub trait StrExt: Index { /// /// let s = "中华Việt Nam"; /// let mut i = s.len(); - /// while i < 0 { + /// while i > 0 { /// let CharRange {ch, next} = s.char_range_at_reverse(i); /// println!("{}: {}", i, ch); /// i = next; From e316c662f8ac029704922baa53a0831da031aea5 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 5 Mar 2015 15:00:25 +0100 Subject: [PATCH 10/37] debuginfo: Add `debuginfo::with_source_location_override()` function... ... and use it to fix a debug-location issue with constants. --- src/librustc_trans/trans/consts.rs | 2 +- src/librustc_trans/trans/debuginfo.rs | 37 +++++++++++++ src/librustc_trans/trans/expr.rs | 10 +++- src/test/debuginfo/constant-debug-locs.rs | 67 +++++++++++++++++++++++ 4 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 src/test/debuginfo/constant-debug-locs.rs diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index a39f5d42b555..39b430b7ad51 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -173,7 +173,7 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, &**expr } else { ccx.sess().span_bug(ref_expr.span, - &format!("get_const_val given non-constant item {}", + &format!("get_const_expr given non-constant item {}", item.repr(ccx.tcx()))); } } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index f3b7058336b2..ab35a33cfdd5 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -695,6 +695,7 @@ struct FunctionDebugContextData { fn_metadata: DISubprogram, argument_counter: Cell, source_locations_enabled: Cell, + source_location_override: Cell, } enum VariableAccess<'a> { @@ -1174,6 +1175,12 @@ pub fn set_source_location(fcx: &FunctionContext, return; } FunctionDebugContext::RegularContext(box ref function_debug_context) => { + if function_debug_context.source_location_override.get() { + // Just ignore any attempts to set a new debug location while + // the override is active. + return; + } + let cx = fcx.ccx; debug!("set_source_location: {}", cx.sess().codemap().span_to_string(span)); @@ -1192,6 +1199,35 @@ pub fn set_source_location(fcx: &FunctionContext, } } +/// This function makes sure that all debug locations emitted while executing +/// `wrapped_function` are set to the given `debug_loc`. +pub fn with_source_location_override(fcx: &FunctionContext, + debug_loc: DebugLoc, + wrapped_function: F) -> R + where F: FnOnce() -> R +{ + match fcx.debug_context { + FunctionDebugContext::DebugInfoDisabled => { + wrapped_function() + } + FunctionDebugContext::FunctionWithoutDebugInfo => { + set_debug_location(fcx.ccx, UnknownLocation); + wrapped_function() + } + FunctionDebugContext::RegularContext(box ref function_debug_context) => { + if function_debug_context.source_location_override.get() { + wrapped_function() + } else { + debug_loc.apply(fcx); + function_debug_context.source_location_override.set(true); + let result = wrapped_function(); + function_debug_context.source_location_override.set(false); + result + } + } + } +} + /// Clears the current debug location. /// /// Instructions generated hereafter won't be assigned a source location. @@ -1412,6 +1448,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn_metadata: fn_metadata, argument_counter: Cell::new(1), source_locations_enabled: Cell::new(false), + source_location_override: Cell::new(false), }; diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 60455119d587..96d3e16d253b 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -147,7 +147,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::ExprPath(..) => { match bcx.def(expr.id) { def::DefConst(did) => { - let expr = consts::get_const_expr(bcx.ccx(), did, expr); + let const_expr = consts::get_const_expr(bcx.ccx(), did, expr); // Temporarily get cleanup scopes out of the way, // as they require sub-expressions to be contained // inside the current AST scope. @@ -155,7 +155,13 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // can't have destructors. let scopes = mem::replace(&mut *bcx.fcx.scopes.borrow_mut(), vec![]); - bcx = trans_into(bcx, expr, dest); + // Lock emitted debug locations to the location of + // the constant reference expression. + debuginfo::with_source_location_override(bcx.fcx, + expr.debug_loc(), + || { + bcx = trans_into(bcx, const_expr, dest) + }); let scopes = mem::replace(&mut *bcx.fcx.scopes.borrow_mut(), scopes); assert!(scopes.is_empty()); diff --git a/src/test/debuginfo/constant-debug-locs.rs b/src/test/debuginfo/constant-debug-locs.rs new file mode 100644 index 000000000000..24332e317750 --- /dev/null +++ b/src/test/debuginfo/constant-debug-locs.rs @@ -0,0 +1,67 @@ +// Copyright 2013-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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-android: FIXME(#10381) +// min-lldb-version: 310 + +// compile-flags:-g + +#![allow(unused_variables)] +#![allow(dead_code)] +#![omit_gdb_pretty_printer_section] + +// This test makes sure that the compiler doesn't crash when trying to assign +// debug locations to const-expressions. + +use std::sync::MUTEX_INIT; +use std::cell::UnsafeCell; + +const CONSTANT: u64 = 3 + 4; + +struct Struct { + a: isize, + b: usize, +} +const STRUCT: Struct = Struct { a: 1, b: 2 }; + +struct TupleStruct(u32); +const TUPLE_STRUCT: TupleStruct = TupleStruct(4); + +enum Enum { + Variant1(char), + Variant2 { a: u8 }, + Variant3 +} + +const VARIANT1: Enum = Enum::Variant1('v'); +const VARIANT2: Enum = Enum::Variant2 { a: 2 }; +const VARIANT3: Enum = Enum::Variant3; + +const STRING: &'static str = "String"; + +const VEC: [u32; 8] = [0; 8]; + +const NESTED: (Struct, TupleStruct) = (STRUCT, TUPLE_STRUCT); + +const UNSAFE_CELL: UnsafeCell = UnsafeCell { value: false }; + +fn main() { + let mut _constant = CONSTANT; + let mut _struct = STRUCT; + let mut _tuple_struct = TUPLE_STRUCT; + let mut _variant1 = VARIANT1; + let mut _variant2 = VARIANT2; + let mut _variant3 = VARIANT3; + let mut _string = STRING; + let mut _vec = VEC; + let mut _nested = NESTED; + let mut _extern = MUTEX_INIT; + let mut _unsafe_cell = UNSAFE_CELL; +} From 4a6fb45ee1c51a67d75d99244446868b36f22cc6 Mon Sep 17 00:00:00 2001 From: Kang Seonghoon Date: Thu, 5 Mar 2015 23:10:15 +0900 Subject: [PATCH 11/37] rustdoc: Reworded comments to give the rationale for JS. --- src/librustdoc/html/render.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index a9a9d0f76948..0edeff71364f 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2209,7 +2209,14 @@ impl<'a> fmt::Display for Sidebar<'a> { let it = self.item; let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; - // this is not rendered via JS, as that would hamper the accessibility + // the sidebar is designed to display sibling functions, modules and + // other miscellaneous informations. since there are lots of sibling + // items (and that causes quadratic growth in large modules), + // we refactor common parts into a shared JavaScript file per module. + // still, we don't move everything into JS because we want to preserve + // as much HTML as possible in order to allow non-JS-enabled browsers + // to navigate the documentation (though slightly inefficiently). + try!(write!(fmt, "
' panicked at 'arithmetic operation overflowed' +// compile-flags: -C debug-assertions // (Work around constant-evaluation) fn value() -> u8 { 200 } diff --git a/src/test/run-fail/overflowing-mul.rs b/src/test/run-fail/overflowing-mul.rs index b18d99cd232e..5d2f53962406 100644 --- a/src/test/run-fail/overflowing-mul.rs +++ b/src/test/run-fail/overflowing-mul.rs @@ -9,6 +9,7 @@ // except according to those terms. // error-pattern:thread '
' panicked at 'arithmetic operation overflowed' +// compile-flags: -C debug-assertions // (Work around constant-evaluation) fn value() -> u8 { 200 } diff --git a/src/test/run-fail/overflowing-sub.rs b/src/test/run-fail/overflowing-sub.rs index ee32291eca6b..b089dccbaa52 100644 --- a/src/test/run-fail/overflowing-sub.rs +++ b/src/test/run-fail/overflowing-sub.rs @@ -9,6 +9,7 @@ // except according to those terms. // error-pattern:thread '
' panicked at 'arithmetic operation overflowed' +// compile-flags: -C debug-assertions // (Work around constant-evaluation) fn value() -> u8 { 42 } diff --git a/src/test/run-make/debug-assertions/Makefile b/src/test/run-make/debug-assertions/Makefile new file mode 100644 index 000000000000..712975627686 --- /dev/null +++ b/src/test/run-make/debug-assertions/Makefile @@ -0,0 +1,21 @@ +-include ../tools.mk + +all: + $(RUSTC) debug.rs -C debug-assertions=no + $(call RUN,debug) good + $(RUSTC) debug.rs -C opt-level=0 + $(call RUN,debug) bad + $(RUSTC) debug.rs -C opt-level=1 + $(call RUN,debug) good + $(RUSTC) debug.rs -C opt-level=2 + $(call RUN,debug) good + $(RUSTC) debug.rs -C opt-level=3 + $(call RUN,debug) good + $(RUSTC) debug.rs -O + $(call RUN,debug) good + $(RUSTC) debug.rs + $(call RUN,debug) bad + $(RUSTC) debug.rs -C debug-assertions=yes -O + $(call RUN,debug) bad + $(RUSTC) debug.rs -C debug-assertions=yes -C opt-level=1 + $(call RUN,debug) bad diff --git a/src/test/run-make/debug-assertions/debug.rs b/src/test/run-make/debug-assertions/debug.rs new file mode 100644 index 000000000000..a0ccc75afd05 --- /dev/null +++ b/src/test/run-make/debug-assertions/debug.rs @@ -0,0 +1,42 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(warnings)] + +use std::env; +use std::thread; + +fn main() { + let should_fail = env::args().nth(1) == Some("bad".to_string()); + + assert_eq!(thread::spawn(debug_assert_eq).join().is_err(), should_fail); + assert_eq!(thread::spawn(debug_assert).join().is_err(), should_fail); + assert_eq!(thread::spawn(overflow).join().is_err(), should_fail); +} + +fn debug_assert_eq() { + let mut hit1 = false; + let mut hit2 = false; + debug_assert_eq!({ hit1 = true; 1 }, { hit2 = true; 2 }); + assert!(!hit1); + assert!(!hit2); +} + +fn debug_assert() { + let mut hit = false; + debug_assert!({ hit = true; false }); + assert!(!hit); +} + +fn overflow() { + fn add(a: u8, b: u8) -> u8 { a + b } + + add(200u8, 200u8); +} diff --git a/src/test/run-pass/conditional-debug-macro-off.rs b/src/test/run-pass/conditional-debug-macro-off.rs index b5a5f57d07ab..90142350772b 100644 --- a/src/test/run-pass/conditional-debug-macro-off.rs +++ b/src/test/run-pass/conditional-debug-macro-off.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: --cfg ndebug +// compile-flags: -C debug-assertions=no // exec-env:RUST_LOG=conditional-debug-macro-off=4 #[macro_use] diff --git a/src/test/run-pass/logging-enabled-debug.rs b/src/test/run-pass/logging-enabled-debug.rs index 262d9b21eb48..dfc927282706 100644 --- a/src/test/run-pass/logging-enabled-debug.rs +++ b/src/test/run-pass/logging-enabled-debug.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:--cfg ndebug +// compile-flags:-C debug-assertions=no // exec-env:RUST_LOG=logging-enabled-debug=debug #[macro_use] diff --git a/src/test/run-pass/logging-separate-lines.rs b/src/test/run-pass/logging-separate-lines.rs index 8526dfe72da1..82a155b11730 100644 --- a/src/test/run-pass/logging-separate-lines.rs +++ b/src/test/run-pass/logging-separate-lines.rs @@ -10,6 +10,7 @@ // ignore-windows // exec-env:RUST_LOG=debug +// compile-flags:-C debug-assertions=y #[macro_use] extern crate log; From 628f5d29c3b93bbd590e08dc2c69f842a18d1231 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 2 Mar 2015 10:46:05 -0800 Subject: [PATCH 19/37] std: Stabilize the `ffi` module The two main sub-modules, `c_str` and `os_str`, have now had some time to bake in the standard library. This commits performs a sweep over the modules adding various stability tags. The following APIs are now marked `#[stable]` * `OsString` * `OsStr` * `OsString::from_string` * `OsString::from_str` * `OsString::new` * `OsString::into_string` * `OsString::push` (renamed from `push_os_str`, added an `AsOsStr` bound) * various trait implementations for `OsString` * `OsStr::from_str` * `OsStr::to_str` * `OsStr::to_string_lossy` * `OsStr::to_os_string` * various trait implementations for `OsStr` * `CString` * `CStr` * `NulError` * `CString::new` - this API's implementation may change as a result of rust-lang/rfcs#912 but the usage of `CString::new(thing)` looks like it is unlikely to change. Additionally, the `IntoBytes` bound is also likely to change but the set of implementors for the trait will not change (despite the trait perhaps being renamed). * `CString::from_vec_unchecked` * `CString::as_bytes` * `CString::as_bytes_with_nul` * `NulError::nul_position` * `NulError::into_vec` * `CStr::from_ptr` * `CStr::as_ptr` * `CStr::to_bytes` * `CStr::to_bytes_with_nul` * various trait implementations for `CStr` The following APIs remain `#[unstable]` * `OsStr*Ext` traits remain unstable as the organization of `os::platform` is uncertain still and the traits may change location. * `AsOsStr` remains unstable as generic conversion traits are likely to be rethought soon. The following APIs were deprecated * `OsString::push_os_str` is now called `push` and takes `T: AsOsStr` instead (a superset of the previous functionality). --- src/compiletest/compiletest.rs | 1 - src/compiletest/runtest.rs | 9 +++---- src/librustc/lib.rs | 1 - src/librustc_driver/lib.rs | 1 - src/librustc_trans/back/link.rs | 8 +++--- src/librustc_trans/lib.rs | 2 -- src/librustdoc/html/render.rs | 3 +-- src/libstd/ffi/c_str.rs | 28 ++++++++++++++++++++ src/libstd/ffi/mod.rs | 11 +++++--- src/libstd/ffi/os_str.rs | 46 +++++++++++++++++++++++++++++---- src/libstd/path.rs | 8 +++--- 11 files changed, 89 insertions(+), 29 deletions(-) diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index b9e6f1842eea..a5d087b6dd2d 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -22,7 +22,6 @@ #![feature(unicode)] #![feature(core)] #![feature(path)] -#![feature(os)] #![feature(io)] #![feature(fs)] #![feature(net)] diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 7fb1a436ba38..04714b50fc02 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -20,7 +20,6 @@ use procsrv; use util::logv; use std::env; -use std::ffi::OsStr; use std::fmt; use std::fs::{self, File}; use std::io::BufReader; @@ -1323,7 +1322,7 @@ fn make_exe_name(config: &Config, testfile: &Path) -> PathBuf { let mut f = output_base_name(config, testfile); if !env::consts::EXE_SUFFIX.is_empty() { let mut fname = f.file_name().unwrap().to_os_string(); - fname.push_os_str(OsStr::from_str(env::consts::EXE_SUFFIX)); + fname.push(env::consts::EXE_SUFFIX); f.set_file_name(&fname); } f @@ -1433,7 +1432,7 @@ fn make_out_name(config: &Config, testfile: &Path, extension: &str) -> PathBuf { fn aux_output_dir_name(config: &Config, testfile: &Path) -> PathBuf { let f = output_base_name(config, testfile); let mut fname = f.file_name().unwrap().to_os_string(); - fname.push_os_str(OsStr::from_str("libaux")); + fname.push("libaux"); f.with_file_name(&fname) } @@ -1647,8 +1646,8 @@ fn append_suffix_to_stem(p: &Path, suffix: &str) -> PathBuf { p.to_path_buf() } else { let mut stem = p.file_stem().unwrap().to_os_string(); - stem.push_os_str(OsStr::from_str("-")); - stem.push_os_str(OsStr::from_str(suffix)); + stem.push("-"); + stem.push(suffix); p.with_file_name(&stem) } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 2d542eafbe1a..2c426a3e7fe2 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -38,7 +38,6 @@ #![feature(unsafe_destructor)] #![feature(staged_api)] #![feature(std_misc)] -#![feature(os)] #![feature(path)] #![feature(fs)] #![feature(io)] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index aa8b7c7785d2..6fa8cca23e10 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -29,7 +29,6 @@ #![feature(int_uint)] #![feature(old_io)] #![feature(libc)] -#![feature(os)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 1e84bc4b8e0b..21c738aa4a70 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -27,7 +27,7 @@ use util::common::time; use util::ppaux; use util::sha2::{Digest, Sha256}; -use std::ffi::{AsOsStr, OsString}; +use std::ffi::OsString; use std::fs::{self, TempDir, PathExt}; use std::io::{self, Read, Write}; use std::mem; @@ -882,7 +882,7 @@ fn link_args(cmd: &mut Command, let morestack = lib_path.join("libmorestack.a"); let mut v = OsString::from_str("-Wl,-force_load,"); - v.push_os_str(morestack.as_os_str()); + v.push(&morestack); cmd.arg(&v); } else { cmd.args(&["-Wl,--whole-archive", "-lmorestack", "-Wl,--no-whole-archive"]); @@ -1007,7 +1007,7 @@ fn link_args(cmd: &mut Command, if sess.opts.cg.rpath { let mut v = OsString::from_str("-Wl,-install_name,@rpath/"); - v.push_os_str(out_filename.file_name().unwrap()); + v.push(out_filename.file_name().unwrap()); cmd.arg(&v); } } else { @@ -1107,7 +1107,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) { &search_path[..], &sess.diagnostic().handler); let mut v = OsString::from_str("-Wl,-force_load,"); - v.push_os_str(lib.as_os_str()); + v.push(&lib); cmd.arg(&v); } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index dcc79e90cc57..88293afa53fc 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -35,12 +35,10 @@ #![feature(rustc_private)] #![feature(unsafe_destructor)] #![feature(staged_api)] -#![feature(std_misc)] #![feature(unicode)] #![feature(io)] #![feature(fs)] #![feature(path)] -#![feature(os)] #![feature(tempdir)] extern crate arena; diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index add44769bab6..b00d61c0303e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -38,7 +38,6 @@ use std::cell::RefCell; use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; use std::default::Default; -use std::ffi::OsStr; use std::fmt; use std::fs::{self, File}; use std::io::prelude::*; @@ -770,7 +769,7 @@ impl<'a> SourceCollector<'a> { let mut fname = p.file_name().expect("source has no filename") .to_os_string(); - fname.push_os_str(OsStr::from_str(".html")); + fname.push(".html"); cur.push(&fname); let mut w = BufWriter::new(try!(File::create(&cur))); diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index c94edb9d2a1c..ec9f90723be9 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable(feature = "std_misc")] + use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; use error::{Error, FromError}; use fmt; @@ -59,6 +61,7 @@ use vec::Vec; /// # } /// ``` #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct CString { inner: Vec, } @@ -110,13 +113,19 @@ pub struct CString { /// } /// ``` #[derive(Hash)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct CStr { + // FIXME: this should not be represented with a DST slice but rather with + // just a raw `libc::c_char` along with some form of marker to make + // this an unsized type. Essentially `sizeof(&CStr)` should be the + // same as `sizeof(&c_char)` but `CStr` should be an unsized type. inner: [libc::c_char] } /// An error returned from `CString::new` to indicate that a nul byte was found /// in the vector provided. #[derive(Clone, PartialEq, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct NulError(usize, Vec); /// A conversion trait used by the constructor of `CString` for types that can @@ -153,6 +162,7 @@ impl CString { /// This function will return an error if the bytes yielded contain an /// internal 0 byte. The error returned will contain the bytes as well as /// the position of the nul byte. + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(t: T) -> Result { let bytes = t.into_bytes(); match bytes.iter().position(|x| *x == 0) { @@ -216,6 +226,7 @@ impl CString { /// /// This method is equivalent to `from_vec` except that no runtime assertion /// is made that `v` contains no 0 bytes. + #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_vec_unchecked(mut v: Vec) -> CString { v.push(0); CString { inner: v } @@ -225,17 +236,20 @@ impl CString { /// /// The returned slice does **not** contain the trailing nul separator and /// it is guaranteed to not have any interior nul bytes. + #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes(&self) -> &[u8] { &self.inner[..self.inner.len() - 1] } /// Equivalent to the `as_bytes` function except that the returned slice /// includes the trailing nul byte. + #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes_with_nul(&self) -> &[u8] { &self.inner } } +#[stable(feature = "rust1", since = "1.0.0")] impl Deref for CString { type Target = CStr; @@ -254,23 +268,28 @@ impl fmt::Debug for CString { impl NulError { /// Returns the position of the nul byte in the slice that was provided to /// `CString::from_vec`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn nul_position(&self) -> usize { self.0 } /// Consumes this error, returning the underlying vector of bytes which /// generated the error in the first place. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_vec(self) -> Vec { self.1 } } +#[stable(feature = "rust1", since = "1.0.0")] impl Error for NulError { fn description(&self) -> &str { "nul byte found in data" } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for NulError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "nul byte found in provided data at position: {}", self.0) } } +#[stable(feature = "rust1", since = "1.0.0")] impl FromError for io::Error { fn from_error(_: NulError) -> io::Error { io::Error::new(io::ErrorKind::InvalidInput, @@ -278,6 +297,7 @@ impl FromError for io::Error { } } +#[stable(feature = "rust1", since = "1.0.0")] impl FromError for old_io::IoError { fn from_error(_: NulError) -> old_io::IoError { old_io::IoError { @@ -325,6 +345,7 @@ impl CStr { /// } /// # } /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr { let len = libc::strlen(ptr); mem::transmute(slice::from_raw_parts(ptr, len as usize + 1)) @@ -335,6 +356,7 @@ impl CStr { /// The returned pointer will be valid for as long as `self` is and points /// to a contiguous region of memory terminated with a 0 byte to represent /// the end of the string. + #[stable(feature = "rust1", since = "1.0.0")] pub fn as_ptr(&self) -> *const libc::c_char { self.inner.as_ptr() } @@ -351,6 +373,7 @@ impl CStr { /// > **Note**: This method is currently implemented as a 0-cost cast, but /// > it is planned to alter its definition in the future to perform the /// > length calculation whenever this method is called. + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_bytes(&self) -> &[u8] { let bytes = self.to_bytes_with_nul(); &bytes[..bytes.len() - 1] @@ -364,22 +387,27 @@ impl CStr { /// > **Note**: This method is currently implemented as a 0-cost cast, but /// > it is planned to alter its definition in the future to perform the /// > length calculation whenever this method is called. + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_bytes_with_nul(&self) -> &[u8] { unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) } } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for CStr { fn eq(&self, other: &CStr) -> bool { self.to_bytes().eq(other.to_bytes()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for CStr {} +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for CStr { fn partial_cmp(&self, other: &CStr) -> Option { self.to_bytes().partial_cmp(&other.to_bytes()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for CStr { fn cmp(&self, other: &CStr) -> Ordering { self.to_bytes().cmp(&other.to_bytes()) diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 1bff6afb7760..f17dc6542491 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -10,17 +10,19 @@ //! Utilities related to FFI bindings. -#![unstable(feature = "std_misc", - reason = "module just underwent fairly large reorganization and the dust \ - still needs to settle")] +#![stable(feature = "rust1", since = "1.0.0")] -pub use self::c_str::{CString, CStr, NulError, IntoBytes}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::c_str::{CString, CStr}; +pub use self::c_str::{NulError, IntoBytes}; #[allow(deprecated)] pub use self::c_str::c_str_to_bytes; #[allow(deprecated)] pub use self::c_str::c_str_to_bytes_with_nul; +#[stable(feature = "rust1", since = "1.0.0")] pub use self::os_str::OsString; +#[stable(feature = "rust1", since = "1.0.0")] pub use self::os_str::OsStr; mod c_str; @@ -28,6 +30,7 @@ mod os_str; // FIXME (#21670): these should be defined in the os_str module /// Freely convertible to an `&OsStr` slice. +#[unstable(feature = "std_misc")] pub trait AsOsStr { /// Convert to an `&OsStr` slice. fn as_os_str(&self) -> &OsStr; diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 926d8e03f2c3..77df831bbfe3 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -49,17 +49,20 @@ use super::AsOsStr; /// Owned, mutable OS strings. #[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct OsString { inner: Buf } /// Slices into OS strings. +#[stable(feature = "rust1", since = "1.0.0")] pub struct OsStr { inner: Slice } impl OsString { /// Constructs an `OsString` at no cost by consuming a `String`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn from_string(s: String) -> OsString { OsString { inner: Buf::from_string(s) } } @@ -67,11 +70,13 @@ impl OsString { /// Constructs an `OsString` by copying from a `&str` slice. /// /// Equivalent to: `OsString::from_string(String::from_str(s))`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn from_str(s: &str) -> OsString { OsString { inner: Buf::from_str(s) } } /// Constructs a new empty `OsString`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> OsString { OsString { inner: Buf::from_string(String::new()) } } @@ -79,16 +84,26 @@ impl OsString { /// Convert the `OsString` into a `String` if it contains valid Unicode data. /// /// On failure, ownership of the original `OsString` is returned. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_string(self) -> Result { self.inner.into_string().map_err(|buf| OsString { inner: buf} ) } /// Extend the string with the given `&OsStr` slice. + #[deprecated(since = "1.0.0", reason = "renamed to `push`")] + #[unstable(feature = "os")] pub fn push_os_str(&mut self, s: &OsStr) { self.inner.push_slice(&s.inner) } + + /// Extend the string with the given `&OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push(&mut self, s: &T) { + self.inner.push_slice(&s.as_os_str().inner) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index for OsString { type Output = OsStr; @@ -98,6 +113,7 @@ impl ops::Index for OsString { } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Deref for OsString { type Target = OsStr; @@ -107,32 +123,38 @@ impl ops::Deref for OsString { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Debug for OsString { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt::Debug::fmt(&**self, formatter) } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for OsString { fn eq(&self, other: &OsString) -> bool { &**self == &**other } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for OsString { fn eq(&self, other: &str) -> bool { &**self == other } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for str { fn eq(&self, other: &OsString) -> bool { &**other == self } } +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for OsString {} +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for OsString { #[inline] fn partial_cmp(&self, other: &OsString) -> Option { @@ -148,6 +170,7 @@ impl PartialOrd for OsString { fn ge(&self, other: &OsString) -> bool { &**self >= &**other } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for OsString { #[inline] fn partial_cmp(&self, other: &str) -> Option { @@ -155,6 +178,7 @@ impl PartialOrd for OsString { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for OsString { #[inline] fn cmp(&self, other: &OsString) -> cmp::Ordering { @@ -172,6 +196,7 @@ impl Hash for OsString { impl OsStr { /// Coerce directly from a `&str` slice to a `&OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] pub fn from_str(s: &str) -> &OsStr { unsafe { mem::transmute(Slice::from_str(s)) } } @@ -179,6 +204,7 @@ impl OsStr { /// Yield a `&str` slice if the `OsStr` is valid unicode. /// /// This conversion may entail doing a check for UTF-8 validity. + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_str(&self) -> Option<&str> { self.inner.to_str() } @@ -186,11 +212,13 @@ impl OsStr { /// Convert an `OsStr` to a `Cow`. /// /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER. + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_string_lossy(&self) -> Cow { self.inner.to_string_lossy() } /// Copy the slice into an owned `OsString`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_os_string(&self) -> OsString { OsString { inner: self.inner.to_owned() } } @@ -204,26 +232,31 @@ impl OsStr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for OsStr { fn eq(&self, other: &OsStr) -> bool { self.bytes().eq(other.bytes()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for OsStr { fn eq(&self, other: &str) -> bool { *self == *OsStr::from_str(other) } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for str { fn eq(&self, other: &OsStr) -> bool { *other == *OsStr::from_str(self) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for OsStr {} +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for OsStr { #[inline] fn partial_cmp(&self, other: &OsStr) -> Option { @@ -239,6 +272,7 @@ impl PartialOrd for OsStr { fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for OsStr { #[inline] fn partial_cmp(&self, other: &str) -> Option { @@ -249,6 +283,7 @@ impl PartialOrd for OsStr { // FIXME (#19470): cannot provide PartialOrd for str until we // have more flexible coherence rules. +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for OsStr { #[inline] fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) } @@ -262,21 +297,25 @@ impl Hash for OsStr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Debug for OsStr { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { self.inner.fmt(formatter) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Borrow for OsString { fn borrow(&self) -> &OsStr { &self[..] } } +#[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for OsStr { type Owned = OsString; fn to_owned(&self) -> OsString { self.to_os_string() } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: AsOsStr + ?Sized> AsOsStr for &'a T { fn as_os_str(&self) -> &OsStr { (*self).as_os_str() @@ -307,15 +346,12 @@ impl AsOsStr for String { } } -#[cfg(unix)] impl AsOsStr for Path { + #[cfg(unix)] fn as_os_str(&self) -> &OsStr { unsafe { mem::transmute(self.as_vec()) } } -} - -#[cfg(windows)] -impl AsOsStr for Path { + #[cfg(windows)] fn as_os_str(&self) -> &OsStr { // currently .as_str() is actually infallible on windows OsStr::from_str(self.as_str().unwrap()) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index b85a0dcec818..18720ecddd9f 100755 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -872,10 +872,10 @@ impl PathBuf { // `path` is a pure relative path } else if need_sep { - self.inner.push_os_str(OsStr::from_str(MAIN_SEP_STR)); + self.inner.push(MAIN_SEP_STR); } - self.inner.push_os_str(path.as_os_str()); + self.inner.push(path); } /// Truncate `self` to `self.parent()`. @@ -937,8 +937,8 @@ impl PathBuf { let extension = extension.as_os_str(); if os_str_as_u8_slice(extension).len() > 0 { - stem.push_os_str(OsStr::from_str(".")); - stem.push_os_str(extension.as_os_str()); + stem.push("."); + stem.push(extension); } self.set_file_name(&stem); From 614853734e1e3553f9f10a5bd72bb31cbd0b1e13 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 5 Mar 2015 15:27:19 -0800 Subject: [PATCH 20/37] mk: Once again rename the beta channel artifacts as 'beta' No more alphas, please. --- mk/main.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mk/main.mk b/mk/main.mk index 9752ee233b6e..c00494be47cb 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -18,7 +18,7 @@ CFG_RELEASE_NUM=1.0.0 # An optional number to put after the label, e.g. '.2' -> '-beta.2' # NB Make sure it starts with a dot to conform to semver pre-release # versions (section 9) -CFG_PRERELEASE_VERSION=.2 +CFG_PRERELEASE_VERSION= CFG_FILENAME_EXTRA=4e7c5e5c @@ -30,8 +30,8 @@ CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM) CFG_DISABLE_UNSTABLE_FEATURES=1 endif ifeq ($(CFG_RELEASE_CHANNEL),beta) -CFG_RELEASE=$(CFG_RELEASE_NUM)-alpha$(CFG_PRERELEASE_VERSION) -CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-alpha$(CFG_PRERELEASE_VERSION) +CFG_RELEASE=$(CFG_RELEASE_NUM)-beta(CFG_PRERELEASE_VERSION) +CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-beta(CFG_PRERELEASE_VERSION) CFG_DISABLE_UNSTABLE_FEATURES=1 endif ifeq ($(CFG_RELEASE_CHANNEL),nightly) From d3e7700de45d6f6cb6acd7f598f9e635fd4de6fb Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Fri, 6 Mar 2015 02:33:24 +0300 Subject: [PATCH 21/37] std: net: enable bind_error test on all platforms Bind on non-local IP address is essentially the same test, and it works same way on all platforms. Fixes #11530 --- src/libstd/net/tcp.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 6ce3a939c6a4..fd723ea13e96 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -233,13 +233,13 @@ mod tests { } } - // FIXME #11530 this fails on android because tests are run as root - #[cfg_attr(any(windows, target_os = "android"), ignore)] #[test] fn bind_error() { - match TcpListener::bind("0.0.0.0:1") { + match TcpListener::bind("1.1.1.1:9999") { Ok(..) => panic!(), - Err(e) => assert_eq!(e.kind(), ErrorKind::PermissionDenied), + Err(e) => + // EADDRNOTAVAIL is mapped to ConnectionRefused + assert_eq!(e.kind(), ErrorKind::ConnectionRefused), } } From 73b0b25e326687aba319df99aee4b0c4124d4498 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Mar 2015 19:18:29 -0800 Subject: [PATCH 22/37] std: Stabilize the `fs` module This commit performs a stabilization pass over the `std::fs` module now that it's had some time to bake. The change was largely just adding `#[stable]` tags, but there are a few APIs that remain `#[unstable]`. The following apis are now marked `#[stable]`: * `std::fs` (the name) * `File` * `Metadata` * `ReadDir` * `DirEntry` * `OpenOptions` * `Permissions` * `File::{open, create}` * `File::{sync_all, sync_data}` * `File::set_len` * `File::metadata` * Trait implementations for `File` and `&File` * `OpenOptions::new` * `OpenOptions::{read, write, append, truncate, create}` * `OpenOptions::open` - this function was modified, however, to not attempt to reject cross-platform openings of directories. This means that some platforms will succeed in opening a directory and others will fail. * `Metadata::{is_dir, is_file, len, permissions}` * `Permissions::{readonly, set_readonly}` * `Iterator for ReadDir` * `DirEntry::path` * `remove_file` - like with `OpenOptions::open`, the extra windows code to remove a readonly file has been removed. This means that removing a readonly file will succeed on some platforms but fail on others. * `metadata` * `rename` * `copy` * `hard_link` * `soft_link` * `read_link` * `create_dir` * `create_dir_all` * `remove_dir` * `remove_dir_all` * `read_dir` The following apis remain `#[unstable]`. * `WalkDir` and `walk` - there are many methods by which a directory walk can be constructed, and it's unclear whether the current semantics are the right ones. For example symlinks are not handled super well currently. This is now behind a new `fs_walk` feature. * `File::path` - this is an extra abstraction which the standard library provides on top of what the system offers and it's unclear whether we should be doing so. This is now behind a new `file_path` feature. * `Metadata::{accessed, modified}` - we do not currently have a good abstraction for a moment in time which is what these APIs should likely be returning, so these remain `#[unstable]` for now. These are now behind a new `fs_time` feature * `set_file_times` - like with `Metadata::accessed`, we do not currently have the appropriate abstraction for the arguments here so this API remains unstable behind the `fs_time` feature gate. * `PathExt` - the precise set of methods on this trait may change over time and some methods may be removed. This API remains unstable behind the `path_ext` feature gate. * `set_permissions` - we may wish to expose a more granular ability to set the permissions on a file instead of just a blanket "set all permissions" method. This function remains behind the `fs` feature. The following apis are now `#[deprecated]` * The `TempDir` type is now entirely deprecated and is [located on crates.io][tempdir] as the `tempdir` crate with [its source][github] at rust-lang/tempdir. [tempdir]: https://crates.io/crates/tempdir [github]: https://github.com/rust-lang/tempdir The stability of some of these APIs has been questioned over the past few weeks in using these APIs, and it is intentional that the majority of APIs here are marked `#[stable]`. The `std::fs` module has a lot of room to grow and the material is [being tracked in a RFC issue][rfc-issue]. [rfc-issue]: https://github.com/rust-lang/rfcs/issues/939 [breaking-change] --- src/compiletest/compiletest.rs | 2 +- src/libgetopts/lib.rs | 2 +- src/librustc/lib.rs | 2 +- src/librustc_back/archive.rs | 4 +- src/librustc_back/lib.rs | 5 +- src/librustc_back/tempdir.rs | 121 ++++++++++++++++++++++++++++++++ src/librustc_driver/lib.rs | 1 - src/librustc_trans/back/link.rs | 3 +- src/librustc_trans/lib.rs | 4 +- src/librustdoc/lib.rs | 4 +- src/librustdoc/test.rs | 2 +- src/libstd/fs/mod.rs | 120 +++++++++++++++++++++---------- src/libstd/fs/tempdir.rs | 3 + src/libsyntax/lib.rs | 2 +- src/libterm/lib.rs | 2 +- src/libtest/lib.rs | 1 - src/rustbook/build.rs | 3 +- src/rustbook/main.rs | 4 +- 18 files changed, 229 insertions(+), 56 deletions(-) create mode 100644 src/librustc_back/tempdir.rs diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index b9e6f1842eea..a7531152a840 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -24,8 +24,8 @@ #![feature(path)] #![feature(os)] #![feature(io)] -#![feature(fs)] #![feature(net)] +#![feature(path_ext)] #![deny(warnings)] diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 6b9d6cb0000f..49a062ca3e4b 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -92,8 +92,8 @@ #![feature(collections)] #![feature(int_uint)] #![feature(staged_api)] -#![feature(str_words)] #![feature(core)] +#![feature(str_words)] #![cfg_attr(test, feature(rustc_private))] #[cfg(test)] #[macro_use] extern crate log; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 2d542eafbe1a..027360b31ad4 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -40,8 +40,8 @@ #![feature(std_misc)] #![feature(os)] #![feature(path)] -#![feature(fs)] #![feature(io)] +#![feature(path_ext)] #![cfg_attr(test, feature(test))] extern crate arena; diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index a6994387f8d6..ed44bf895295 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -11,7 +11,7 @@ //! A helper class for dealing with static archives use std::env; -use std::fs::{self, TempDir}; +use std::fs; use std::io::prelude::*; use std::io; use std::path::{Path, PathBuf}; @@ -19,6 +19,8 @@ use std::process::{Command, Output, Stdio}; use std::str; use syntax::diagnostic::Handler as ErrorHandler; +use tempdir::TempDir; + pub const METADATA_FILENAME: &'static str = "rust.metadata.bin"; pub struct ArchiveConfig<'a> { diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 2b028a5c6262..a7ae9661c3d8 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -34,7 +34,6 @@ #![feature(collections)] #![feature(core)] #![feature(old_fs)] -#![feature(fs)] #![feature(hash)] #![feature(int_uint)] #![feature(io)] @@ -44,7 +43,8 @@ #![feature(path)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(tempdir)] +#![feature(rand)] +#![feature(path_ext)] extern crate syntax; extern crate serialize; @@ -52,6 +52,7 @@ extern crate serialize; pub mod abi; pub mod archive; +pub mod tempdir; pub mod arm; pub mod fs; pub mod mips; diff --git a/src/librustc_back/tempdir.rs b/src/librustc_back/tempdir.rs new file mode 100644 index 000000000000..4d8619a81216 --- /dev/null +++ b/src/librustc_back/tempdir.rs @@ -0,0 +1,121 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env; +use std::io::{self, Error, ErrorKind}; +use std::fs; +use std::path::{self, PathBuf, AsPath}; +use std::rand::{thread_rng, Rng}; + +/// A wrapper for a path to temporary directory implementing automatic +/// scope-based deletion. +pub struct TempDir { + path: Option, +} + +// How many times should we (re)try finding an unused random name? It should be +// enough that an attacker will run out of luck before we run out of patience. +const NUM_RETRIES: u32 = 1 << 31; +// How many characters should we include in a random file name? It needs to +// be enough to dissuade an attacker from trying to preemptively create names +// of that length, but not so huge that we unnecessarily drain the random number +// generator of entropy. +const NUM_RAND_CHARS: uint = 12; + +impl TempDir { + /// Attempts to make a temporary directory inside of `tmpdir` whose name + /// will have the prefix `prefix`. The directory will be automatically + /// deleted once the returned wrapper is destroyed. + /// + /// If no directory can be created, `Err` is returned. + #[allow(deprecated)] // rand usage + pub fn new_in(tmpdir: &P, prefix: &str) + -> io::Result { + let storage; + let mut tmpdir = tmpdir.as_path(); + if !tmpdir.is_absolute() { + let cur_dir = try!(env::current_dir()); + storage = cur_dir.join(tmpdir); + tmpdir = &storage; + // return TempDir::new_in(&cur_dir.join(tmpdir), prefix); + } + + let mut rng = thread_rng(); + for _ in 0..NUM_RETRIES { + let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect(); + let leaf = if prefix.len() > 0 { + format!("{}.{}", prefix, suffix) + } else { + // If we're given an empty string for a prefix, then creating a + // directory starting with "." would lead to it being + // semi-invisible on some systems. + suffix + }; + let path = tmpdir.join(&leaf); + match fs::create_dir(&path) { + Ok(_) => return Ok(TempDir { path: Some(path) }), + Err(ref e) if e.kind() == ErrorKind::PathAlreadyExists => {} + Err(e) => return Err(e) + } + } + + Err(Error::new(ErrorKind::PathAlreadyExists, + "too many temporary directories already exist", + None)) + } + + /// Attempts to make a temporary directory inside of `env::temp_dir()` whose + /// name will have the prefix `prefix`. The directory will be automatically + /// deleted once the returned wrapper is destroyed. + /// + /// If no directory can be created, `Err` is returned. + #[allow(deprecated)] + pub fn new(prefix: &str) -> io::Result { + TempDir::new_in(&env::temp_dir(), prefix) + } + + /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper. + /// This discards the wrapper so that the automatic deletion of the + /// temporary directory is prevented. + pub fn into_path(mut self) -> PathBuf { + self.path.take().unwrap() + } + + /// Access the wrapped `std::path::Path` to the temporary directory. + pub fn path(&self) -> &path::Path { + self.path.as_ref().unwrap() + } + + /// Close and remove the temporary directory + /// + /// Although `TempDir` removes the directory on drop, in the destructor + /// any errors are ignored. To detect errors cleaning up the temporary + /// directory, call `close` instead. + pub fn close(mut self) -> io::Result<()> { + self.cleanup_dir() + } + + fn cleanup_dir(&mut self) -> io::Result<()> { + match self.path { + Some(ref p) => fs::remove_dir_all(p), + None => Ok(()) + } + } +} + +impl Drop for TempDir { + fn drop(&mut self) { + let _ = self.cleanup_dir(); + } +} + +// the tests for this module need to change the path using change_dir, +// and this doesn't play nicely with other tests so these unit tests are located +// in src/test/run-pass/tempfile.rs diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index aa8b7c7785d2..b8e84e57a787 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -39,7 +39,6 @@ #![feature(exit_status)] #![feature(path)] #![feature(io)] -#![feature(fs)] extern crate arena; extern crate flate; diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 1e84bc4b8e0b..f353c69eca29 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -26,9 +26,10 @@ use middle::ty::{self, Ty}; use util::common::time; use util::ppaux; use util::sha2::{Digest, Sha256}; +use rustc_back::tempdir::TempDir; use std::ffi::{AsOsStr, OsString}; -use std::fs::{self, TempDir, PathExt}; +use std::fs::{self, PathExt}; use std::io::{self, Read, Write}; use std::mem; use std::path::{Path, PathBuf}; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index dcc79e90cc57..7cdd1d0a456c 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -38,10 +38,10 @@ #![feature(std_misc)] #![feature(unicode)] #![feature(io)] -#![feature(fs)] #![feature(path)] #![feature(os)] -#![feature(tempdir)] +#![feature(path_ext)] +#![feature(fs)] extern crate arena; extern crate flate; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b4522ad680b7..712168ae7067 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -35,9 +35,8 @@ #![feature(unicode)] #![feature(str_words)] #![feature(io)] -#![feature(fs)] #![feature(path)] -#![feature(tempdir)] +#![feature(path_ext)] extern crate arena; extern crate getopts; @@ -47,6 +46,7 @@ extern crate rustc_trans; extern crate rustc_driver; extern crate rustc_resolve; extern crate rustc_lint; +extern crate rustc_back; extern crate serialize; extern crate syntax; extern crate "test" as testing; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 9fd38ecb1362..80b0177021e7 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -13,7 +13,6 @@ use std::collections::{HashSet, HashMap}; use std::dynamic_lib::DynamicLibrary; use std::env; use std::ffi::OsString; -use std::fs::TempDir; use std::old_io; use std::io; use std::path::PathBuf; @@ -28,6 +27,7 @@ use rustc_lint; use rustc::session::{self, config}; use rustc::session::config::get_unstable_features_setting; use rustc::session::search_paths::{SearchPaths, PathKind}; +use rustc_back::tempdir::TempDir; use rustc_driver::{driver, Compilation}; use syntax::codemap::CodeMap; use syntax::diagnostic; diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs index 64ec025a5c42..706a51c6c9a0 100644 --- a/src/libstd/fs/mod.rs +++ b/src/libstd/fs/mod.rs @@ -15,7 +15,7 @@ //! operations. Extra platform-specific functionality can be found in the //! extension traits of `std::os::$platform`. -#![unstable(feature = "fs")] +#![stable(feature = "rust1", since = "1.0.0")] use core::prelude::*; @@ -25,6 +25,7 @@ use sys::fs2 as fs_imp; use sys_common::{AsInnerMut, FromInner, AsInner}; use vec::Vec; +#[allow(deprecated)] pub use self::tempdir::TempDir; mod tempdir; @@ -52,6 +53,7 @@ mod tempdir; /// # Ok(()) /// # } /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub struct File { inner: fs_imp::File, path: PathBuf, @@ -62,6 +64,7 @@ pub struct File { /// This structure is returned from the `metadata` function or method and /// represents known metadata about a file such as its permissions, size, /// modification times, etc. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Metadata(fs_imp::FileAttr); /// Iterator over the entries in a directory. @@ -70,6 +73,7 @@ pub struct Metadata(fs_imp::FileAttr); /// will yield instances of `io::Result`. Through a `DirEntry` /// information like the entry's path and possibly other metadata can be /// learned. +#[stable(feature = "rust1", since = "1.0.0")] pub struct ReadDir(fs_imp::ReadDir); /// Entries returned by the `ReadDir` iterator. @@ -77,9 +81,14 @@ pub struct ReadDir(fs_imp::ReadDir); /// An instance of `DirEntry` represents an entry inside of a directory on the /// filesystem. Each entry can be inspected via methods to learn about the full /// path or possibly other metadata through per-platform extension traits. +#[stable(feature = "rust1", since = "1.0.0")] pub struct DirEntry(fs_imp::DirEntry); /// An iterator that recursively walks over the contents of a directory. +#[unstable(feature = "fs_walk", + reason = "the precise semantics and defaults for a recursive walk \ + may change and this may end up accounting for files such \ + as symlinks differently")] pub struct WalkDir { cur: Option, stack: Vec>, @@ -92,6 +101,7 @@ pub struct WalkDir { /// `File::create` methods are aliases for commonly used options using this /// builder. #[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct OpenOptions(fs_imp::OpenOptions); /// Representation of the various permissions on a file. @@ -101,6 +111,7 @@ pub struct OpenOptions(fs_imp::OpenOptions); /// functionality, such as mode bits, is available through the /// `os::unix::PermissionsExt` trait. #[derive(Clone, PartialEq, Eq, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Permissions(fs_imp::FilePermissions); impl File { @@ -112,6 +123,7 @@ impl File { /// /// This function will return an error if `path` does not already exist. /// Other errors may also be returned according to `OpenOptions::open`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn open(path: &P) -> io::Result { OpenOptions::new().read(true).open(path) } @@ -122,11 +134,15 @@ impl File { /// and will truncate it if it does. /// /// See the `OpenOptions::open` function for more details. + #[stable(feature = "rust1", since = "1.0.0")] pub fn create(path: &P) -> io::Result { OpenOptions::new().write(true).create(true).truncate(true).open(path) } /// Returns the original path that was used to open this file. + #[unstable(feature = "file_path", + reason = "this abstraction is imposed by this library instead \ + of the underlying OS and may be removed")] pub fn path(&self) -> Option<&Path> { Some(&self.path) } @@ -135,6 +151,7 @@ impl File { /// /// This function will attempt to ensure that all in-core data reaches the /// filesystem before returning. + #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_all(&self) -> io::Result<()> { self.inner.fsync() } @@ -148,6 +165,7 @@ impl File { /// /// Note that some platforms may simply implement this in terms of /// `sync_all`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_data(&self) -> io::Result<()> { self.inner.datasync() } @@ -159,11 +177,13 @@ impl File { /// be shrunk. If it is greater than the current file's size, then the file /// will be extended to `size` and have all of the intermediate data filled /// in with 0s. + #[stable(feature = "rust1", since = "1.0.0")] pub fn set_len(&self, size: u64) -> io::Result<()> { self.inner.truncate(size) } - /// Queries information about the underlying file. + /// Queries metadata about the underlying file. + #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata(&self) -> io::Result { self.inner.file_attr().map(Metadata) } @@ -172,33 +192,39 @@ impl File { impl AsInner for File { fn as_inner(&self) -> &fs_imp::File { &self.inner } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for File { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for File { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } +#[stable(feature = "rust1", since = "1.0.0")] impl Seek for File { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.inner.seek(pos) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a File { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for &'a File { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Seek for &'a File { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.inner.seek(pos) @@ -209,6 +235,7 @@ impl OpenOptions { /// Creates a blank net set of options ready for configuration. /// /// All options are initially set to `false`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> OpenOptions { OpenOptions(fs_imp::OpenOptions::new()) } @@ -217,6 +244,7 @@ impl OpenOptions { /// /// This option, when true, will indicate that the file should be /// `read`-able if opened. + #[stable(feature = "rust1", since = "1.0.0")] pub fn read(&mut self, read: bool) -> &mut OpenOptions { self.0.read(read); self } @@ -225,6 +253,7 @@ impl OpenOptions { /// /// This option, when true, will indicate that the file should be /// `write`-able if opened. + #[stable(feature = "rust1", since = "1.0.0")] pub fn write(&mut self, write: bool) -> &mut OpenOptions { self.0.write(write); self } @@ -233,6 +262,7 @@ impl OpenOptions { /// /// This option, when true, means that writes will append to a file instead /// of overwriting previous contents. + #[stable(feature = "rust1", since = "1.0.0")] pub fn append(&mut self, append: bool) -> &mut OpenOptions { self.0.append(append); self } @@ -241,6 +271,7 @@ impl OpenOptions { /// /// If a file is successfully opened with this option set it will truncate /// the file to 0 length if it already exists. + #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions { self.0.truncate(truncate); self } @@ -249,6 +280,7 @@ impl OpenOptions { /// /// This option indicates whether a new file will be created if the file /// does not yet already exist. + #[stable(feature = "rust1", since = "1.0.0")] pub fn create(&mut self, create: bool) -> &mut OpenOptions { self.0.create(create); self } @@ -264,37 +296,33 @@ impl OpenOptions { /// * Attempting to open a file with access that the user lacks /// permissions for /// * Filesystem-level errors (full disk, etc) + #[stable(feature = "rust1", since = "1.0.0")] pub fn open(&self, path: &P) -> io::Result { let path = path.as_path(); let inner = try!(fs_imp::File::open(path, &self.0)); - - // On *BSD systems, we can open a directory as a file and read from - // it: fd=open("/tmp", O_RDONLY); read(fd, buf, N); due to an old - // tradition before the introduction of opendir(3). We explicitly - // reject it because there are few use cases. - if cfg!(not(any(target_os = "linux", target_os = "android"))) && - try!(inner.file_attr()).is_dir() { - Err(Error::new(ErrorKind::InvalidInput, "is a directory", None)) - } else { - Ok(File { path: path.to_path_buf(), inner: inner }) - } + Ok(File { path: path.to_path_buf(), inner: inner }) } } + impl AsInnerMut for OpenOptions { fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 } } impl Metadata { /// Returns whether this metadata is for a directory. + #[stable(feature = "rust1", since = "1.0.0")] pub fn is_dir(&self) -> bool { self.0.is_dir() } /// Returns whether this metadata is for a regular file. + #[stable(feature = "rust1", since = "1.0.0")] pub fn is_file(&self) -> bool { self.0.is_file() } /// Returns the size of the file, in bytes, this metadata is for. + #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> u64 { self.0.size() } /// Returns the permissions of the file this metadata is for. + #[stable(feature = "rust1", since = "1.0.0")] pub fn permissions(&self) -> Permissions { Permissions(self.0.perm()) } @@ -302,22 +330,32 @@ impl Metadata { /// Returns the most recent access time for a file. /// /// The return value is in milliseconds since the epoch. + #[unstable(feature = "fs_time", + reason = "the return type of u64 is not quite appropriate for \ + this method and may change if the standard library \ + gains a type to represent a moment in time")] pub fn accessed(&self) -> u64 { self.0.accessed() } /// Returns the most recent modification time for a file. /// /// The return value is in milliseconds since the epoch. + #[unstable(feature = "fs_time", + reason = "the return type of u64 is not quite appropriate for \ + this method and may change if the standard library \ + gains a type to represent a moment in time")] pub fn modified(&self) -> u64 { self.0.modified() } } impl Permissions { /// Returns whether these permissions describe a readonly file. + #[stable(feature = "rust1", since = "1.0.0")] pub fn readonly(&self) -> bool { self.0.readonly() } /// Modify the readonly flag for this set of permissions. /// /// This operation does **not** modify the filesystem. To modify the /// filesystem use the `fs::set_permissions` function. + #[stable(feature = "rust1", since = "1.0.0")] pub fn set_readonly(&mut self, readonly: bool) { self.0.set_readonly(readonly) } @@ -333,6 +371,7 @@ impl AsInner for Permissions { fn as_inner(&self) -> &fs_imp::FilePermissions { &self.0 } } +#[stable(feature = "rust1", since = "1.0.0")] impl Iterator for ReadDir { type Item = io::Result; @@ -341,11 +380,13 @@ impl Iterator for ReadDir { } } +#[stable(feature = "rust1", since = "1.0.0")] impl DirEntry { /// Returns the full path to the file that this entry represents. /// /// The full path is created by joining the original path to `read_dir` or /// `walk_dir` with the filename of this entry. + #[stable(feature = "rust1", since = "1.0.0")] pub fn path(&self) -> PathBuf { self.0.path() } } @@ -368,31 +409,9 @@ impl DirEntry { /// This function will return an error if `path` points to a directory, if the /// user lacks permissions to remove the file, or if some other filesystem-level /// error occurs. +#[stable(feature = "rust1", since = "1.0.0")] pub fn remove_file(path: &P) -> io::Result<()> { - let path = path.as_path(); - let e = match fs_imp::unlink(path) { - Ok(()) => return Ok(()), - Err(e) => e, - }; - if !cfg!(windows) { return Err(e) } - - // On unix, a readonly file can be successfully removed. On windows, - // however, it cannot. To keep the two platforms in line with - // respect to their behavior, catch this case on windows, attempt to - // change it to read-write, and then remove the file. - if e.kind() != ErrorKind::PermissionDenied { return Err(e) } - - let attr = match metadata(path) { Ok(a) => a, Err(..) => return Err(e) }; - let mut perms = attr.permissions(); - if !perms.readonly() { return Err(e) } - perms.set_readonly(false); - - if set_permissions(path, perms).is_err() { return Err(e) } - if fs_imp::unlink(path).is_ok() { return Ok(()) } - - // Oops, try to put things back the way we found it - let _ = set_permissions(path, attr.permissions()); - Err(e) + fs_imp::unlink(path.as_path()) } /// Given a path, query the file system to get information about a file, @@ -418,6 +437,7 @@ pub fn remove_file(path: &P) -> io::Result<()> { /// This function will return an error if the user lacks the requisite /// permissions to perform a `metadata` call on the given `path` or if there /// is no entry in the filesystem at the provided path. +#[stable(feature = "rust1", since = "1.0.0")] pub fn metadata(path: &P) -> io::Result { fs_imp::stat(path.as_path()).map(Metadata) } @@ -438,6 +458,7 @@ pub fn metadata(path: &P) -> io::Result { /// the process lacks permissions to view the contents, if `from` and `to` /// reside on separate filesystems, or if some other intermittent I/O error /// occurs. +#[stable(feature = "rust1", since = "1.0.0")] pub fn rename(from: &P, to: &Q) -> io::Result<()> { fs_imp::rename(from.as_path(), to.as_path()) @@ -468,6 +489,7 @@ pub fn rename(from: &P, to: &Q) /// * The `from` file does not exist /// * The current process does not have the permission rights to access /// `from` or write `to` +#[stable(feature = "rust1", since = "1.0.0")] pub fn copy(from: &P, to: &Q) -> io::Result { let from = from.as_path(); @@ -490,6 +512,7 @@ pub fn copy(from: &P, to: &Q) /// /// The `dst` path will be a link pointing to the `src` path. Note that systems /// often require these two paths to both be located on the same filesystem. +#[stable(feature = "rust1", since = "1.0.0")] pub fn hard_link(src: &P, dst: &Q) -> io::Result<()> { fs_imp::link(src.as_path(), dst.as_path()) @@ -498,6 +521,7 @@ pub fn hard_link(src: &P, dst: &Q) /// Creates a new soft link on the filesystem. /// /// The `dst` path will be a soft link pointing to the `src` path. +#[stable(feature = "rust1", since = "1.0.0")] pub fn soft_link(src: &P, dst: &Q) -> io::Result<()> { fs_imp::symlink(src.as_path(), dst.as_path()) @@ -510,6 +534,7 @@ pub fn soft_link(src: &P, dst: &Q) /// This function will return an error on failure. Failure conditions include /// reading a file that does not exist or reading a file that is not a soft /// link. +#[stable(feature = "rust1", since = "1.0.0")] pub fn read_link(path: &P) -> io::Result { fs_imp::readlink(path.as_path()) } @@ -528,6 +553,7 @@ pub fn read_link(path: &P) -> io::Result { /// /// This function will return an error if the user lacks permissions to make a /// new directory at the provided `path`, or if the directory already exists. +#[stable(feature = "rust1", since = "1.0.0")] pub fn create_dir(path: &P) -> io::Result<()> { fs_imp::mkdir(path.as_path()) } @@ -541,6 +567,7 @@ pub fn create_dir(path: &P) -> io::Result<()> { /// does not already exist and it could not be created otherwise. The specific /// error conditions for when a directory is being created (after it is /// determined to not exist) are outlined by `fs::create_dir`. +#[stable(feature = "rust1", since = "1.0.0")] pub fn create_dir_all(path: &P) -> io::Result<()> { let path = path.as_path(); if path.is_dir() { return Ok(()) } @@ -572,6 +599,7 @@ pub fn create_dir_all(path: &P) -> io::Result<()> { /// /// This function will return an error if the user lacks permissions to remove /// the directory at the provided `path`, or if the directory isn't empty. +#[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir(path: &P) -> io::Result<()> { fs_imp::rmdir(path.as_path()) } @@ -585,6 +613,7 @@ pub fn remove_dir(path: &P) -> io::Result<()> { /// # Errors /// /// See `file::remove_file` and `fs::remove_dir` +#[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir_all(path: &P) -> io::Result<()> { let path = path.as_path(); for child in try!(read_dir(path)) { @@ -637,6 +666,7 @@ pub fn remove_dir_all(path: &P) -> io::Result<()> { /// This function will return an error if the provided `path` doesn't exist, if /// the process lacks permissions to view the contents or if the `path` points /// at a non-directory file +#[stable(feature = "rust1", since = "1.0.0")] pub fn read_dir(path: &P) -> io::Result { fs_imp::readdir(path.as_path()).map(ReadDir) } @@ -649,11 +679,16 @@ pub fn read_dir(path: &P) -> io::Result { /// /// The iterator will yield instances of `io::Result`. New errors may /// be encountered after an iterator is initially constructed. +#[unstable(feature = "fs_walk", + reason = "the precise semantics and defaults for a recursive walk \ + may change and this may end up accounting for files such \ + as symlinks differently")] pub fn walk_dir(path: &P) -> io::Result { let start = try!(read_dir(path)); Ok(WalkDir { cur: Some(start), stack: Vec::new() }) } +#[unstable(feature = "fs_walk")] impl Iterator for WalkDir { type Item = io::Result; @@ -683,6 +718,9 @@ impl Iterator for WalkDir { } /// Utility methods for paths. +#[unstable(feature = "path_ext", + reason = "the precise set of methods exposed on this trait may \ + change and some methods may be removed")] pub trait PathExt { /// Get information on the file, directory, etc at this path. /// @@ -727,6 +765,10 @@ impl PathExt for Path { /// The file at the path specified will have its last access time set to /// `atime` and its modification time set to `mtime`. The times specified should /// be in milliseconds. +#[unstable(feature = "fs_time", + reason = "the argument type of u64 is not quite appropriate for \ + this function and may change if the standard library \ + gains a type to represent a moment in time")] pub fn set_file_times(path: &P, accessed: u64, modified: u64) -> io::Result<()> { fs_imp::utimes(path.as_path(), accessed, modified) @@ -752,6 +794,10 @@ pub fn set_file_times(path: &P, accessed: u64, /// This function will return an error if the provided `path` doesn't exist, if /// the process lacks permissions to change the attributes of the file, or if /// some other I/O error is encountered. +#[unstable(feature = "fs", + reason = "a more granual ability to set specific permissions may \ + be exposed on the Permissions structure itself and this \ + method may not always exist")] pub fn set_permissions(path: &P, perm: Permissions) -> io::Result<()> { fs_imp::set_perm(path.as_path(), perm.0) diff --git a/src/libstd/fs/tempdir.rs b/src/libstd/fs/tempdir.rs index 79bdb35dd48c..c1da77a6668f 100644 --- a/src/libstd/fs/tempdir.rs +++ b/src/libstd/fs/tempdir.rs @@ -9,6 +9,9 @@ // except according to those terms. #![unstable(feature = "tempdir", reason = "needs an RFC before stabilization")] +#![deprecated(since = "1.0.0", + reason = "use the `tempdir` crate from crates.io instead")] +#![allow(deprecated)] use prelude::v1::*; diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 7bd9cc3b8551..c0977508112c 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -37,8 +37,8 @@ #![feature(std_misc)] #![feature(unicode)] #![feature(path)] -#![feature(fs)] #![feature(io)] +#![feature(path_ext)] extern crate arena; extern crate fmt_macros; diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index ba9860ee31f6..d4e22c72e163 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -52,7 +52,6 @@ #![feature(box_syntax)] #![feature(collections)] -#![feature(fs)] #![feature(int_uint)] #![feature(io)] #![feature(old_io)] @@ -61,6 +60,7 @@ #![feature(staged_api)] #![feature(std_misc)] #![feature(unicode)] +#![feature(path_ext)] #![cfg_attr(windows, feature(libc))] #[macro_use] extern crate log; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index e309e7a6c221..60dd91f8c715 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -39,7 +39,6 @@ #![feature(int_uint)] #![feature(old_io)] #![feature(path)] -#![feature(fs)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(std_misc)] diff --git a/src/rustbook/build.rs b/src/rustbook/build.rs index 1fb30e15400e..731773917e09 100644 --- a/src/rustbook/build.rs +++ b/src/rustbook/build.rs @@ -11,10 +11,11 @@ //! Implementation of the `build` subcommand, used to compile a book. use std::env; -use std::fs::{self, File, TempDir}; +use std::fs::{self, File}; use std::io::prelude::*; use std::io::{self, BufWriter}; use std::path::{Path, PathBuf}; +use rustc_back::tempdir::TempDir; use subcommand::Subcommand; use term::Term; diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs index 848f960839e6..8df622b0b5d0 100644 --- a/src/rustbook/main.rs +++ b/src/rustbook/main.rs @@ -12,14 +12,14 @@ #![feature(core)] #![feature(exit_status)] -#![feature(fs)] #![feature(io)] #![feature(old_io)] #![feature(path)] #![feature(rustdoc)] -#![feature(tempdir)] +#![feature(rustc_private)] extern crate rustdoc; +extern crate rustc_back; use std::env; use std::error::Error; From a08f12954c0cfdc0864aea9b1b958ff0b4ee222d Mon Sep 17 00:00:00 2001 From: Paul Osborne Date: Thu, 5 Mar 2015 19:11:59 -0600 Subject: [PATCH 23/37] fix minor grammar mistake in paths documentation --- src/libstd/path.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index b85a0dcec818..af3cf57082dd 100755 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -90,7 +90,7 @@ //! * Repeated separators are ignored: `a/b` and `a//b` both have components `a` //! and `b`. //! -//! * Paths ending in a separator are treated as if they has a current directory +//! * Paths ending in a separator are treated as if they have a current directory //! component at the end (or, in verbatim paths, an empty component). For //! example, while `a/b` has components `a` and `b`, the paths `a/b/` and //! `a/b/.` both have components `a`, `b`, and `.` (current directory). The From 65b4eda5a6f270f5c30beec66c59825aba0524b9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Mar 2015 17:20:16 -0800 Subject: [PATCH 24/37] std: Fix peeling ports from addresses The `rsplitn` call was called with 2 instead of 1 so the iterator would yield 3 items in some cases, not the 2 that it should have. Closes #23076 --- src/libstd/net/addr.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index f16f501c46a1..e767ebfa2d95 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -293,7 +293,7 @@ impl ToSocketAddrs for str { } // split the string by ':' and convert the second part to u16 - let mut parts_iter = self.rsplitn(2, ':'); + let mut parts_iter = self.rsplitn(1, ':'); let port_str = try_opt!(parts_iter.next(), "invalid socket address"); let host = try_opt!(parts_iter.next(), "invalid socket address"); let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value"); @@ -590,4 +590,9 @@ mod tests { let a = SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1), 23924); assert!(tsa("localhost:23924").unwrap().contains(&a)); } + + #[test] + fn to_socket_addr_str_bad() { + assert!(tsa("1200::AB00:1234::2552:7777:1313:34300").is_err()); + } } From 8655e94abf530b3e9cb10e6acc5e39e21d3c19a3 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 5 Mar 2015 17:29:38 -0800 Subject: [PATCH 25/37] 'ignore-fast' directives do nothing --- src/test/compile-fail/privacy5.rs | 1 - src/test/run-pass/c-stack-returning-int64.rs | 1 - src/test/run-pass/foreign-fn-linkname.rs | 1 - src/test/run-pass/foreign-mod-unused-const.rs | 1 - src/test/run-pass/foreign2.rs | 1 - src/test/run-pass/issue-4735.rs | 1 - src/test/run-pass/newtype-struct-with-dtor.rs | 1 - src/test/run-pass/variadic-ffi.rs | 1 - 8 files changed, 8 deletions(-) diff --git a/src/test/compile-fail/privacy5.rs b/src/test/compile-fail/privacy5.rs index df570fd46479..a7f6a514b96a 100644 --- a/src/test/compile-fail/privacy5.rs +++ b/src/test/compile-fail/privacy5.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:privacy-tuple-struct.rs -// ignore-fast extern crate "privacy-tuple-struct" as other; diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs index 6246ee9c6c41..1de7520d2b1d 100644 --- a/src/test/run-pass/c-stack-returning-int64.rs +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate extern crate libc; diff --git a/src/test/run-pass/foreign-fn-linkname.rs b/src/test/run-pass/foreign-fn-linkname.rs index 24b711328a18..0adb3942e501 100644 --- a/src/test/run-pass/foreign-fn-linkname.rs +++ b/src/test/run-pass/foreign-fn-linkname.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate extern crate libc; use std::ffi::CString; diff --git a/src/test/run-pass/foreign-mod-unused-const.rs b/src/test/run-pass/foreign-mod-unused-const.rs index e1ed0b8ea3b0..03023f032335 100644 --- a/src/test/run-pass/foreign-mod-unused-const.rs +++ b/src/test/run-pass/foreign-mod-unused-const.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate extern crate libc; diff --git a/src/test/run-pass/foreign2.rs b/src/test/run-pass/foreign2.rs index ce2f89556643..5ebc4effb371 100644 --- a/src/test/run-pass/foreign2.rs +++ b/src/test/run-pass/foreign2.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate extern crate libc; diff --git a/src/test/run-pass/issue-4735.rs b/src/test/run-pass/issue-4735.rs index bf422bd0405a..196e9748b107 100644 --- a/src/test/run-pass/issue-4735.rs +++ b/src/test/run-pass/issue-4735.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate #![allow(unknown_features)] #![feature(box_syntax)] diff --git a/src/test/run-pass/newtype-struct-with-dtor.rs b/src/test/run-pass/newtype-struct-with-dtor.rs index 8631755f37fd..15c4e8b04533 100644 --- a/src/test/run-pass/newtype-struct-with-dtor.rs +++ b/src/test/run-pass/newtype-struct-with-dtor.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate extern crate libc; use libc::c_int; diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs index 5a476ed9ee2f..b3fff6977a54 100644 --- a/src/test/run-pass/variadic-ffi.rs +++ b/src/test/run-pass/variadic-ffi.rs @@ -13,7 +13,6 @@ extern crate libc; use std::ffi::{self, CString}; use libc::{c_char, c_int}; -// ignore-fast doesn't like extern crate extern { fn sprintf(s: *mut c_char, format: *const c_char, ...) -> c_int; From 1552f672d40c8765bc35136463831503473b2e91 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 5 Mar 2015 17:38:18 -0800 Subject: [PATCH 26/37] Remove run-pass/lint-cstack.rs. No longer testing anything. --- src/test/run-pass/lint-cstack.rs | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 src/test/run-pass/lint-cstack.rs diff --git a/src/test/run-pass/lint-cstack.rs b/src/test/run-pass/lint-cstack.rs deleted file mode 100644 index f180ffcd4e82..000000000000 --- a/src/test/run-pass/lint-cstack.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate libc; - -extern { - fn rust_get_test_int() -> libc::intptr_t; -} - -trait A { - fn foo(&self) { - unsafe { - rust_get_test_int(); - } - } -} - -pub fn main() { -} From 96b1f0c0be849d785cb4597ea9a8d088c3a2adf4 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 5 Mar 2015 20:45:54 -0500 Subject: [PATCH 27/37] Fix reference to 'librlibc' in libcore docs Fixes #23059 --- src/libcore/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 94d37cee5b37..b1cfdbf69c3e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -35,8 +35,7 @@ //! often generated by LLVM. Additionally, this library can make explicit //! calls to these functions. Their signatures are the same as found in C. //! These functions are often provided by the system libc, but can also be -//! provided by `librlibc` which is distributed with the standard rust -//! distribution. +//! provided by the [rlibc crate](https://crates.io/crates/rlibc). //! //! * `rust_begin_unwind` - This function takes three arguments, a //! `fmt::Arguments`, a `&str`, and a `usize`. These three arguments dictate From ccd83daa418310f2a48af29b1e6545577e579e65 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Fri, 6 Mar 2015 10:03:00 +0800 Subject: [PATCH 28/37] file permission: remove executable bit from *.rs Signed-off-by: Lai Jiangshan --- src/libstd/path.rs | 0 src/test/auxiliary/lint_output_format.rs | 0 src/test/compile-fail/send-is-not-static-ensures-scoping.rs | 0 src/test/run-make/mismatching-target-triples/bar.rs | 0 src/test/run-make/mismatching-target-triples/foo.rs | 0 src/test/run-make/pretty-expanded-hygiene/input.pp.rs | 0 src/test/run-make/pretty-expanded-hygiene/input.rs | 0 src/test/run-make/simd-ffi/simd.rs | 0 src/test/run-pass/send-is-not-static-par-for.rs | 0 9 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/libstd/path.rs mode change 100755 => 100644 src/test/auxiliary/lint_output_format.rs mode change 100755 => 100644 src/test/compile-fail/send-is-not-static-ensures-scoping.rs mode change 100755 => 100644 src/test/run-make/mismatching-target-triples/bar.rs mode change 100755 => 100644 src/test/run-make/mismatching-target-triples/foo.rs mode change 100755 => 100644 src/test/run-make/pretty-expanded-hygiene/input.pp.rs mode change 100755 => 100644 src/test/run-make/pretty-expanded-hygiene/input.rs mode change 100755 => 100644 src/test/run-make/simd-ffi/simd.rs mode change 100755 => 100644 src/test/run-pass/send-is-not-static-par-for.rs diff --git a/src/libstd/path.rs b/src/libstd/path.rs old mode 100755 new mode 100644 diff --git a/src/test/auxiliary/lint_output_format.rs b/src/test/auxiliary/lint_output_format.rs old mode 100755 new mode 100644 diff --git a/src/test/compile-fail/send-is-not-static-ensures-scoping.rs b/src/test/compile-fail/send-is-not-static-ensures-scoping.rs old mode 100755 new mode 100644 diff --git a/src/test/run-make/mismatching-target-triples/bar.rs b/src/test/run-make/mismatching-target-triples/bar.rs old mode 100755 new mode 100644 diff --git a/src/test/run-make/mismatching-target-triples/foo.rs b/src/test/run-make/mismatching-target-triples/foo.rs old mode 100755 new mode 100644 diff --git a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs old mode 100755 new mode 100644 diff --git a/src/test/run-make/pretty-expanded-hygiene/input.rs b/src/test/run-make/pretty-expanded-hygiene/input.rs old mode 100755 new mode 100644 diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs old mode 100755 new mode 100644 diff --git a/src/test/run-pass/send-is-not-static-par-for.rs b/src/test/run-pass/send-is-not-static-par-for.rs old mode 100755 new mode 100644 From 3f94260b0fb2639ba81a5458ec54329e4b860afd Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 5 Mar 2015 23:03:30 +0200 Subject: [PATCH 29/37] Fix an easy to trigger deadlock in std::io::stdio Being a person who somehow has taken a liking to premature optimisation, my knee-jerk reaction to locking in std handles was preamble resembling following snippet: let stdout = stdout(); let lstdout = stdout.lock(); let stdin = stdin(); let lstdin = stdin.lock(); and then reading from the locked handle like this: let mut letter = [0; 1]; lstdin.read(&mut letter).unwrap(); As it is now this code will deadlock because the `read` method attempts to lock stdout as well! --- src/libstd/io/stdio.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 61ad9905771a..4027f741654b 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -157,9 +157,6 @@ impl Read for Stdin { impl<'a> Read for StdinLock<'a> { fn read(&mut self, buf: &mut [u8]) -> io::Result { - // Flush stdout so that weird issues like a print!'d prompt not being - // shown until after the user hits enter. - drop(stdout().flush()); self.inner.read(buf) } } From 707f7a1617013f7684fe81a1bba2dd77acbaaa73 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 6 Mar 2015 08:07:50 -0500 Subject: [PATCH 30/37] Check that traits with default impls have no methods fixes #23080 --- src/librustc_typeck/check/mod.rs | 28 +++++++++++++++++++++++++++ src/test/compile-fail/issue-23080.rs | 29 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/test/compile-fail/issue-23080.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 595a2295674a..57469d94ce8c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -465,6 +465,29 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { } } +// Check that trait with default impls (`impl Trait for ..`) contain no methods +struct DefaultedTraitVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } + +impl<'a, 'tcx> Visitor<'tcx> for DefaultedTraitVisitor<'a, 'tcx> { + fn visit_item(&mut self, item: &ast::Item) { + let tcx = self.ccx.tcx; + + match item.node { + ast::ItemTrait(_, _, _, ref trait_methods) => { + if ty::trait_has_default_impl(tcx, local_def(item.id)) && + !trait_methods.is_empty() + { + tcx.sess.span_err( + item.span, + "traits with default impls (`e.g. impl Trait for ..`) must have no \ + methods") + } + }, + _ => {}, + } + } +} + pub fn check_item_types(ccx: &CrateCtxt) { let krate = ccx.tcx.map.krate(); let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx); @@ -478,6 +501,11 @@ pub fn check_item_types(ccx: &CrateCtxt) { visit::walk_crate(&mut visit, krate); ccx.tcx.sess.abort_if_errors(); + + let mut visit = DefaultedTraitVisitor { ccx: ccx }; + visit::walk_crate(&mut visit, krate); + + ccx.tcx.sess.abort_if_errors(); } fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, diff --git a/src/test/compile-fail/issue-23080.rs b/src/test/compile-fail/issue-23080.rs new file mode 100644 index 000000000000..61b9a1a14e0e --- /dev/null +++ b/src/test/compile-fail/issue-23080.rs @@ -0,0 +1,29 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] + +unsafe trait Trait { +//~^ error: traits with default impls (`e.g. impl Trait for ..`) must have no methods + fn method(&self) { + println!("Hello"); + } +} + +unsafe impl Trait for .. {} + +fn call_method(x: T) { + x.method(); +} + +fn main() { + // ICE + call_method(()); +} From 61c6b199bcc23fe931f3fda2f968442256e07dab Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 6 Mar 2015 11:03:51 +0530 Subject: [PATCH 31/37] BufferedWriter -> BufWriter (fixup #23060) --- src/librustdoc/html/render.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4af6a6d229f5..2578912127eb 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1228,7 +1228,7 @@ impl Context { { let items = this.build_sidebar_items(&m); let js_dst = this.dst.join("sidebar-items.js"); - let mut js_out = BufferedWriter::new(try!(File::create(&js_dst))); + let mut js_out = BufWriter::new(try!(File::create(&js_dst))); try!(write!(&mut js_out, "initSidebarItems({});", json::as_json(&items))); } From 8a391dd8cf2ff938a392cbd177dc0a21d644d627 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 6 Mar 2015 12:14:38 -0500 Subject: [PATCH 32/37] move check into wf pass, add a test for assoc types --- src/librustc_typeck/check/mod.rs | 28 ------------------------- src/librustc_typeck/check/wf.rs | 10 ++++++++- src/test/compile-fail/issue-23080-2.rs | 29 ++++++++++++++++++++++++++ src/test/compile-fail/issue-23080.rs | 4 +++- 4 files changed, 41 insertions(+), 30 deletions(-) create mode 100644 src/test/compile-fail/issue-23080-2.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 57469d94ce8c..595a2295674a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -465,29 +465,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { } } -// Check that trait with default impls (`impl Trait for ..`) contain no methods -struct DefaultedTraitVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } - -impl<'a, 'tcx> Visitor<'tcx> for DefaultedTraitVisitor<'a, 'tcx> { - fn visit_item(&mut self, item: &ast::Item) { - let tcx = self.ccx.tcx; - - match item.node { - ast::ItemTrait(_, _, _, ref trait_methods) => { - if ty::trait_has_default_impl(tcx, local_def(item.id)) && - !trait_methods.is_empty() - { - tcx.sess.span_err( - item.span, - "traits with default impls (`e.g. impl Trait for ..`) must have no \ - methods") - } - }, - _ => {}, - } - } -} - pub fn check_item_types(ccx: &CrateCtxt) { let krate = ccx.tcx.map.krate(); let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx); @@ -501,11 +478,6 @@ pub fn check_item_types(ccx: &CrateCtxt) { visit::walk_crate(&mut visit, krate); ccx.tcx.sess.abort_if_errors(); - - let mut visit = DefaultedTraitVisitor { ccx: ccx }; - visit::walk_crate(&mut visit, krate); - - ccx.tcx.sess.abort_if_errors(); } fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index aa7e2b6dcce8..8185f48cb8c7 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -118,7 +118,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { self.check_variances_for_type_defn(item, ast_generics); } - ast::ItemTrait(_, ref ast_generics, _, _) => { + ast::ItemTrait(_, ref ast_generics, _, ref items) => { let trait_predicates = ty::lookup_predicates(ccx.tcx, local_def(item.id)); reject_non_type_param_bounds( @@ -127,6 +127,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { &trait_predicates); self.check_variances(item, ast_generics, &trait_predicates, self.tcx().lang_items.phantom_fn()); + if ty::trait_has_default_impl(ccx.tcx, local_def(item.id)) { + if !items.is_empty() { + ccx.tcx.sess.span_err( + item.span, + "traits with default impls (`e.g. unsafe impl Trait for ..`) must \ + have no methods or associated items") + } + } } _ => {} } diff --git a/src/test/compile-fail/issue-23080-2.rs b/src/test/compile-fail/issue-23080-2.rs new file mode 100644 index 000000000000..ff5ac9de8d94 --- /dev/null +++ b/src/test/compile-fail/issue-23080-2.rs @@ -0,0 +1,29 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +unsafe trait Trait: MarkerTrait { +//~^ error: traits with default impls (`e.g. unsafe impl Trait for ..`) must have no methods or associated items + type Output; +} + +unsafe impl Trait for .. {} + +fn call_method(x: T) {} + +fn main() { + // ICE + call_method(()); +} diff --git a/src/test/compile-fail/issue-23080.rs b/src/test/compile-fail/issue-23080.rs index 61b9a1a14e0e..99373a69697a 100644 --- a/src/test/compile-fail/issue-23080.rs +++ b/src/test/compile-fail/issue-23080.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + #![feature(optin_builtin_traits)] unsafe trait Trait { -//~^ error: traits with default impls (`e.g. impl Trait for ..`) must have no methods +//~^ error: traits with default impls (`e.g. unsafe impl Trait for ..`) must have no methods or associated items fn method(&self) { println!("Hello"); } From f7594e14b8bf291c7312332947f17f4411a02b3a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 6 Mar 2015 10:10:47 -0800 Subject: [PATCH 33/37] Remove two green threading tests --- src/test/run-pass/extern-stress.rs | 49 ------------------------------ src/test/run-pass/extern-yield.rs | 48 ----------------------------- 2 files changed, 97 deletions(-) delete mode 100644 src/test/run-pass/extern-stress.rs delete mode 100644 src/test/run-pass/extern-yield.rs diff --git a/src/test/run-pass/extern-stress.rs b/src/test/run-pass/extern-stress.rs deleted file mode 100644 index b9e08e47b378..000000000000 --- a/src/test/run-pass/extern-stress.rs +++ /dev/null @@ -1,49 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This creates a bunch of descheduling tasks that run concurrently -// while holding onto C stacks - -extern crate libc; -use std::thread::Thread; - -mod rustrt { - extern crate libc; - - #[link(name = "rust_test_helpers")] - extern { - pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, - data: libc::uintptr_t) - -> libc::uintptr_t; - } -} - -extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t { - if data == 1 { - data - } else { - Thread::yield_now(); - count(data - 1) + count(data - 1) - } -} - -fn count(n: libc::uintptr_t) -> libc::uintptr_t { - unsafe { - rustrt::rust_dbg_call(cb, n) - } -} - -pub fn main() { - (0_usize..100).map(|_| { - Thread::scoped(move|| { - assert_eq!(count(5), 16); - }) - }).collect::>(); -} diff --git a/src/test/run-pass/extern-yield.rs b/src/test/run-pass/extern-yield.rs deleted file mode 100644 index 80428d787f21..000000000000 --- a/src/test/run-pass/extern-yield.rs +++ /dev/null @@ -1,48 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate libc; -use std::thread::Thread; - -mod rustrt { - extern crate libc; - - #[link(name = "rust_test_helpers")] - extern { - pub fn rust_dbg_call(cb: extern "C" fn (libc::uintptr_t) -> libc::uintptr_t, - data: libc::uintptr_t) - -> libc::uintptr_t; - } -} - -extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t { - if data == 1 { - data - } else { - count(data - 1) + count(data - 1) - } -} - -fn count(n: libc::uintptr_t) -> libc::uintptr_t { - unsafe { - Thread::yield_now(); - rustrt::rust_dbg_call(cb, n) - } -} - -pub fn main() { - (0..10_usize).map(|i| { - Thread::scoped(move|| { - let result = count(5); - println!("result = {}", result); - assert_eq!(result, 16); - }) - }).collect::>(); -} From 9aea749b835a6fdcad6f2840a00adac996cc0339 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 25 Feb 2015 13:08:51 -0800 Subject: [PATCH 34/37] std: Deprecate the std::old_io::net primitives The `std::net` primitives should be ready for use now and as a result the old ones are now deprecated and slated for removal. Most TCP/UDP functionality is now available through `std::net` but the `std::old_io::net::pipe` module is removed entirely from the standard library. Unix socket funtionality can be found in sfackler's [`unix_socket`][unix] crate and there is currently no replacement for named pipes on Windows. [unix]: https://crates.io/crates/unix_socket [breaking-change] --- src/libstd/old_io/net/mod.rs | 4 ++++ src/libstd/old_io/net/pipe.rs | 6 ++++++ src/libstd/sys/common/net.rs | 2 ++ src/libstd/sys/unix/ext.rs | 7 +++++++ src/libstd/sys/unix/tcp.rs | 2 ++ src/libstd/sys/windows/ext.rs | 7 +++++++ src/libstd/sys/windows/tcp.rs | 2 ++ 7 files changed, 30 insertions(+) diff --git a/src/libstd/old_io/net/mod.rs b/src/libstd/old_io/net/mod.rs index bbe3a71dcc0d..a3567290b0e1 100644 --- a/src/libstd/old_io/net/mod.rs +++ b/src/libstd/old_io/net/mod.rs @@ -10,6 +10,10 @@ //! Networking I/O +#![deprecated(since = "1.0.0", + reason = "replaced with new I/O primitives in `std::net`")] +#![unstable(feature = "old_io")] + use old_io::{IoError, IoResult, InvalidInput}; use ops::FnMut; use option::Option::None; diff --git a/src/libstd/old_io/net/pipe.rs b/src/libstd/old_io/net/pipe.rs index d05669d32b8c..2ecaf515f081 100644 --- a/src/libstd/old_io/net/pipe.rs +++ b/src/libstd/old_io/net/pipe.rs @@ -19,6 +19,12 @@ //! instances as clients. #![allow(missing_docs)] +#![deprecated(since = "1.0.0", + reason = "will be removed to be reintroduced at a later date; \ + in the meantime consider using the `unix_socket` crate \ + for unix sockets; there is currently no replacement \ + for named pipes")] +#![unstable(feature = "old_io")] use prelude::v1::*; diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 228362e3d62a..344645dfc1a1 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use prelude::v1::*; use self::SocketStatus::*; use self::InAddr::*; diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index 45042d6f0325..ca7f7c4c0ca4 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -73,42 +73,49 @@ impl AsRawFd for old_io::pipe::PipeStream { } } +#[allow(deprecated)] impl AsRawFd for old_io::net::pipe::UnixStream { fn as_raw_fd(&self) -> Fd { self.as_inner().fd() } } +#[allow(deprecated)] impl AsRawFd for old_io::net::pipe::UnixListener { fn as_raw_fd(&self) -> Fd { self.as_inner().fd() } } +#[allow(deprecated)] impl AsRawFd for old_io::net::pipe::UnixAcceptor { fn as_raw_fd(&self) -> Fd { self.as_inner().fd() } } +#[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpStream { fn as_raw_fd(&self) -> Fd { self.as_inner().fd() } } +#[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpListener { fn as_raw_fd(&self) -> Fd { self.as_inner().fd() } } +#[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpAcceptor { fn as_raw_fd(&self) -> Fd { self.as_inner().fd() } } +#[allow(deprecated)] impl AsRawFd for old_io::net::udp::UdpSocket { fn as_raw_fd(&self) -> Fd { self.as_inner().fd() diff --git a/src/libstd/sys/unix/tcp.rs b/src/libstd/sys/unix/tcp.rs index b08f6ef9b903..4fcaf504c3da 100644 --- a/src/libstd/sys/unix/tcp.rs +++ b/src/libstd/sys/unix/tcp.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use prelude::v1::*; use old_io::net::ip; diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs index df18b404f5fe..b30aec084392 100644 --- a/src/libstd/sys/windows/ext.rs +++ b/src/libstd/sys/windows/ext.rs @@ -58,18 +58,21 @@ impl AsRawHandle for old_io::pipe::PipeStream { } } +#[allow(deprecated)] impl AsRawHandle for old_io::net::pipe::UnixStream { fn as_raw_handle(&self) -> Handle { self.as_inner().handle() } } +#[allow(deprecated)] impl AsRawHandle for old_io::net::pipe::UnixListener { fn as_raw_handle(&self) -> Handle { self.as_inner().handle() } } +#[allow(deprecated)] impl AsRawHandle for old_io::net::pipe::UnixAcceptor { fn as_raw_handle(&self) -> Handle { self.as_inner().handle() @@ -81,24 +84,28 @@ pub trait AsRawSocket { fn as_raw_socket(&self) -> Socket; } +#[allow(deprecated)] impl AsRawSocket for old_io::net::tcp::TcpStream { fn as_raw_socket(&self) -> Socket { self.as_inner().fd() } } +#[allow(deprecated)] impl AsRawSocket for old_io::net::tcp::TcpListener { fn as_raw_socket(&self) -> Socket { self.as_inner().socket() } } +#[allow(deprecated)] impl AsRawSocket for old_io::net::tcp::TcpAcceptor { fn as_raw_socket(&self) -> Socket { self.as_inner().socket() } } +#[allow(deprecated)] impl AsRawSocket for old_io::net::udp::UdpSocket { fn as_raw_socket(&self) -> Socket { self.as_inner().fd() diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs index 25b70918591d..8547de145f8c 100644 --- a/src/libstd/sys/windows/tcp.rs +++ b/src/libstd/sys/windows/tcp.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use old_io::net::ip; use old_io::IoResult; use libc; From 16ff1401d8fb11b9c0f5fab8052b2a993ff93916 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Mar 2015 13:54:42 -0800 Subject: [PATCH 35/37] std: Ignore a test on windows This test is known to fail on windows. --- src/libstd/fs/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs index ef2dd65a8161..42bc636d4bd5 100644 --- a/src/libstd/fs/mod.rs +++ b/src/libstd/fs/mod.rs @@ -1552,6 +1552,7 @@ mod tests { } #[test] + #[cfg(not(windows))] fn unlink_readonly() { let tmpdir = tmpdir(); let path = tmpdir.join("file"); From 1a30412ebf4363acf92f1edafa2c007617c94d02 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Mar 2015 15:11:59 -0800 Subject: [PATCH 36/37] Suppress some warnings about features --- src/librustc/lib.rs | 2 ++ src/librustc_trans/lib.rs | 1 + src/librustdoc/lib.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index be625affc2ef..d39b14e6fee5 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -44,7 +44,9 @@ #![feature(path)] #![feature(io)] #![feature(path_ext)] +#![feature(str_words)] #![cfg_attr(test, feature(test))] + extern crate arena; extern crate flate; extern crate fmt_macros; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 5f97709dd331..01076a4afa26 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -44,6 +44,7 @@ #![feature(os)] #![feature(path_ext)] #![feature(fs)] +#![feature(hash)] extern crate arena; extern crate flate; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 80584da265c0..c203dc0e7199 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -38,6 +38,7 @@ #![feature(str_words)] #![feature(io)] #![feature(path)] +#![feature(file_path)] #![feature(path_ext)] extern crate arena; From aed31ee08e9adff815e8a5df2499f2e4c6e7916b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Mar 2015 15:53:32 -0800 Subject: [PATCH 37/37] Test fixes and rebase conflicts --- src/librustc_llvm/lib.rs | 2 +- src/librustc_trans/lib.rs | 2 -- src/libstd/fs/mod.rs | 9 +++++++-- src/libstd/net/addr.rs | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 5bf872b3a1d5..0ff96784e58d 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -31,8 +31,8 @@ #![feature(libc)] #![feature(link_args)] #![feature(staged_api)] -#![feature(std_misc)] #![feature(path)] +#![cfg_attr(unix, feature(std_misc))] extern crate libc; #[macro_use] #[no_link] extern crate rustc_bitflags; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 08e31a6b3394..b74f85aa8661 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -40,11 +40,9 @@ #![feature(unicode)] #![feature(io)] #![feature(path)] -#![feature(os)] #![feature(path_ext)] #![feature(fs)] #![feature(hash)] -#![feature(tempdir)] extern crate arena; extern crate flate; diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs index 42bc636d4bd5..80ec9909824b 100644 --- a/src/libstd/fs/mod.rs +++ b/src/libstd/fs/mod.rs @@ -1313,6 +1313,8 @@ mod tests { check!(fs::set_permissions(&input, p)); check!(fs::copy(&input, &out)); assert!(check!(out.metadata()).permissions().readonly()); + check!(fs::set_permissions(&input, attr.permissions())); + check!(fs::set_permissions(&out, attr.permissions())); } #[cfg(not(windows))] // FIXME(#10264) operation not permitted? @@ -1396,10 +1398,13 @@ mod tests { let attr = check!(fs::metadata(&file)); assert!(attr.permissions().readonly()); - match fs::set_permissions(&tmpdir.join("foo"), p) { - Ok(..) => panic!("wanted a panic"), + match fs::set_permissions(&tmpdir.join("foo"), p.clone()) { + Ok(..) => panic!("wanted an error"), Err(..) => {} } + + p.set_readonly(false); + check!(fs::set_permissions(&file, p)); } #[test] diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index d975369af494..101aae3eb248 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -592,6 +592,7 @@ mod tests { } #[test] + #[cfg(not(windows))] fn to_socket_addr_str_bad() { assert!(tsa("1200::AB00:1234::2552:7777:1313:34300").is_err()); }

")); for (i, name) in cx.current.iter().take(parentlen).enumerate() { if i > 0 { From 215d287982b0ea678312892fb2f8db58acebd3b8 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 5 Mar 2015 15:03:14 +0100 Subject: [PATCH 12/37] debuginfo: Add test case for `extern "C"` functions. --- src/test/debuginfo/extern-c-fn.rs | 68 +++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/test/debuginfo/extern-c-fn.rs diff --git a/src/test/debuginfo/extern-c-fn.rs b/src/test/debuginfo/extern-c-fn.rs new file mode 100644 index 000000000000..9e73417e7de7 --- /dev/null +++ b/src/test/debuginfo/extern-c-fn.rs @@ -0,0 +1,68 @@ +// Copyright 2013-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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// min-lldb-version: 310 + +// compile-flags:-g + +// === GDB TESTS =================================================================================== +// gdb-command:run + +// gdb-command:print s +// gdb-check:$1 = [...]"abcd" +// gdb-command:print len +// gdb-check:$2 = 20 +// gdb-command:print local0 +// gdb-check:$3 = 19 +// gdb-command:print local1 +// gdb-check:$4 = true +// gdb-command:print local2 +// gdb-check:$5 = 20.5 + +// gdb-command:continue + +// === LLDB TESTS ================================================================================== +// lldb-command:run + +// lldb-command:print len +// lldb-check:[...]$0 = 20 +// lldb-command:print local0 +// lldb-check:[...]$1 = 19 +// lldb-command:print local1 +// lldb-check:[...]$2 = true +// lldb-command:print local2 +// lldb-check:[...]$3 = 20.5 + +// lldb-command:continue + +#![allow(unused_variables)] +#![allow(dead_code)] +#![omit_gdb_pretty_printer_section] + + +#[no_mangle] +pub unsafe extern "C" fn fn_with_c_abi(s: *const u8, len: i32) -> i32 { + let local0 = len - 1; + let local1 = len > 2; + let local2 = (len as f64) + 0.5; + + zzz(); // #break + + return 0; +} + +fn main() { + unsafe { + fn_with_c_abi(b"abcd\0".as_ptr(), 20); + } +} + +#[inline(never)] +fn zzz() {()} From 951ef9d1f105984383b9795c56f7ab8fdd681b63 Mon Sep 17 00:00:00 2001 From: awlnx Date: Thu, 5 Mar 2015 11:53:51 -0500 Subject: [PATCH 13/37] fix for new attributes failing. issue #22964 --- src/liballoc/lib.rs | 2 ++ src/libarena/lib.rs | 2 ++ src/libcollections/lib.rs | 3 ++- src/libcore/lib.rs | 2 ++ src/libcoretest/lib.rs | 2 ++ src/libflate/lib.rs | 2 ++ src/libfmt_macros/lib.rs | 2 ++ src/libgetopts/lib.rs | 3 +++ src/libgraphviz/lib.rs | 2 ++ src/liblibc/lib.rs | 2 ++ src/liblog/lib.rs | 2 ++ src/librand/lib.rs | 2 ++ src/librbml/lib.rs | 2 ++ src/librustc/lib.rs | 3 ++- src/librustc_back/lib.rs | 2 ++ src/librustc_bitflags/lib.rs | 3 +++ src/librustc_borrowck/lib.rs | 2 ++ src/librustc_driver/lib.rs | 2 ++ src/librustc_lint/lib.rs | 2 ++ src/librustc_llvm/lib.rs | 2 ++ src/librustc_privacy/lib.rs | 2 ++ src/librustc_resolve/lib.rs | 2 ++ src/librustc_trans/lib.rs | 2 ++ src/librustc_typeck/lib.rs | 3 ++- src/librustdoc/lib.rs | 2 ++ src/libserialize/lib.rs | 2 ++ src/libstd/lib.rs | 3 ++- src/libsyntax/lib.rs | 2 ++ src/libterm/lib.rs | 2 ++ src/libtest/lib.rs | 2 ++ src/libunicode/lib.rs | 2 ++ 31 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 82bd13475c74..828e6b8dd761 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -56,6 +56,8 @@ //! The [`heap`](heap/index.html) module defines the low-level interface to the //! default global allocator. It is not compatible with the libc allocator API. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "alloc"] #![unstable(feature = "alloc")] #![feature(staged_api)] diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index b43f9adfb26d..b2ac9a34b026 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -19,6 +19,8 @@ //! arena but can only hold objects of a single type, and `Arena`, which is a //! more complex, slower arena which can hold objects of any type. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "arena"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 7b66bfee34f2..9c1c2cc5906e 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -12,7 +12,8 @@ //! //! See [std::collections](../std/collections) for a detailed discussion of collections in Rust. - +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "collections"] #![unstable(feature = "collections")] #![staged_api] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 7cc963bed358..ea39ab3da5e7 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -47,6 +47,8 @@ // Since libcore defines many fundamental lang items, all tests live in a // separate crate, libcoretest, to avoid bizarre issues. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "core"] #![unstable(feature = "core")] #![staged_api] diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 03924910e048..1dbbb845d46e 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![feature(box_syntax)] #![feature(int_uint)] #![feature(unboxed_closures)] diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 2ce52cdec256..ec75c1022248 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -14,6 +14,8 @@ //! [def]: https://en.wikipedia.org/wiki/DEFLATE //! [mz]: https://code.google.com/p/miniz/ +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "flate"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 4e25e51e9a46..9b220409ef59 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -14,6 +14,8 @@ //! Parsing does not happen at runtime: structures of `std::fmt::rt` are //! generated instead. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "fmt_macros"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 6240b0e6afdd..c33c48476d56 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -77,6 +77,9 @@ //! } //! ``` + +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "getopts"] #![unstable(feature = "rustc_private", reason = "use the crates.io `getopts` library instead")] diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 09fbf4935e4c..751cbe688d19 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -264,6 +264,8 @@ //! //! * [DOT language](http://www.graphviz.org/doc/info/lang.html) +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "graphviz"] #![unstable(feature = "rustc_private")] #![feature(staged_api)] diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 42143b06ca0e..4051ae9d33aa 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "libc"] #![crate_type = "rlib"] #![cfg_attr(not(feature = "cargo-build"), diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index d0105bb65776..3b6e1d046914 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -155,6 +155,8 @@ //! they're turned off (just a load and an integer comparison). This also means that //! if logging is disabled, none of the components of the log will be executed. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "log"] #![unstable(feature = "rustc_private", reason = "use the crates.io `log` library instead")] diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 583c658dfe05..7acd6cda0445 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -16,6 +16,8 @@ //! is not recommended to use this library directly, but rather the official //! interface through `std::rand`. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rand"] #![crate_type = "rlib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png", diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 05cd24de7368..c247e3a3decc 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -15,6 +15,8 @@ //! It is loosely based on the Extensible Binary Markup Language (ebml): //! http://www.matroska.org/technical/specs/rfc/index.html +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rbml"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index aa51320ee7f4..53f44c0eb1ba 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -14,6 +14,8 @@ //! //! This API is completely unstable and subject to change. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -40,7 +42,6 @@ #![feature(std_misc)] #![feature(os)] #![cfg_attr(test, feature(test))] - extern crate arena; extern crate flate; extern crate fmt_macros; diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 9005c666afbc..f5fab17006c1 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -21,6 +21,8 @@ //! one that doesn't; the one that doesn't might get decent parallel //! build speedups. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_back"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/librustc_bitflags/lib.rs b/src/librustc_bitflags/lib.rs index 370a5d48deca..5115e9a4a207 100644 --- a/src/librustc_bitflags/lib.rs +++ b/src/librustc_bitflags/lib.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_bitflags"] #![feature(staged_api)] #![staged_api] diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index b7cfda280925..e09457970e12 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_borrowck"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index d08fb2b313ef..3292b2e026bc 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -14,6 +14,8 @@ //! //! This API is completely unstable and subject to change. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_driver"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 9eef0f1cf8b0..9781e9944f64 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -19,6 +19,8 @@ //! //! This API is completely unstable and subject to change. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_lint"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 09a187befb21..8f6ad3433170 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 46729988bb6b..859e4ab28580 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_privacy"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 78ce9abe07d9..7724f4253b74 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_resolve"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 71317d5875b8..5ccd7f61e01d 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -14,6 +14,8 @@ //! //! This API is completely unstable and subject to change. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_trans"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 78dd66c8e7db..bbc64a54013b 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -62,7 +62,8 @@ independently: This API is completely unstable and subject to change. */ - +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_typeck"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e58239a82c60..cbf7adcbe9a8 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustdoc"] #![unstable(feature = "rustdoc")] #![staged_api] diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index d476fd72abc3..8d58ba99e131 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -14,6 +14,8 @@ Core encoding and decoding interfaces. */ +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "serialize"] #![unstable(feature = "rustc_private", reason = "deprecated in favor of rustc-serialize on crates.io")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 7957bc35b76b..73848a51c1e2 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -94,7 +94,8 @@ //! to all code by default. [`macros`](macros/index.html) contains //! all the standard macros, such as `assert!`, `panic!`, `println!`, //! and `format!`, also available to all Rust code. - +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "std"] #![stable(feature = "rust1", since = "1.0.0")] #![staged_api] diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 7acbd10ef03d..091f3be631ea 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -14,6 +14,8 @@ //! //! This API is completely unstable and subject to change. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "syntax"] #![unstable(feature = "rustc_private")] #![staged_api] diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 756d67b5db1e..ed42c16f19a0 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -38,6 +38,8 @@ //! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx //! [ti]: https://en.wikipedia.org/wiki/Terminfo +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "term"] #![unstable(feature = "rustc_private", reason = "use the crates.io `term` library instead")] diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index a144904903e5..538c96cd63ca 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -23,6 +23,8 @@ // running tests while providing a base that other test frameworks may // build off of. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "test"] #![unstable(feature = "test")] #![staged_api] diff --git a/src/libunicode/lib.rs b/src/libunicode/lib.rs index 791886be1ce5..2095b6921c84 100644 --- a/src/libunicode/lib.rs +++ b/src/libunicode/lib.rs @@ -20,6 +20,8 @@ //! provide for basic string-related manipulations. This crate does not //! (yet) aim to provide a full set of Unicode tables. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "unicode"] #![unstable(feature = "unicode")] #![feature(staged_api)] From 7ed418c3b4ede0364bf419b2c12b27f89b706dcf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Mar 2015 10:41:42 -0800 Subject: [PATCH 14/37] std: Deprecate the old_io::process module This module is now superseded by the `std::process` module. This module still has some room to expand to get quite back up to parity with the `old_io` version, and there is a [tracking issue][issue] for feature requests as well as known room for expansion. [issue]: https://github.com/rust-lang/rfcs/issues/941 [breaking-change] --- src/librustc_back/target/apple_ios_base.rs | 16 ++++++++-------- src/libstd/old_io/process.rs | 3 +++ src/libstd/sys/unix/process.rs | 2 ++ src/libstd/sys/windows/process.rs | 2 ++ 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs index 904b337c03f4..2fbbe7d1f7c5 100644 --- a/src/librustc_back/target/apple_ios_base.rs +++ b/src/librustc_back/target/apple_ios_base.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::old_io::{Command, IoError, OtherIoError}; +use std::io; +use std::process::Command; use target::TargetOptions; use self::Arch::*; @@ -40,16 +41,15 @@ pub fn get_sdk_root(sdk_name: &str) -> String { .arg("--show-sdk-path") .arg("-sdk") .arg(sdk_name) - .spawn() - .and_then(|c| c.wait_with_output()) + .output() .and_then(|output| { if output.status.success() { - Ok(String::from_utf8(output.output).unwrap()) + Ok(String::from_utf8(output.stdout).unwrap()) } else { - Err(IoError { - kind: OtherIoError, - desc: "process exit with error", - detail: String::from_utf8(output.error).ok()}) + let error = String::from_utf8(output.stderr); + Err(io::Error::new(io::ErrorKind::Other, + "process exit with error", + error.ok())) } }); diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index a13295b1ccb5..e02e863516ab 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -11,6 +11,9 @@ //! Bindings for executing child processes #![allow(non_upper_case_globals)] +#![unstable(feature = "old_io")] +#![deprecated(since = "1.0.0", + reason = "replaced with the std::process module")] pub use self::StdioContainer::*; pub use self::ProcessExit::*; diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 68c5c65e7cdb..62a1799de94c 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use prelude::v1::*; use self::Req::*; diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 53a037ef07e6..ca3ed54eb036 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use prelude::v1::*; use collections; From 1eb37bf4573e6fc28c6595a60dd3868d6c7daea7 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Thu, 5 Mar 2015 20:53:53 +0100 Subject: [PATCH 15/37] Fix Playpen Links Containing Multiple Examples Fixes #22615. --- src/librustdoc/html/static/playpen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/playpen.js b/src/librustdoc/html/static/playpen.js index 687f764f0207..8fb979875cd7 100644 --- a/src/librustdoc/html/static/playpen.js +++ b/src/librustdoc/html/static/playpen.js @@ -15,7 +15,7 @@ if (window.playgroundUrl) { $('pre.rust').hover(function() { var a = $('').text('⇱').attr('class', 'test-arrow'); - var code = $(this).siblings(".rusttest").text(); + var code = $(this).prev(".rusttest").text(); a.attr('href', window.playgroundUrl + '?code=' + encodeURIComponent(code)); a.attr('target', '_blank'); From f0897aa17f98ff41f1eb6a3af40d84123d3d89d5 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 5 Mar 2015 16:20:02 -0500 Subject: [PATCH 16/37] OIBIT: for `PhantomData` check `T` rather than the struct itself --- src/librustc/middle/traits/select.rs | 7 +++++ src/test/compile-fail/phantom-oibit.rs | 41 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/test/compile-fail/phantom-oibit.rs diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 470315c78f81..5de67cfd38eb 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1700,6 +1700,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + // for `PhantomData`, we pass `T` + ty::ty_struct(def_id, substs) + if Some(def_id) == self.tcx().lang_items.phantom_data() => + { + Some(substs.types.get_slice(TypeSpace).to_vec()) + } + ty::ty_struct(def_id, substs) => { Some(ty::struct_fields(self.tcx(), def_id, substs).iter() .map(|f| f.mt.ty) diff --git a/src/test/compile-fail/phantom-oibit.rs b/src/test/compile-fail/phantom-oibit.rs new file mode 100644 index 000000000000..c912d084daa8 --- /dev/null +++ b/src/test/compile-fail/phantom-oibit.rs @@ -0,0 +1,41 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Ensure that OIBIT checks `T` when it encounters a `PhantomData` field, instead of checking +// the `PhantomData` type itself (which almost always implements a "default" trait +// (`impl Trait for ..`)) + +#![feature(optin_builtin_traits)] + +use std::marker::{MarkerTrait, PhantomData}; + +unsafe trait Zen: MarkerTrait {} + +unsafe impl Zen for .. {} + +unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {} + +struct Guard<'a, T: 'a> { + _marker: PhantomData<&'a T>, +} + +struct Nested(T); + +fn is_zen(_: T) {} + +fn not_sync(x: Guard) { + is_zen(x) //~ error: the trait `core::marker::Sync` is not implemented for the type `T` +} + +fn nested_not_sync(x: Nested>) { + is_zen(x) //~ error: the trait `core::marker::Sync` is not implemented for the type `T` +} + +fn main() {} From 93192524fb4e9411bd4163fdd5031b7fbc370eca Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Mar 2015 14:49:58 -0800 Subject: [PATCH 17/37] rustc: Don't emit dep-info for imported files Closes #23089 --- src/librustc_driver/driver.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 73682faf1a77..10be1810c218 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -797,7 +797,9 @@ fn write_out_deps(sess: &Session, // Build a list of files used to compile the output and // write Makefile-compatible dependency rules let files: Vec = sess.codemap().files.borrow() - .iter().filter(|fmap| fmap.is_real_file()) + .iter() + .filter(|fmap| fmap.is_real_file()) + .filter(|fmap| !fmap.is_imported()) .map(|fmap| escape_dep_filename(&fmap.name)) .collect(); let mut file = try!(fs::File::create(&deps_filename)); From d5d834551cd5a7e7d89ac9f2ae642a93409ed989 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 2 Mar 2015 14:51:24 -0800 Subject: [PATCH 18/37] rustc: Add a debug_assertions #[cfg] directive This commit is an implementation of [RFC 563][rfc] which adds a new `cfg(debug_assertions)` directive which is specially recognized and calculated by the compiler. The flag is turned off at any optimization level greater than 1 and may also be explicitly controlled through the `-C debug-assertions` flag. [rfc]: https://github.com/rust-lang/rfcs/pull/563 The `debug_assert!` and `debug_assert_eq!` macros now respect this instead of the `ndebug` variable and `ndebug` no longer holds any meaning to the standard library. Code which was previously relying on `not(ndebug)` to gate expensive code should be updated to rely on `debug_assertions` instead. Closes #22492 [breaking-change] --- mk/tests.mk | 2 +- src/libcore/macros.rs | 24 ++++++----- src/liblog/macros.rs | 4 +- src/librustc/session/config.rs | 16 +++++-- src/librustc_trans/trans/base.rs | 2 +- src/test/run-fail/overflowing-add.rs | 1 + src/test/run-fail/overflowing-mul.rs | 1 + src/test/run-fail/overflowing-sub.rs | 1 + src/test/run-make/debug-assertions/Makefile | 21 ++++++++++ src/test/run-make/debug-assertions/debug.rs | 42 +++++++++++++++++++ .../run-pass/conditional-debug-macro-off.rs | 2 +- src/test/run-pass/logging-enabled-debug.rs | 2 +- src/test/run-pass/logging-separate-lines.rs | 1 + 13 files changed, 100 insertions(+), 19 deletions(-) create mode 100644 src/test/run-make/debug-assertions/Makefile create mode 100644 src/test/run-make/debug-assertions/debug.rs diff --git a/mk/tests.mk b/mk/tests.mk index 838ed0dccfcb..ef38abcab651 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -590,7 +590,7 @@ TEST_SREQ$(1)_T_$(2)_H_$(3) = \ # The tests select when to use debug configuration on their own; # remove directive, if present, from CFG_RUSTC_FLAGS (issue #7898). -CTEST_RUSTC_FLAGS := $$(subst --cfg ndebug,,$$(CFG_RUSTC_FLAGS)) +CTEST_RUSTC_FLAGS := $$(subst -C debug-assertions,,$$(CFG_RUSTC_FLAGS)) # The tests cannot be optimized while the rest of the compiler is optimized, so # filter out the optimization (if any) from rustc and then figure out if we need diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 94ca9ec37b49..96c9beece1c0 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -100,10 +100,12 @@ macro_rules! assert_eq { /// This will invoke the `panic!` macro if the provided expression cannot be /// evaluated to `true` at runtime. /// -/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing -/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for -/// checks that are too expensive to be present in a release build but may be -/// helpful during development. +/// Unlike `assert!`, `debug_assert!` statements are only enabled in non +/// optimized builds by default. An optimized build will omit all +/// `debug_assert!` statements unless `-C debug-assertions` is passed to the +/// compiler. This makes `debug_assert!` useful for checks that are too +/// expensive to be present in a release build but may be helpful during +/// development. /// /// # Example /// @@ -125,7 +127,7 @@ macro_rules! assert_eq { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! debug_assert { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); }) + ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); }) } /// Asserts that two expressions are equal to each other, testing equality in @@ -133,10 +135,12 @@ macro_rules! debug_assert { /// /// On panic, this macro will print the values of the expressions. /// -/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by -/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!` -/// useful for checks that are too expensive to be present in a release build -/// but may be helpful during development. +/// Unlike `assert_eq!`, `debug_assert_eq!` statements are only enabled in non +/// optimized builds by default. An optimized build will omit all +/// `debug_assert_eq!` statements unless `-C debug-assertions` is passed to the +/// compiler. This makes `debug_assert_eq!` useful for checks that are too +/// expensive to be present in a release build but may be helpful during +/// development. /// /// # Example /// @@ -147,7 +151,7 @@ macro_rules! debug_assert { /// ``` #[macro_export] macro_rules! debug_assert_eq { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); }) + ($($arg:tt)*) => (if cfg!(debug_assertions) { assert_eq!($($arg)*); }) } /// Short circuiting evaluation on Err diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs index 4a9a9bd40600..f0f861a3831a 100644 --- a/src/liblog/macros.rs +++ b/src/liblog/macros.rs @@ -157,7 +157,7 @@ macro_rules! info { /// ``` #[macro_export] macro_rules! debug { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { log!(::log::DEBUG, $($arg)*) }) + ($($arg:tt)*) => (if cfg!(debug_assertions) { log!(::log::DEBUG, $($arg)*) }) } /// A macro to test whether a log level is enabled for the current module. @@ -192,7 +192,7 @@ macro_rules! debug { macro_rules! log_enabled { ($lvl:expr) => ({ let lvl = $lvl; - (lvl != ::log::DEBUG || cfg!(not(ndebug))) && + (lvl != ::log::DEBUG || cfg!(debug_assertions)) && lvl <= ::log::log_level() && ::log::mod_enabled(lvl, module_path!()) }) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index a4355803f4a4..1b09be050203 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -81,6 +81,7 @@ pub struct Options { pub gc: bool, pub optimize: OptLevel, + pub debug_assertions: bool, pub debuginfo: DebugInfoLevel, pub lint_opts: Vec<(String, lint::Level)>, pub describe_lints: bool, @@ -238,7 +239,8 @@ pub fn basic_options() -> Options { crate_name: None, alt_std_name: None, libs: Vec::new(), - unstable_features: UnstableFeatures::Disallow + unstable_features: UnstableFeatures::Disallow, + debug_assertions: true, } } @@ -528,6 +530,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, 2 = full debug info with variable and type information"), opt_level: Option = (None, parse_opt_uint, "Optimize with possible levels 0-3"), + debug_assertions: Option = (None, parse_opt_bool, + "explicitly enable the cfg(debug_assertions) directive"), } @@ -621,7 +625,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { }; let mk = attr::mk_name_value_item_str; - return vec!(// Target bindings. + let mut ret = vec![ // Target bindings. attr::mk_word_item(fam.clone()), mk(InternedString::new("target_os"), intern(os)), mk(InternedString::new("target_family"), fam), @@ -629,7 +633,11 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { mk(InternedString::new("target_endian"), intern(end)), mk(InternedString::new("target_pointer_width"), intern(wordsz)) - ); + ]; + if sess.opts.debug_assertions { + ret.push(attr::mk_word_item(InternedString::new("debug_assertions"))); + } + return ret; } pub fn append_configuration(cfg: &mut ast::CrateConfig, @@ -923,6 +931,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } } }; + let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == No); let gc = debugging_opts.gc; let debuginfo = if matches.opt_present("g") { if cg.debuginfo.is_some() { @@ -1064,6 +1073,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { alt_std_name: None, libs: libs, unstable_features: get_unstable_features_setting(), + debug_assertions: debug_assertions, } } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 13f882bc3631..cf4d0e543e37 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -3089,7 +3089,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks { v } else { - !attr::contains_name(&krate.config, "ndebug") + tcx.sess.opts.debug_assertions }; // Before we touch LLVM, make sure that multithreading is enabled. diff --git a/src/test/run-fail/overflowing-add.rs b/src/test/run-fail/overflowing-add.rs index 34a03e5f0080..cd13b817c2b8 100644 --- a/src/test/run-fail/overflowing-add.rs +++ b/src/test/run-fail/overflowing-add.rs @@ -9,6 +9,7 @@ // except according to those terms. // error-pattern:thread '