From 62645a13db527bbdb048d9c4f126d821bce26927 Mon Sep 17 00:00:00 2001 From: Falco Hirschenberger Date: Wed, 25 Mar 2015 16:10:49 +0100 Subject: [PATCH 01/46] Fix ICE when dividing integral SIMD types. Fixes #23339 --- src/librustc_trans/trans/base.rs | 13 +++++++++++-- src/test/run-pass/simd-binop.rs | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 2f944e49b15..ccda25eff39 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -41,7 +41,7 @@ use middle::cfg; use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; use middle::weak_lang_items; use middle::subst::{Subst, Substs}; -use middle::ty::{self, Ty, ClosureTyper}; +use middle::ty::{self, Ty, ClosureTyper, type_is_simd, simd_size}; use session::config::{self, NoDebugInfo}; use session::Session; use trans::_match; @@ -52,7 +52,7 @@ use trans::callee; use trans::cleanup::CleanupMethods; use trans::cleanup; use trans::closure; -use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral}; +use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_integral}; use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef}; use trans::common::{CrateContext, ExternMap, FunctionContext}; use trans::common::{Result, NodeIdAndSpan}; @@ -824,6 +824,15 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>( let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0, false); (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false) } + ty::ty_struct(_, _) if type_is_simd(cx.tcx(), rhs_t) => { + let mut res = C_bool(cx.ccx(), false); + for i in 0 .. simd_size(cx.tcx(), rhs_t) { + res = Or(cx, res, + IsNull(cx, + ExtractElement(cx, rhs, C_int(cx.ccx(), i as i64))), debug_loc); + } + (res, false) + } _ => { cx.sess().bug(&format!("fail-if-zero on unexpected type: {}", ty_to_string(cx.tcx(), rhs_t))); diff --git a/src/test/run-pass/simd-binop.rs b/src/test/run-pass/simd-binop.rs index 0d26b75c2ad..9f7b78e4e33 100644 --- a/src/test/run-pass/simd-binop.rs +++ b/src/test/run-pass/simd-binop.rs @@ -32,6 +32,7 @@ pub fn main() { assert!(eq_u32x4(u32x4(1, 2, 3, 4) + u32x4(4, 3, 2, 1), u32x4(5, 5, 5, 5))); assert!(eq_u32x4(u32x4(4, 5, 6, 7) - u32x4(4, 3, 2, 1), u32x4(0, 2, 4, 6))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) * u32x4(4, 3, 2, 1), u32x4(4, 6, 6, 4))); + assert!(eq_u32x4(u32x4(1, 2, 3, 4) / u32x4(4, 3, 2, 1), u32x4(0, 0, 1, 4))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) & u32x4(4, 3, 2, 1), u32x4(0, 2, 2, 0))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) | u32x4(4, 3, 2, 1), u32x4(5, 3, 3, 5))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) ^ u32x4(4, 3, 2, 1), u32x4(5, 1, 1, 5))); @@ -41,6 +42,7 @@ pub fn main() { assert!(eq_i32x4(i32x4(1, 2, 3, 4) + i32x4(4, 3, 2, 1), i32x4(5, 5, 5, 5))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) - i32x4(4, 3, 2, 1), i32x4(-3, -1, 1, 3))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) * i32x4(4, 3, 2, 1), i32x4(4, 6, 6, 4))); + assert!(eq_i32x4(i32x4(1, 2, 3, 4) / i32x4(4, 3, 2, 1), i32x4(0, 0, 1, 4))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) & i32x4(4, 3, 2, 1), i32x4(0, 2, 2, 0))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) | i32x4(4, 3, 2, 1), i32x4(5, 3, 3, 5))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) ^ i32x4(4, 3, 2, 1), i32x4(5, 1, 1, 5))); From 6370f2978e485fd46bcb64f51a1c003395acfedc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 26 Mar 2015 16:18:29 -0700 Subject: [PATCH 02/46] std: Stabilize parts of std::os::platform::io This commit stabilizes the platform-specific `io` modules, specifically around the traits having to do with the raw representation of each object on each platform. Specifically, the following material was stabilized: * `AsRaw{Fd,Socket,Handle}` * `RawFd` (renamed from `Fd`) * `RawHandle` (renamed from `Handle`) * `RawSocket` (renamed from `Socket`) * `AsRaw{Fd,Socket,Handle}` implementations * `std::os::{unix, windows}::io` The following material was added as `#[unstable]`: * `FromRaw{Fd,Socket,Handle}` * Implementations for various primitives There are a number of future improvements that are possible to make to this module, but this should cover a good bit of functionality desired from these modules for now. Some specific future additions may include: * `IntoRawXXX` traits to consume the raw representation and cancel the auto-destructor. * `Fd`, `Socket`, and `Handle` abstractions that behave like Rust objects and have nice methods for various syscalls. At this time though, these are considered backwards-compatible extensions and will not be stabilized at this time. This commit is a breaking change due to the addition of `Raw` in from of the type aliases in each of the platform-specific modules. [breaking-change] --- src/libstd/fs/mod.rs | 12 +++- src/libstd/net/tcp.rs | 12 +++- src/libstd/net/udp.rs | 6 +- src/libstd/sys/common/net2.rs | 18 +++++ src/libstd/sys/unix/ext.rs | 113 +++++++++++++++++++++++++------- src/libstd/sys/unix/fs2.rs | 6 ++ src/libstd/sys/unix/net.rs | 6 +- src/libstd/sys/windows/ext.rs | 120 +++++++++++++++++++++++++++------- src/libstd/sys/windows/fs2.rs | 15 +++-- src/libstd/sys/windows/net.rs | 8 ++- src/libstd/sys/windows/os.rs | 4 +- 11 files changed, 262 insertions(+), 58 deletions(-) diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs index c1253706832..b01cb53388f 100644 --- a/src/libstd/fs/mod.rs +++ b/src/libstd/fs/mod.rs @@ -56,7 +56,7 @@ mod tempdir; #[stable(feature = "rust1", since = "1.0.0")] pub struct File { inner: fs_imp::File, - path: PathBuf, + path: Option, } /// Metadata information about a file. @@ -171,7 +171,7 @@ impl File { 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) + self.path.as_ref().map(|p| &**p) } /// Attempt to sync all OS-internal metadata to disk. @@ -273,6 +273,12 @@ impl File { impl AsInner for File { fn as_inner(&self) -> &fs_imp::File { &self.inner } } +impl FromInner for File { + fn from_inner(f: fs_imp::File) -> File { + File { inner: f, path: None } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Read for File { fn read(&mut self, buf: &mut [u8]) -> io::Result { @@ -381,7 +387,7 @@ impl OpenOptions { pub fn open>(&self, path: P) -> io::Result { let path = path.as_ref(); let inner = try!(fs_imp::File::open(path, &self.0)); - Ok(File { path: path.to_path_buf(), inner: inner }) + Ok(File { path: Some(path.to_path_buf()), inner: inner }) } } diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 869faa795f9..9ed08d05e8b 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -17,7 +17,7 @@ use io::prelude::*; use io; use net::{ToSocketAddrs, SocketAddr, Shutdown}; use sys_common::net2 as net_imp; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; /// A structure which represents a TCP stream between a local socket and a /// remote socket. @@ -172,6 +172,10 @@ impl AsInner for TcpStream { fn as_inner(&self) -> &net_imp::TcpStream { &self.0 } } +impl FromInner for TcpStream { + fn from_inner(inner: net_imp::TcpStream) -> TcpStream { TcpStream(inner) } +} + impl TcpListener { /// Creates a new `TcpListener` which will be bound to the specified /// address. @@ -245,6 +249,12 @@ impl AsInner for TcpListener { fn as_inner(&self) -> &net_imp::TcpListener { &self.0 } } +impl FromInner for TcpListener { + fn from_inner(inner: net_imp::TcpListener) -> TcpListener { + TcpListener(inner) + } +} + #[cfg(test)] mod tests { use prelude::v1::*; diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 81151114962..4aeb3d7c7c8 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use io::{self, Error, ErrorKind}; use net::{ToSocketAddrs, SocketAddr, IpAddr}; use sys_common::net2 as net_imp; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; /// A User Datagram Protocol socket. /// @@ -140,6 +140,10 @@ impl AsInner for UdpSocket { fn as_inner(&self) -> &net_imp::UdpSocket { &self.0 } } +impl FromInner for UdpSocket { + fn from_inner(inner: net_imp::UdpSocket) -> UdpSocket { UdpSocket(inner) } +} + #[cfg(test)] mod tests { use prelude::v1::*; diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index e213a86644f..8b54b7e6fb4 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -222,6 +222,12 @@ impl TcpStream { } } +impl FromInner for TcpStream { + fn from_inner(socket: Socket) -> TcpStream { + TcpStream { inner: socket } + } +} + //////////////////////////////////////////////////////////////////////////////// // TCP listeners //////////////////////////////////////////////////////////////////////////////// @@ -275,6 +281,12 @@ impl TcpListener { } } +impl FromInner for TcpListener { + fn from_inner(socket: Socket) -> TcpListener { + TcpListener { inner: socket } + } +} + //////////////////////////////////////////////////////////////////////////////// // UDP //////////////////////////////////////////////////////////////////////////////// @@ -387,3 +399,9 @@ impl UdpSocket { self.inner.duplicate().map(|s| UdpSocket { inner: s }) } } + +impl FromInner for UdpSocket { + fn from_inner(socket: Socket) -> UdpSocket { + UdpSocket { inner: socket } + } +} diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index 0805949d560..080cf5620fc 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -32,102 +32,171 @@ #![stable(feature = "rust1", since = "1.0.0")] /// Unix-specific extensions to general I/O primitives -#[unstable(feature = "io_ext", - reason = "may want a slightly different organization or a more \ - general file descriptor primitive")] +#[stable(feature = "rust1", since = "1.0.0")] pub mod io { #[allow(deprecated)] use old_io; use fs; use libc; use net; - use sys_common::AsInner; + use sys_common::{net2, AsInner, FromInner}; + use sys; /// Raw file descriptors. - pub type Fd = libc::c_int; + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawFd = libc::c_int; - /// Extract raw file descriptor + /// A trait to extract the raw unix file descriptor from an underlying + /// object. + /// + /// This is only available on unix platforms and must be imported in order + /// to call the method. Windows platforms have a corresponding `AsRawHandle` + /// and `AsRawSocket` set of traits. + #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRawFd { - /// Extract the raw file descriptor, without taking any ownership. - fn as_raw_fd(&self) -> Fd; + /// Extract the raw file descriptor. + /// + /// This method does **not** pass ownership of the raw file descriptor + /// to the caller. The descriptor is only guarantee to be valid while + /// the original object has not yet been destroyed. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_fd(&self) -> RawFd; + } + + /// A trait to express the ability to construct an object from a raw file + /// descriptor. + #[unstable(feature = "from_raw_os", + reason = "recent addition to std::os::unix::io")] + pub trait FromRawFd { + /// Constructs a new instances of `Self` from the given raw file + /// descriptor. + /// + /// This function **consumes ownership** of the specified file + /// descriptor. The returned object will take responsibility for closing + /// it when the object goes out of scope. + /// + /// Callers should normally only pass in a valid file descriptor to this + /// method or otherwise methods will return errors. + fn from_raw_fd(fd: RawFd) -> Self; } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::fs::File { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for fs::File { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().raw() } } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for fs::File { + fn from_raw_fd(fd: RawFd) -> fs::File { + fs::File::from_inner(sys::fs2::File::from_inner(fd)) + } + } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::pipe::PipeStream { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::pipe::UnixStream { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::pipe::UnixListener { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::pipe::UnixAcceptor { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpStream { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpListener { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpAcceptor { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::udp::UdpSocket { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::TcpStream { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::TcpListener { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::UdpSocket { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } + } + + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::TcpStream { + fn from_raw_fd(fd: RawFd) -> net::TcpStream { + let socket = sys::net::Socket::from_inner(fd); + net::TcpStream::from_inner(net2::TcpStream::from_inner(socket)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::TcpListener { + fn from_raw_fd(fd: RawFd) -> net::TcpListener { + let socket = sys::net::Socket::from_inner(fd); + net::TcpListener::from_inner(net2::TcpListener::from_inner(socket)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::UdpSocket { + fn from_raw_fd(fd: RawFd) -> net::UdpSocket { + let socket = sys::net::Socket::from_inner(fd); + net::UdpSocket::from_inner(net2::UdpSocket::from_inner(socket)) + } } } @@ -302,7 +371,7 @@ pub mod process { #[stable(feature = "rust1", since = "1.0.0")] pub mod prelude { #[doc(no_inline)] - pub use super::io::{Fd, AsRawFd}; + pub use super::io::{RawFd, AsRawFd}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs index 202e5ddaec4..80fc1235a31 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs2.rs @@ -280,6 +280,12 @@ fn cstr(path: &Path) -> io::Result { Ok(cstring) } +impl FromInner for File { + fn from_inner(fd: c_int) -> File { + File(FileDesc::new(fd)) + } +} + pub fn mkdir(p: &Path) -> io::Result<()> { let p = try!(cstr(p)); try!(cvt(unsafe { libc::mkdir(p.as_ptr(), 0o777) })); diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index b22fa33e562..00b907ce10c 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -17,7 +17,7 @@ use str; use sys::c; use net::SocketAddr; use sys::fd::FileDesc; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; pub use sys::{cvt, cvt_r}; @@ -72,3 +72,7 @@ impl Socket { impl AsInner for Socket { fn as_inner(&self) -> &c_int { self.0.as_inner() } } + +impl FromInner for Socket { + fn from_inner(fd: c_int) -> Socket { Socket(FileDesc::new(fd)) } +} diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs index 7955397892b..2dd61861bd6 100644 --- a/src/libstd/sys/windows/ext.rs +++ b/src/libstd/sys/windows/ext.rs @@ -16,112 +16,188 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[unstable(feature = "io_ext", - reason = "organization may change slightly and the primitives \ - provided may be tweaked")] +#[stable(feature = "rust1", since = "1.0.0")] pub mod io { use fs; use libc; use net; - use sys_common::AsInner; + use sys_common::{net2, AsInner, FromInner}; + use sys; #[allow(deprecated)] use old_io; /// Raw HANDLEs. - pub type Handle = libc::HANDLE; + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawHandle = libc::HANDLE; /// Raw SOCKETs. - pub type Socket = libc::SOCKET; + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawSocket = libc::SOCKET; /// Extract raw handles. + #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRawHandle { /// Extract the raw handle, without taking any ownership. - fn as_raw_handle(&self) -> Handle; + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_handle(&self) -> RawHandle; + } + + /// Construct I/O objects from raw handles. + #[unstable(feature = "from_raw_os", + reason = "recent addition to the std::os::windows::io module")] + pub trait FromRawHandle { + /// Construct a new I/O object from the specified raw handle. + /// + /// This function will **consume ownership** of the handle given, + /// passing responsibility for closing the handle to the returned + /// object. + fn from_raw_handle(handle: RawHandle) -> Self; } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::fs::File { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for fs::File { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() } } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawHandle for fs::File { + fn from_raw_handle(handle: RawHandle) -> fs::File { + fs::File::from_inner(sys::fs2::File::from_inner(handle)) + } + } + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::pipe::PipeStream { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::net::pipe::UnixStream { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::net::pipe::UnixListener { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::net::pipe::UnixAcceptor { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } /// Extract raw sockets. + #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRawSocket { - fn as_raw_socket(&self) -> Socket; + /// Extract the underlying raw socket from this object. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_socket(&self) -> RawSocket; + } + + /// Create I/O objects from raw sockets. + #[unstable(feature = "from_raw_os", reason = "recent addition to module")] + pub trait FromRawSocket { + /// Creates a new I/O object from the given raw socket. + /// + /// This function will **consume ownership** of the socket provided and + /// it will be closed when the returned object goes out of scope. + fn from_raw_socket(sock: RawSocket) -> Self; } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::tcp::TcpStream { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::tcp::TcpListener { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().socket() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::tcp::TcpAcceptor { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().socket() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::udp::UdpSocket { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::TcpStream { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::TcpListener { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::UdpSocket { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } + } + + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::TcpStream { + fn from_raw_socket(sock: RawSocket) -> net::TcpStream { + let sock = sys::net::Socket::from_inner(sock); + net::TcpStream::from_inner(net2::TcpStream::from_inner(sock)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::TcpListener { + fn from_raw_socket(sock: RawSocket) -> net::TcpListener { + let sock = sys::net::Socket::from_inner(sock); + net::TcpListener::from_inner(net2::TcpListener::from_inner(sock)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::UdpSocket { + fn from_raw_socket(sock: RawSocket) -> net::UdpSocket { + let sock = sys::net::Socket::from_inner(sock); + net::UdpSocket::from_inner(net2::UdpSocket::from_inner(sock)) + } } } @@ -230,7 +306,7 @@ pub mod fs { #[stable(feature = "rust1", since = "1.0.0")] pub mod prelude { #[doc(no_inline)] - pub use super::io::{Socket, Handle, AsRawSocket, AsRawHandle}; + pub use super::io::{RawSocket, RawHandle, AsRawSocket, AsRawHandle}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs2.rs index 99835265111..d03e45649ed 100644 --- a/src/libstd/sys/windows/fs2.rs +++ b/src/libstd/sys/windows/fs2.rs @@ -20,11 +20,12 @@ use mem; use path::{Path, PathBuf}; use ptr; use sync::Arc; -use sys::handle::Handle as RawHandle; +use sys::handle::Handle; use sys::{c, cvt}; +use sys_common::FromInner; use vec::Vec; -pub struct File { handle: RawHandle } +pub struct File { handle: Handle } pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA } pub struct ReadDir { @@ -192,7 +193,7 @@ impl File { if handle == libc::INVALID_HANDLE_VALUE { Err(Error::last_os_error()) } else { - Ok(File { handle: RawHandle::new(handle) }) + Ok(File { handle: Handle::new(handle) }) } } @@ -260,7 +261,13 @@ impl File { Ok(newpos as u64) } - pub fn handle(&self) -> &RawHandle { &self.handle } + pub fn handle(&self) -> &Handle { &self.handle } +} + +impl FromInner for File { + fn from_inner(handle: libc::HANDLE) -> File { + File { handle: Handle::new(handle) } + } } pub fn to_utf16(s: &Path) -> Vec { diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index 734268c70ac..b07b3d8651e 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -19,7 +19,7 @@ use num::{SignedInt, Int}; use rt; use sync::{Once, ONCE_INIT}; use sys::c; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; pub type wrlen_t = i32; @@ -123,10 +123,14 @@ impl Socket { impl Drop for Socket { fn drop(&mut self) { - unsafe { cvt(libc::closesocket(self.0)).unwrap(); } + let _ = unsafe { libc::closesocket(self.0) }; } } impl AsInner for Socket { fn as_inner(&self) -> &libc::SOCKET { &self.0 } } + +impl FromInner for Socket { + fn from_inner(sock: libc::SOCKET) -> Socket { Socket(sock) } +} diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 167db1e8ac2..5cd90b0902b 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -31,7 +31,7 @@ use ptr; use slice; use sys::c; use sys::fs::FileDesc; -use sys::handle::Handle as RawHandle; +use sys::handle::Handle; use libc::funcs::extra::kernel32::{ GetEnvironmentStringsW, @@ -369,7 +369,7 @@ pub fn home_dir() -> Option { if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 { return None } - let _handle = RawHandle::new(token); + let _handle = Handle::new(token); super::fill_utf16_buf_new(|buf, mut sz| { match c::GetUserProfileDirectoryW(token, buf, &mut sz) { 0 if libc::GetLastError() != 0 => 0, From df65f59fe9dd856c96a383c01067a176fee0dbb6 Mon Sep 17 00:00:00 2001 From: Emeliov Dmitrii Date: Mon, 30 Mar 2015 19:22:46 +0300 Subject: [PATCH 03/46] replace deprecated as_slice() --- src/liballoc/arc.rs | 2 +- src/libcollections/slice.rs | 2 -- src/libcollections/str.rs | 6 +++--- src/libcollections/string.rs | 2 +- src/libcollections/vec.rs | 4 ++-- src/libcollections/vec_deque.rs | 3 ++- src/libcollectionstest/fmt.rs | 2 +- src/libcollectionstest/slice.rs | 2 +- src/libcollectionstest/str.rs | 4 ++-- src/libcore/iter.rs | 8 ++++---- src/libgraphviz/lib.rs | 2 +- src/librand/chacha.rs | 2 +- src/librand/lib.rs | 6 +++--- src/libserialize/json.rs | 2 +- src/libstd/fs/mod.rs | 4 ++-- src/libstd/io/cursor.rs | 8 ++++---- src/libstd/old_io/fs.rs | 2 +- src/libstd/old_io/mem.rs | 2 +- src/libstd/old_io/net/ip.rs | 2 +- src/libstd/old_io/process.rs | 4 ++-- src/libstd/os.rs | 2 +- src/libstd/process.rs | 8 ++++---- src/test/run-pass-fulldeps/compiler-calls.rs | 2 +- src/test/run-pass/regions-refcell.rs | 2 +- 24 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 9b37ddc7ab5..855c86f08e7 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -110,7 +110,7 @@ use heap::deallocate; /// let child_numbers = shared_numbers.clone(); /// /// thread::spawn(move || { -/// let local_numbers = child_numbers.as_slice(); +/// let local_numbers = &child_numbers[..]; /// /// // Work with the local numbers /// }); diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 14dcd52fe80..fb885d012c4 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -556,7 +556,6 @@ impl [T] { /// ```rust /// # #![feature(core)] /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// let s = s.as_slice(); /// /// let seek = 13; /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9)); @@ -923,7 +922,6 @@ impl [T] { /// ```rust /// # #![feature(core)] /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// let s = s.as_slice(); /// /// assert_eq!(s.binary_search(&13), Ok(9)); /// assert_eq!(s.binary_search(&4), Err(7)); diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 0665abc9e95..1e0a9adf760 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1473,12 +1473,12 @@ impl str { /// let gr1 = "a\u{310}e\u{301}o\u{308}\u{332}".graphemes(true).collect::>(); /// let b: &[_] = &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"]; /// - /// assert_eq!(gr1.as_slice(), b); + /// assert_eq!(&gr1[..], b); /// /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::>(); /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"]; /// - /// assert_eq!(gr2.as_slice(), b); + /// assert_eq!(&gr2[..], b); /// ``` #[unstable(feature = "unicode", reason = "this functionality may only be provided by libunicode")] @@ -1496,7 +1496,7 @@ impl str { /// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::>(); /// let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; /// - /// assert_eq!(gr_inds.as_slice(), b); + /// assert_eq!(&gr_inds[..], b); /// ``` #[unstable(feature = "unicode", reason = "this functionality may only be provided by libunicode")] diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 7131c1cd881..6115f87951b 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -93,7 +93,7 @@ impl String { /// ``` /// # #![feature(collections, core)] /// let s = String::from_str("hello"); - /// assert_eq!(s.as_slice(), "hello"); + /// assert_eq!(&s[..], "hello"); /// ``` #[inline] #[unstable(feature = "collections", diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 14bc7f65e09..ec04e77790d 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -821,13 +821,13 @@ impl Vec { /// # #![feature(collections, core)] /// let v = vec![0, 1, 2]; /// let w = v.map_in_place(|i| i + 3); - /// assert_eq!(w.as_slice(), [3, 4, 5].as_slice()); + /// assert_eq!(&w[..], &[3, 4, 5]); /// /// #[derive(PartialEq, Debug)] /// struct Newtype(u8); /// let bytes = vec![0x11, 0x22]; /// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x)); - /// assert_eq!(newtyped_bytes.as_slice(), [Newtype(0x11), Newtype(0x22)].as_slice()); + /// assert_eq!(&newtyped_bytes[..], &[Newtype(0x11), Newtype(0x22)]); /// ``` #[unstable(feature = "collections", reason = "API may change to provide stronger guarantees")] diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 8f3f4e6b890..3bdb85f3c4f 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -526,7 +526,8 @@ impl VecDeque { /// buf.push_back(3); /// buf.push_back(4); /// let b: &[_] = &[&5, &3, &4]; - /// assert_eq!(buf.iter().collect::>().as_slice(), b); + /// let c: Vec<&i32> = buf.iter().collect(); + /// assert_eq!(&c[..], b); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter { diff --git a/src/libcollectionstest/fmt.rs b/src/libcollectionstest/fmt.rs index 9a9aa71b58b..abd1262dbf1 100644 --- a/src/libcollectionstest/fmt.rs +++ b/src/libcollectionstest/fmt.rs @@ -13,5 +13,5 @@ use std::fmt; #[test] fn test_format() { let s = fmt::format(format_args!("Hello, {}!", "world")); - assert_eq!(s.as_slice(), "Hello, world!"); + assert_eq!(&s[..], "Hello, world!"); } diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index 4168fe88a4b..24cafa9f1c6 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -59,7 +59,7 @@ fn test_from_elem() { // Test on-heap from_elem. v = vec![20; 6]; { - let v = v.as_slice(); + let v = &v[..]; assert_eq!(v[0], 20); assert_eq!(v[1], 20); assert_eq!(v[2], 20); diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index 5cfa8009054..5b390befebe 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -1470,9 +1470,9 @@ fn test_split_strator() { fn test_str_default() { use std::default::Default; - fn t() { + fn t>() { let s: S = Default::default(); - assert_eq!(s.as_slice(), ""); + assert_eq!(s.as_ref(), ""); } t::<&str>(); diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 39bf97ae1ce..6496aee2ea3 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -624,7 +624,7 @@ pub trait Iterator { /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert!(it.any(|x| *x == 3)); - /// assert_eq!(it.as_slice(), [4, 5]); + /// assert_eq!(&it[..], [4, 5]); /// /// ``` #[inline] @@ -648,7 +648,7 @@ pub trait Iterator { /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3); - /// assert_eq!(it.as_slice(), [4, 5]); + /// assert_eq!(&it[..], [4, 5]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn find

(&mut self, mut predicate: P) -> Option where @@ -672,7 +672,7 @@ pub trait Iterator { /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert_eq!(it.position(|x| *x == 3).unwrap(), 2); - /// assert_eq!(it.as_slice(), [4, 5]); + /// assert_eq!(&it[..], [4, 5]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn position

(&mut self, mut predicate: P) -> Option where @@ -702,7 +702,7 @@ pub trait Iterator { /// let a = [1, 2, 2, 4, 5]; /// let mut it = a.iter(); /// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2); - /// assert_eq!(it.as_slice(), [1, 2]); + /// assert_eq!(&it[..], [1, 2]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn rposition

(&mut self, mut predicate: P) -> Option where diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index b3a3f266a5e..74be96235d2 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -84,7 +84,7 @@ //! //! fn edges(&'a self) -> dot::Edges<'a,Ed> { //! let &Edges(ref edges) = self; -//! edges.as_slice().into_cow() +//! (&edges[..]).into_cow() //! } //! //! fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s } diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 91abb548d2e..44187a4fc99 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -198,7 +198,7 @@ impl Rand for ChaChaRng { for word in &mut key { *word = other.gen(); } - SeedableRng::from_seed(key.as_slice()) + SeedableRng::from_seed(&key[..]) } } diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 97106908cde..7f7ab85e1db 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -153,7 +153,7 @@ pub trait Rng : Sized { /// /// let mut v = [0; 13579]; /// thread_rng().fill_bytes(&mut v); - /// println!("{:?}", v.as_slice()); + /// println!("{:?}", v); /// ``` fn fill_bytes(&mut self, dest: &mut [u8]) { // this could, in theory, be done by transmuting dest to a @@ -309,9 +309,9 @@ pub trait Rng : Sized { /// let mut rng = thread_rng(); /// let mut y = [1, 2, 3]; /// rng.shuffle(&mut y); - /// println!("{:?}", y.as_slice()); + /// println!("{:?}", y); /// rng.shuffle(&mut y); - /// println!("{:?}", y.as_slice()); + /// println!("{:?}", y); /// ``` fn shuffle(&mut self, values: &mut [T]) { let mut i = values.len(); diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index f6f059f7210..5cca41e3515 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -100,7 +100,7 @@ //! let encoded = json::encode(&object).unwrap(); //! //! // Deserialize using `json::decode` -//! let decoded: TestStruct = json::decode(encoded.as_slice()).unwrap(); +//! let decoded: TestStruct = json::decode(&encoded[..]).unwrap(); //! } //! ``` //! diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs index a3128ef0f8d..98c63d01e1a 100644 --- a/src/libstd/fs/mod.rs +++ b/src/libstd/fs/mod.rs @@ -1327,7 +1327,7 @@ mod tests { check!(fs::copy(&input, &out)); let mut v = Vec::new(); check!(check!(File::open(&out)).read_to_end(&mut v)); - assert_eq!(v.as_slice(), b"hello"); + assert_eq!(&v[..], b"hello"); assert_eq!(check!(input.metadata()).permissions(), check!(out.metadata()).permissions()); @@ -1622,7 +1622,7 @@ mod tests { check!(check!(File::create(&tmpdir.join("test"))).write(&bytes)); let mut v = Vec::new(); check!(check!(File::open(&tmpdir.join("test"))).read_to_end(&mut v)); - assert!(v == bytes.as_slice()); + assert!(v == &bytes[..]); } #[test] diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 79f0af670b4..10fe08fb688 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -282,19 +282,19 @@ mod tests { #[test] fn test_slice_reader() { let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; - let mut reader = &mut in_buf.as_slice(); + let mut reader = &mut &in_buf[..]; let mut buf = []; assert_eq!(reader.read(&mut buf), Ok(0)); let mut buf = [0]; assert_eq!(reader.read(&mut buf), Ok(1)); assert_eq!(reader.len(), 7); let b: &[_] = &[0]; - assert_eq!(buf.as_slice(), b); + assert_eq!(buf, b); let mut buf = [0; 4]; assert_eq!(reader.read(&mut buf), Ok(4)); assert_eq!(reader.len(), 3); let b: &[_] = &[1, 2, 3, 4]; - assert_eq!(buf.as_slice(), b); + assert_eq!(buf, b); assert_eq!(reader.read(&mut buf), Ok(3)); let b: &[_] = &[5, 6, 7]; assert_eq!(&buf[..3], b); @@ -304,7 +304,7 @@ mod tests { #[test] fn test_buf_reader() { let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; - let mut reader = Cursor::new(in_buf.as_slice()); + let mut reader = Cursor::new(&in_buf[..]); let mut buf = []; assert_eq!(reader.read(&mut buf), Ok(0)); assert_eq!(reader.position(), 0); diff --git a/src/libstd/old_io/fs.rs b/src/libstd/old_io/fs.rs index 6aa63c395c6..c5fd10a9e85 100644 --- a/src/libstd/old_io/fs.rs +++ b/src/libstd/old_io/fs.rs @@ -1639,7 +1639,7 @@ mod test { check!(File::create(&tmpdir.join("test")).write(&bytes)); let actual = check!(File::open(&tmpdir.join("test")).read_to_end()); - assert!(actual == bytes.as_slice()); + assert!(actual == &bytes[..]); } #[test] diff --git a/src/libstd/old_io/mem.rs b/src/libstd/old_io/mem.rs index 5f20c383bb7..b03664ec0d0 100644 --- a/src/libstd/old_io/mem.rs +++ b/src/libstd/old_io/mem.rs @@ -744,7 +744,7 @@ mod test { wr.write(&[5; 10]).unwrap(); } } - assert_eq!(buf.as_slice(), [5; 100].as_slice()); + assert_eq!(buf.as_ref(), [5; 100].as_ref()); }); } diff --git a/src/libstd/old_io/net/ip.rs b/src/libstd/old_io/net/ip.rs index 26e1bb6550b..d405bde19cb 100644 --- a/src/libstd/old_io/net/ip.rs +++ b/src/libstd/old_io/net/ip.rs @@ -435,7 +435,7 @@ pub struct ParseError; /// let tcp_l = TcpListener::bind("localhost:12345"); /// /// let mut udp_s = UdpSocket::bind(("127.0.0.1", 23451)).unwrap(); -/// udp_s.send_to([7, 7, 7].as_slice(), (Ipv4Addr(127, 0, 0, 1), 23451)); +/// udp_s.send_to([7, 7, 7].as_ref(), (Ipv4Addr(127, 0, 0, 1), 23451)); /// } /// ``` pub trait ToSocketAddr { diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index 06940bf6860..a2129fcde58 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -376,8 +376,8 @@ impl Command { /// }; /// /// println!("status: {}", output.status); - /// println!("stdout: {}", String::from_utf8_lossy(output.output.as_slice())); - /// println!("stderr: {}", String::from_utf8_lossy(output.error.as_slice())); + /// println!("stdout: {}", String::from_utf8_lossy(output.output.as_ref())); + /// println!("stderr: {}", String::from_utf8_lossy(output.error.as_ref())); /// ``` pub fn output(&self) -> IoResult { self.spawn().and_then(|p| p.wait_with_output()) diff --git a/src/libstd/os.rs b/src/libstd/os.rs index e19c734b8a3..2e3f47fea86 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -311,7 +311,7 @@ pub fn split_paths(unparsed: T) -> Vec { /// let key = "PATH"; /// let mut paths = os::getenv_as_bytes(key).map_or(Vec::new(), os::split_paths); /// paths.push(Path::new("/home/xyz/bin")); -/// os::setenv(key, os::join_paths(paths.as_slice()).unwrap()); +/// os::setenv(key, os::join_paths(&paths[..]).unwrap()); /// ``` #[unstable(feature = "os")] pub fn join_paths(paths: &[T]) -> Result, &'static str> { diff --git a/src/libstd/process.rs b/src/libstd/process.rs index b4bd513e8f0..7033ab5f09f 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -678,7 +678,7 @@ mod tests { fn test_process_output_output() { let Output {status, stdout, stderr} = Command::new("echo").arg("hello").output().unwrap(); - let output_str = str::from_utf8(stdout.as_slice()).unwrap(); + let output_str = str::from_utf8(&stdout[..]).unwrap(); assert!(status.success()); assert_eq!(output_str.trim().to_string(), "hello"); @@ -720,7 +720,7 @@ mod tests { let prog = Command::new("echo").arg("hello").stdout(Stdio::piped()) .spawn().unwrap(); let Output {status, stdout, stderr} = prog.wait_with_output().unwrap(); - let output_str = str::from_utf8(stdout.as_slice()).unwrap(); + let output_str = str::from_utf8(&stdout[..]).unwrap(); assert!(status.success()); assert_eq!(output_str.trim().to_string(), "hello"); @@ -855,7 +855,7 @@ mod tests { cmd.env("PATH", &p); } let result = cmd.output().unwrap(); - let output = String::from_utf8_lossy(result.stdout.as_slice()).to_string(); + let output = String::from_utf8_lossy(&result.stdout[..]).to_string(); assert!(output.contains("RUN_TEST_NEW_ENV=123"), "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); @@ -864,7 +864,7 @@ mod tests { #[test] fn test_add_to_env() { let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap(); - let output = String::from_utf8_lossy(result.stdout.as_slice()).to_string(); + let output = String::from_utf8_lossy(&result.stdout[..]).to_string(); assert!(output.contains("RUN_TEST_NEW_ENV=123"), "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs index 7a3c32a45f9..fdc670c6b71 100644 --- a/src/test/run-pass-fulldeps/compiler-calls.rs +++ b/src/test/run-pass-fulldeps/compiler-calls.rs @@ -77,6 +77,6 @@ fn main() { let mut tc = TestCalls { count: 1 }; // we should never get use this filename, but lets make sure they are valid args. let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; - rustc_driver::run_compiler(args.as_slice(), &mut tc); + rustc_driver::run_compiler(&args[..], &mut tc); assert!(tc.count == 30); } diff --git a/src/test/run-pass/regions-refcell.rs b/src/test/run-pass/regions-refcell.rs index febf5f92ef6..63525b36206 100644 --- a/src/test/run-pass/regions-refcell.rs +++ b/src/test/run-pass/regions-refcell.rs @@ -29,7 +29,7 @@ fn foo<'a>(map: RefCell>) { // supposed to match the lifetime `'a`) ... fn foo<'a>(map: RefCell>) { let one = [1]; - assert_eq!(map.borrow().get("one"), Some(&one.as_slice())); + assert_eq!(map.borrow().get("one"), Some(&&one[..])); } #[cfg(all(not(cannot_use_this_yet),not(cannot_use_this_yet_either)))] From 2a89d695f4edb6fe8c7629f48908d3d3d9076426 Mon Sep 17 00:00:00 2001 From: Kevin Butler Date: Mon, 30 Mar 2015 23:47:01 +0100 Subject: [PATCH 04/46] libcore: Ensure min and max functions are consistent for equal inputs --- src/libcore/cmp.rs | 14 ++-- src/libcore/iter.rs | 58 ++++++++----- .../run-pass/minmax-stability-issue-23687.rs | 83 +++++++++++++++++++ 3 files changed, 127 insertions(+), 28 deletions(-) create mode 100644 src/test/run-pass/minmax-stability-issue-23687.rs diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 9ab8ab8672d..6954438e93a 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -362,6 +362,8 @@ pub trait PartialOrd: PartialEq { /// Compare and return the minimum of two values. /// +/// Returns the first argument if the comparison determines them to be equal. +/// /// # Examples /// /// ``` @@ -373,11 +375,13 @@ pub trait PartialOrd: PartialEq { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn min(v1: T, v2: T) -> T { - if v1 < v2 { v1 } else { v2 } + if v1 <= v2 { v1 } else { v2 } } /// Compare and return the maximum of two values. /// +/// Returns the second argument if the comparison determines them to be equal. +/// /// # Examples /// /// ``` @@ -389,7 +393,7 @@ pub fn min(v1: T, v2: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn max(v1: T, v2: T) -> T { - if v1 > v2 { v1 } else { v2 } + if v2 >= v1 { v2 } else { v1 } } /// Compare and return the minimum of two values if there is one. @@ -427,7 +431,7 @@ pub fn partial_min(v1: T, v2: T) -> Option { /// Compare and return the maximum of two values if there is one. /// -/// Returns the first argument if the comparison determines them to be equal. +/// Returns the second argument if the comparison determines them to be equal. /// /// # Examples /// @@ -452,8 +456,8 @@ pub fn partial_min(v1: T, v2: T) -> Option { #[unstable(feature = "core")] pub fn partial_max(v1: T, v2: T) -> Option { match v1.partial_cmp(&v2) { - Some(Less) => Some(v2), - Some(Equal) | Some(Greater) => Some(v1), + Some(Equal) | Some(Less) => Some(v2), + Some(Greater) => Some(v1), None => None } } diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 39bf97ae1ce..ca83a128c99 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -722,6 +722,9 @@ pub trait Iterator { /// Consumes the entire iterator to return the maximum element. /// + /// Returns the rightmost element if the comparison determines two elements + /// to be equally maximum. + /// /// # Examples /// /// ``` @@ -732,16 +735,19 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn max(self) -> Option where Self: Sized, Self::Item: Ord { - self.fold(None, |max, x| { + self.fold(None, |max, y| { match max { - None => Some(x), - Some(y) => Some(cmp::max(x, y)) + None => Some(y), + Some(x) => Some(cmp::max(x, y)) } }) } /// Consumes the entire iterator to return the minimum element. /// + /// Returns the leftmost element if the comparison determines two elements + /// to be equally minimum. + /// /// # Examples /// /// ``` @@ -752,10 +758,10 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn min(self) -> Option where Self: Sized, Self::Item: Ord { - self.fold(None, |min, x| { + self.fold(None, |min, y| { match min { - None => Some(x), - Some(y) => Some(cmp::min(x, y)) + None => Some(y), + Some(x) => Some(cmp::min(x, y)) } }) } @@ -799,7 +805,7 @@ pub trait Iterator { Some(x) => { match self.next() { None => return OneElement(x), - Some(y) => if x < y {(x, y)} else {(y,x)} + Some(y) => if x <= y {(x, y)} else {(y, x)} } } }; @@ -817,19 +823,19 @@ pub trait Iterator { None => { if first < min { min = first; - } else if first > max { + } else if first >= max { max = first; } break; } Some(x) => x }; - if first < second { - if first < min {min = first;} - if max < second {max = second;} + if first <= second { + if first < min { min = first } + if second >= max { max = second } } else { - if second < min {min = second;} - if max < first {max = first;} + if second < min { min = second } + if first >= max { max = first } } } @@ -839,6 +845,9 @@ pub trait Iterator { /// Return the element that gives the maximum value from the /// specified function. /// + /// Returns the rightmost element if the comparison determines two elements + /// to be equally maximum. + /// /// # Examples /// /// ``` @@ -855,14 +864,14 @@ pub trait Iterator { Self: Sized, F: FnMut(&Self::Item) -> B, { - self.fold(None, |max: Option<(Self::Item, B)>, x| { - let x_val = f(&x); + self.fold(None, |max: Option<(Self::Item, B)>, y| { + let y_val = f(&y); match max { - None => Some((x, x_val)), - Some((y, y_val)) => if x_val > y_val { - Some((x, x_val)) - } else { + None => Some((y, y_val)), + Some((x, x_val)) => if y_val >= x_val { Some((y, y_val)) + } else { + Some((x, x_val)) } } }).map(|(x, _)| x) @@ -871,6 +880,9 @@ pub trait Iterator { /// Return the element that gives the minimum value from the /// specified function. /// + /// Returns the leftmost element if the comparison determines two elements + /// to be equally minimum. + /// /// # Examples /// /// ``` @@ -887,11 +899,11 @@ pub trait Iterator { Self: Sized, F: FnMut(&Self::Item) -> B, { - self.fold(None, |min: Option<(Self::Item, B)>, x| { - let x_val = f(&x); + self.fold(None, |min: Option<(Self::Item, B)>, y| { + let y_val = f(&y); match min { - None => Some((x, x_val)), - Some((y, y_val)) => if x_val < y_val { + None => Some((y, y_val)), + Some((x, x_val)) => if x_val <= y_val { Some((x, x_val)) } else { Some((y, y_val)) diff --git a/src/test/run-pass/minmax-stability-issue-23687.rs b/src/test/run-pass/minmax-stability-issue-23687.rs new file mode 100644 index 00000000000..86dd1a04532 --- /dev/null +++ b/src/test/run-pass/minmax-stability-issue-23687.rs @@ -0,0 +1,83 @@ +// 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(core)] +use std::fmt::Debug; +use std::cmp::{self, PartialOrd, Ordering}; +use std::iter::MinMaxResult::MinMax; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct Foo { + n: u8, + name: &'static str +} + +impl PartialOrd for Foo { + fn partial_cmp(&self, other: &Foo) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Foo { + fn cmp(&self, other: &Foo) -> Ordering { + self.n.cmp(&other.n) + } +} + +fn main() { + let a = Foo { n: 4, name: "a" }; + let b = Foo { n: 4, name: "b" }; + let c = Foo { n: 8, name: "c" }; + let d = Foo { n: 8, name: "d" }; + let e = Foo { n: 22, name: "e" }; + let f = Foo { n: 22, name: "f" }; + + let data = [a, b, c, d, e, f]; + + // `min` should return the left when the values are equal + assert_eq!(data.iter().min(), Some(&a)); + assert_eq!(data.iter().min_by(|a| a.n), Some(&a)); + assert_eq!(cmp::min(a, b), a); + assert_eq!(cmp::min(b, a), b); + assert_eq!(cmp::partial_min(a, b), Some(a)); + assert_eq!(cmp::partial_min(b, a), Some(b)); + + // `max` should return the right when the values are equal + assert_eq!(data.iter().max(), Some(&f)); + assert_eq!(data.iter().max_by(|a| a.n), Some(&f)); + assert_eq!(cmp::max(e, f), f); + assert_eq!(cmp::max(f, e), e); + assert_eq!(cmp::partial_max(e, f), Some(f)); + assert_eq!(cmp::partial_max(f, e), Some(e)); + + // Similar for `min_max` + assert_eq!(data.iter().min_max(), MinMax(&a, &f)); + assert_eq!(data[1..5].iter().min_max(), MinMax(&b, &e)); + assert_eq!(data[2..4].iter().min_max(), MinMax(&c, &d)); + + let mut presorted = data.to_vec(); + presorted.sort(); + assert_stable(&presorted); + + let mut presorted = data.to_vec(); + presorted.sort_by(|a, b| a.cmp(b)); + assert_stable(&presorted); + + // Assert that sorted and min/max are the same + fn assert_stable(presorted: &[T]) { + for slice in presorted.windows(2) { + let a = &slice[0]; + let b = &slice[1]; + + assert_eq!(a, cmp::min(a, b)); + assert_eq!(b, cmp::max(a, b)); + } + } +} From f19e763e0824a73118ed715f526cb7bdd584d4c4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 30 Mar 2015 16:43:04 -0700 Subject: [PATCH 05/46] std: Stabilize the rest of Any/BoxAny This commit stabilizes the following APIs: * `TypeId::of` - now that it has an `Any` bound it's ready to be stable. * `Box::downcast` - now that an inherent impl on `Box` as well as `Box` is allowed the `BoxAny` trait is removed in favor of these inherent methods. This is a breaking change due to the removal of the `BoxAny` trait, but consumers can simply remove imports to fix crates. [breaking-change] --- src/liballoc/boxed.rs | 26 +++++-------------- src/liballoc/boxed_test.rs | 1 - src/libcore/any.rs | 3 +-- src/libstd/thread/mod.rs | 1 - .../run-pass/unit-like-struct-drop-run.rs | 1 - 5 files changed, 7 insertions(+), 25 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index f9bd0ab2f1e..48dce3d8815 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -233,24 +233,10 @@ impl Hash for Box { } } -/// Extension methods for an owning `Any` trait object. -#[unstable(feature = "alloc", - reason = "this trait will likely disappear once compiler bugs blocking \ - a direct impl on `Box` have been fixed ")] -// FIXME(#18737): this should be a direct impl on `Box`. If you're -// removing this please make sure that you can downcase on -// `Box` as well as `Box` -pub trait BoxAny { - /// Returns the boxed value if it is of type `T`, or - /// `Err(Self)` if it isn't. - #[stable(feature = "rust1", since = "1.0.0")] - fn downcast(self) -> Result, Box>; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl BoxAny for Box { +impl Box { #[inline] - fn downcast(self) -> Result, Box> { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn downcast(self) -> Result, Box> { if self.is::() { unsafe { // Get the raw representation of the trait object @@ -267,10 +253,10 @@ impl BoxAny for Box { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl BoxAny for Box { +impl Box { #[inline] - fn downcast(self) -> Result, Box> { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn downcast(self) -> Result, Box> { >::downcast(self) } } diff --git a/src/liballoc/boxed_test.rs b/src/liballoc/boxed_test.rs index bb1ff9428a7..682d5f407c4 100644 --- a/src/liballoc/boxed_test.rs +++ b/src/liballoc/boxed_test.rs @@ -17,7 +17,6 @@ use core::clone::Clone; use std::boxed; use std::boxed::Box; -use std::boxed::BoxAny; #[test] fn test_owned_clone() { diff --git a/src/libcore/any.rs b/src/libcore/any.rs index d3bc07b173a..0ffc4a229b5 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -202,8 +202,7 @@ pub struct TypeId { impl TypeId { /// Returns the `TypeId` of the type this generic function has been /// instantiated with - #[unstable(feature = "core", - reason = "may grow a `Reflect` bound soon via marker traits")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn of() -> TypeId { TypeId { t: unsafe { intrinsics::type_id::() }, diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 074030bd07b..863291ff542 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -810,7 +810,6 @@ mod test { use any::Any; use sync::mpsc::{channel, Sender}; - use boxed::BoxAny; use result; use std::old_io::{ChanReader, ChanWriter}; use super::{Builder}; diff --git a/src/test/run-pass/unit-like-struct-drop-run.rs b/src/test/run-pass/unit-like-struct-drop-run.rs index 9e1ced36402..c2db63ed251 100644 --- a/src/test/run-pass/unit-like-struct-drop-run.rs +++ b/src/test/run-pass/unit-like-struct-drop-run.rs @@ -14,7 +14,6 @@ #![feature(alloc)] -use std::boxed::BoxAny; use std::thread; struct Foo; From e17f4fc1d4545f5c17b21805c5145b05495484ee Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Mon, 30 Mar 2015 17:56:48 -0700 Subject: [PATCH 06/46] convert: remove FromError, use From instead This removes the FromError trait, since it can now be expressed using the new convert::Into trait. All implementations of FromError where changed to From, and `try!` was changed to use From::from instead. Because this removes FromError, it is a breaking change, but fixing it simply requires changing the words `FromError` to `From`, and `from_error` to `from`. [breaking-change] --- src/liballoc/boxed.rs | 6 +++--- src/libcore/convert.rs | 7 +++++++ src/libcore/error.rs | 35 ++++------------------------------- src/libcore/macros.rs | 2 +- src/libserialize/json.rs | 4 ++-- src/libstd/ffi/c_str.rs | 10 +++++----- src/libstd/io/buffered.rs | 6 +++--- src/libstd/macros.rs | 2 +- src/libstd/os.rs | 2 +- src/libstd/sync/poison.rs | 6 +++--- 10 files changed, 30 insertions(+), 50 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index f9bd0ab2f1e..94a497dfe85 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -51,7 +51,7 @@ use core::prelude::*; use core::any::Any; use core::cmp::Ordering; use core::default::Default; -use core::error::{Error, FromError}; +use core::error::Error; use core::fmt; use core::hash::{self, Hash}; use core::mem; @@ -322,8 +322,8 @@ impl DoubleEndedIterator for Box { impl ExactSizeIterator for Box {} #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> FromError for Box { - fn from_error(err: E) -> Box { +impl<'a, E: Error + 'a> From for Box { + fn from(err: E) -> Box { Box::new(err) } } diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 21f9b1f5513..3680daa2d5e 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -99,6 +99,13 @@ impl<'a, T: ?Sized, U: ?Sized> AsMut for &'a mut T where T: AsMut { // } // } +// From itself is always itself +impl From for T { + fn from(t: T) -> T { + t + } +} + // From implies Into impl Into for T where U: From { fn into(self) -> U { diff --git a/src/libcore/error.rs b/src/libcore/error.rs index 51f3369a75b..73ec19f1a14 100644 --- a/src/libcore/error.rs +++ b/src/libcore/error.rs @@ -34,17 +34,6 @@ //! particular implementation, but also reveal some of its implementation for //! debugging via `cause` chains. //! -//! # The `FromError` trait -//! -//! `FromError` is a simple trait that expresses conversions between different -//! error types. To provide maximum flexibility, it does not require either of -//! the types to actually implement the `Error` trait, although this will be the -//! common case. -//! -//! The main use of this trait is in the `try!` macro, which uses it to -//! automatically convert a given error to the error specified in a function's -//! return type. -//! //! For example, //! //! ``` @@ -59,14 +48,14 @@ //! Map(MapError) //! } //! -//! impl FromError for MyError { -//! fn from_error(err: IoError) -> MyError { +//! impl From for MyError { +//! fn from(err: IoError) -> MyError { //! MyError::Io(err) //! } //! } //! -//! impl FromError for MyError { -//! fn from_error(err: MapError) -> MyError { +//! impl From for MyError { +//! fn from(err: MapError) -> MyError { //! MyError::Map(err) //! } //! } @@ -100,19 +89,3 @@ pub trait Error: Debug + Display { #[stable(feature = "rust1", since = "1.0.0")] fn cause(&self) -> Option<&Error> { None } } - -/// A trait for types that can be converted from a given error type `E`. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait FromError { - /// Perform the conversion. - #[stable(feature = "rust1", since = "1.0.0")] - fn from_error(err: E) -> Self; -} - -// Any type is convertable from itself -#[stable(feature = "rust1", since = "1.0.0")] -impl FromError for E { - fn from_error(err: E) -> E { - err - } -} diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index d5a7c1d6b26..19626aa5056 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -156,7 +156,7 @@ macro_rules! debug_assert_eq { /// Short circuiting evaluation on Err /// -/// `libstd` contains a more general `try!` macro that uses `FromError`. +/// `libstd` contains a more general `try!` macro that uses `From`. #[macro_export] macro_rules! try { ($e:expr) => ({ diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index f6f059f7210..cd7f66f50c8 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -365,8 +365,8 @@ impl std::error::Error for EncoderError { fn description(&self) -> &str { "encoder error" } } -impl std::error::FromError for EncoderError { - fn from_error(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) } +impl From for EncoderError { + fn from(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) } } pub type EncodeResult = Result<(), EncoderError>; diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index a00f7708025..f5c7d1d18d5 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -12,7 +12,7 @@ use convert::Into; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; -use error::{Error, FromError}; +use error::Error; use fmt; use io; use iter::Iterator; @@ -298,8 +298,8 @@ impl fmt::Display for NulError { } #[stable(feature = "rust1", since = "1.0.0")] -impl FromError for io::Error { - fn from_error(_: NulError) -> io::Error { +impl From for io::Error { + fn from(_: NulError) -> io::Error { io::Error::new(io::ErrorKind::InvalidInput, "data provided contains a nul byte", None) } @@ -307,8 +307,8 @@ impl FromError for io::Error { #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] -impl FromError for old_io::IoError { - fn from_error(_: NulError) -> old_io::IoError { +impl From for old_io::IoError { + fn from(_: NulError) -> old_io::IoError { old_io::IoError { kind: old_io::IoErrorKind::InvalidInput, desc: "data provided contains a nul byte", diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 98581fc43f8..f03ed7a3dde 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use io::prelude::*; use cmp; -use error::{self, FromError}; +use error; use fmt; use io::{self, DEFAULT_BUF_SIZE, Error, ErrorKind}; use ptr; @@ -264,8 +264,8 @@ impl IntoInnerError { } #[stable(feature = "rust1", since = "1.0.0")] -impl FromError> for Error { - fn from_error(iie: IntoInnerError) -> Error { iie.1 } +impl From> for Error { + fn from(iie: IntoInnerError) -> Error { iie.1 } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 52492a019a2..88106811093 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -97,7 +97,7 @@ macro_rules! try { ($expr:expr) => (match $expr { $crate::result::Result::Ok(val) => val, $crate::result::Result::Err(err) => { - return $crate::result::Result::Err($crate::error::FromError::from_error(err)) + return $crate::result::Result::Err($crate::convert::From::from(err)) } }) } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index e19c734b8a3..9aebdbe9eec 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -40,7 +40,7 @@ use boxed::Box; use clone::Clone; use convert::From; use env; -use error::{FromError, Error}; +use error::Error; use ffi::{OsString, OsStr}; use fmt; use iter::Iterator; diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs index c07c83d37f4..cea2def30f1 100644 --- a/src/libstd/sync/poison.rs +++ b/src/libstd/sync/poison.rs @@ -11,7 +11,7 @@ use prelude::v1::*; use cell::UnsafeCell; -use error::{Error, FromError}; +use error::{Error}; use fmt; use thread; @@ -144,8 +144,8 @@ impl PoisonError { pub fn get_mut(&mut self) -> &mut T { &mut self.guard } } -impl FromError> for TryLockError { - fn from_error(err: PoisonError) -> TryLockError { +impl From> for TryLockError { + fn from(err: PoisonError) -> TryLockError { TryLockError::Poisoned(err) } } From 606f50c46dd9a3852d36456d2015e1ccf832642e Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 31 Mar 2015 00:27:13 +1100 Subject: [PATCH 07/46] Lex binary and octal literals more eagerly. Previously 0b12 was considered two tokens, 0b1 and 2, as 2 isn't a valid base 2 digit. This patch changes that to collapse them into one (and makes `0b12` etc. an error: 2 isn't a valid base 2 digit). This may break some macro invocations of macros with `tt` (or syntax extensions) that rely on adjacent digits being separate tokens and hence is a [breaking-change] The fix is to separate the tokens, e.g. `0b12` -> `0b1 2`. cc https://github.com/rust-lang/rfcs/pull/879 --- src/libsyntax/parse/lexer/mod.rs | 38 ++++++++++++------- src/libsyntax/parse/mod.rs | 15 +++++++- src/test/parse-fail/issue-1802-1.rs | 2 +- src/test/parse-fail/lex-bad-binary-literal.rs | 21 ++++++++++ src/test/parse-fail/lex-bad-octal-literal.rs | 14 +++++++ 5 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 src/test/parse-fail/lex-bad-binary-literal.rs create mode 100644 src/test/parse-fail/lex-bad-octal-literal.rs diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 532b632fac8..ae5c99123a5 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -621,7 +621,7 @@ impl<'a> StringReader<'a> { let base = 10; // find the integer representing the name - self.scan_digits(base); + self.scan_digits(base, base); let encoded_name : u32 = self.with_str_from(start_bpos, |s| { num::from_str_radix(s, 10).unwrap_or_else(|_| { panic!("expected digits representing a name, got {:?}, {}, range [{:?},{:?}]", @@ -639,7 +639,7 @@ impl<'a> StringReader<'a> { // find the integer representing the ctxt let start_bpos = self.last_pos; - self.scan_digits(base); + self.scan_digits(base, base); let encoded_ctxt : ast::SyntaxContext = self.with_str_from(start_bpos, |s| { num::from_str_radix(s, 10).unwrap_or_else(|_| { panic!("expected digits representing a ctxt, got {:?}, {}", s, whence); @@ -653,16 +653,28 @@ impl<'a> StringReader<'a> { ctxt: encoded_ctxt, } } - /// Scan through any digits (base `radix`) or underscores, and return how - /// many digits there were. - fn scan_digits(&mut self, radix: u32) -> usize { + /// Scan through any digits (base `scan_radix`) or underscores, + /// and return how many digits there were. + /// + /// `real_radix` represents the true radix of the number we're + /// interested in, and errors will be emitted for any digits + /// between `real_radix` and `scan_radix`. + fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize { + assert!(real_radix <= scan_radix); let mut len = 0; loop { let c = self.curr; if c == Some('_') { debug!("skipping a _"); self.bump(); continue; } - match c.and_then(|cc| cc.to_digit(radix)) { + match c.and_then(|cc| cc.to_digit(scan_radix)) { Some(_) => { debug!("{:?} in scan_digits", c); + // check that the hypothetical digit is actually + // in range for the true radix + if c.unwrap().to_digit(real_radix).is_none() { + self.err_span_(self.last_pos, self.pos, + &format!("invalid digit for a base {} literal", + real_radix)); + } len += 1; self.bump(); } @@ -681,11 +693,11 @@ impl<'a> StringReader<'a> { if c == '0' { match self.curr.unwrap_or('\0') { - 'b' => { self.bump(); base = 2; num_digits = self.scan_digits(2); } - 'o' => { self.bump(); base = 8; num_digits = self.scan_digits(8); } - 'x' => { self.bump(); base = 16; num_digits = self.scan_digits(16); } + 'b' => { self.bump(); base = 2; num_digits = self.scan_digits(2, 10); } + 'o' => { self.bump(); base = 8; num_digits = self.scan_digits(8, 10); } + 'x' => { self.bump(); base = 16; num_digits = self.scan_digits(16, 16); } '0'...'9' | '_' | '.' => { - num_digits = self.scan_digits(10) + 1; + num_digits = self.scan_digits(10, 10) + 1; } _ => { // just a 0 @@ -693,7 +705,7 @@ impl<'a> StringReader<'a> { } } } else if c.is_digit(10) { - num_digits = self.scan_digits(10) + 1; + num_digits = self.scan_digits(10, 10) + 1; } else { num_digits = 0; } @@ -712,7 +724,7 @@ impl<'a> StringReader<'a> { // with a number self.bump(); if self.curr.unwrap_or('\0').is_digit(10) { - self.scan_digits(10); + self.scan_digits(10, 10); self.scan_float_exponent(); } let last_pos = self.last_pos; @@ -935,7 +947,7 @@ impl<'a> StringReader<'a> { if self.curr_is('-') || self.curr_is('+') { self.bump(); } - if self.scan_digits(10) == 0 { + if self.scan_digits(10, 10) == 0 { self.err_span_(self.last_pos, self.pos, "expected at least one digit in exponent") } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index bea42a88bf5..f8820999c9d 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -735,7 +735,20 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> let res: u64 = match ::std::num::from_str_radix(s, base).ok() { Some(r) => r, - None => { sd.span_err(sp, "int literal is too large"); 0 } + None => { + // small bases are lexed as if they were base 10, e.g, the string + // might be `0b10201`. This will cause the conversion above to fail, + // but these cases have errors in the lexer: we don't want to emit + // two errors, and we especially don't want to emit this error since + // it isn't necessarily true. + let already_errored = base < 10 && + s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base)); + + if !already_errored { + sd.span_err(sp, "int literal is too large"); + } + 0 + } }; // adjust the sign diff --git a/src/test/parse-fail/issue-1802-1.rs b/src/test/parse-fail/issue-1802-1.rs index 8ce99f517c4..00fb2808faa 100644 --- a/src/test/parse-fail/issue-1802-1.rs +++ b/src/test/parse-fail/issue-1802-1.rs @@ -10,5 +10,5 @@ // error-pattern:no valid digits found for number fn main() { - log(error, 0b42); + log(error, 0b); } diff --git a/src/test/parse-fail/lex-bad-binary-literal.rs b/src/test/parse-fail/lex-bad-binary-literal.rs new file mode 100644 index 00000000000..e92000c54ba --- /dev/null +++ b/src/test/parse-fail/lex-bad-binary-literal.rs @@ -0,0 +1,21 @@ +// Copyright 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. + +fn main() { + 0b121; //~ ERROR invalid digit for a base 2 literal + 0b10_10301; //~ ERROR invalid digit for a base 2 literal + 0b30; //~ ERROR invalid digit for a base 2 literal + 0b41; //~ ERROR invalid digit for a base 2 literal + 0b5; //~ ERROR invalid digit for a base 2 literal + 0b6; //~ ERROR invalid digit for a base 2 literal + 0b7; //~ ERROR invalid digit for a base 2 literal + 0b8; //~ ERROR invalid digit for a base 2 literal + 0b9; //~ ERROR invalid digit for a base 2 literal +} diff --git a/src/test/parse-fail/lex-bad-octal-literal.rs b/src/test/parse-fail/lex-bad-octal-literal.rs new file mode 100644 index 00000000000..bf9880cb6cf --- /dev/null +++ b/src/test/parse-fail/lex-bad-octal-literal.rs @@ -0,0 +1,14 @@ +// Copyright 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. + +fn main() { + 0o18; //~ ERROR invalid digit for a base 8 literal + 0o1234_9_5670; //~ ERROR invalid digit for a base 8 literal +} From a78d3832ed955697a2f69da2ba22cee7f32047cc Mon Sep 17 00:00:00 2001 From: Camille Roussel Date: Mon, 30 Mar 2015 18:52:08 -0700 Subject: [PATCH 08/46] Update lib.rs Removed duplicate words --- src/libstd/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index b7cb8f9ed50..a17be591811 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -44,7 +44,7 @@ //! lives in the [`vec`](vec/index.html) module. Contiguous, unsized regions //! of memory, `[T]`, commonly called "slices", and their borrowed versions, //! `&[T]`, commonly called "borrowed slices", are built-in types for which the -//! for which the [`slice`](slice/index.html) module defines many methods. +//! [`slice`](slice/index.html) module defines many methods. //! //! `&str`, a UTF-8 string, is a built-in type, and the standard library //! defines methods for it on a variety of traits in the From edc096d820c549319aaa9662412beb2deec39441 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 24 Mar 2015 16:48:57 -0400 Subject: [PATCH 09/46] Document std::borrow with examples --- src/libcollections/borrow.rs | 56 ++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 88d59f699d1..63f5c838baf 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -40,6 +40,24 @@ use self::Cow::*; #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { /// Immutably borrow from an owned value. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::Borrow; + /// + /// fn check>(s: T) { + /// assert_eq!("Hello", s.borrow()); + /// } + /// + /// let s = "Hello".to_string(); + /// + /// check(s); + /// + /// let s = "Hello"; + /// + /// check(s); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn borrow(&self) -> &Borrowed; } @@ -50,6 +68,20 @@ pub trait Borrow { #[stable(feature = "rust1", since = "1.0.0")] pub trait BorrowMut : Borrow { /// Mutably borrow from an owned value. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::BorrowMut; + /// + /// fn check>(mut v: T) { + /// assert_eq!(&mut [1, 2, 3], v.borrow_mut()); + /// } + /// + /// let v = vec![1, 2, 3]; + /// + /// check(v); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn borrow_mut(&mut self) -> &mut Borrowed; } @@ -171,6 +203,18 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { /// Acquire a mutable reference to the owned form of the data. /// /// Copies the data if it is not already owned. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::Cow; + /// + /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]); + /// + /// let hello = cow.to_mut(); + /// + /// assert_eq!(&[1, 2, 3], hello); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_mut(&mut self) -> &mut ::Owned { match *self { @@ -185,6 +229,18 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { /// Extract the owned data. /// /// Copies the data if it is not already owned. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::Cow; + /// + /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]); + /// + /// let hello = cow.into_owned(); + /// + /// assert_eq!(vec![1, 2, 3], hello); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_owned(self) -> ::Owned { match self { From fe8a66040742f9acd26e5b932550cc0e5d853445 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 31 Mar 2015 00:19:31 -0400 Subject: [PATCH 10/46] Last docs for std::env --- src/libstd/env.rs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 71f072302fb..c50548081ab 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -261,7 +261,20 @@ pub fn set_var(k: &K, v: &V) os_imp::setenv(k.as_os_str(), v.as_os_str()) } -/// Remove a variable from the environment entirely. +/// Remove an environment variable from the environment of the currently running process. +/// +/// # Examples +/// +/// ``` +/// use std::env; +/// +/// let key = "KEY"; +/// env::set_var(key, "VALUE"); +/// assert_eq!(env::var(key), Ok("VALUE".to_string())); +/// +/// env::remove_var(key); +/// assert!(env::var(key).is_err()); +/// ``` #[stable(feature = "env", since = "1.0.0")] pub fn remove_var(k: &K) where K: AsOsStr { let _g = ENV_LOCK.lock(); @@ -398,6 +411,19 @@ pub fn home_dir() -> Option { /// On Windows, returns the value of, in order, the 'TMP', 'TEMP', /// 'USERPROFILE' environment variable if any are set and not the empty /// string. Otherwise, tmpdir returns the path to the Windows directory. +/// +/// ``` +/// use std::env; +/// use std::fs::File; +/// +/// # fn foo() -> std::io::Result<()> { +/// let mut dir = env::temp_dir(); +/// dir.push("foo.txt"); +/// +/// let f = try!(File::create(dir)); +/// # Ok(()) +/// # } +/// ``` #[stable(feature = "env", since = "1.0.0")] pub fn temp_dir() -> PathBuf { os_imp::temp_dir() @@ -557,6 +583,7 @@ pub mod consts { #[stable(feature = "env", since = "1.0.0")] pub const ARCH: &'static str = super::arch::ARCH; + /// The family of the operating system. In this case, `unix`. #[stable(feature = "env", since = "1.0.0")] pub const FAMILY: &'static str = super::os::FAMILY; From 5872ae4a7a76ba67e702323d2de09a86fb5ba692 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 31 Mar 2015 10:32:53 -0400 Subject: [PATCH 11/46] Indicate select! is code-like --- src/libstd/sync/mpsc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index b2b87bb6c44..e14f32865fa 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -114,7 +114,7 @@ //! ``` //! //! Reading from a channel with a timeout requires to use a Timer together -//! with the channel. You can use the select! macro to select either and +//! with the channel. You can use the `select!` macro to select either and //! handle the timeout case. This first example will break out of the loop //! after 10 seconds no matter what: //! From 9fc51efe3344a32d9e522f08383f052277b6ab63 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Mon, 30 Mar 2015 15:15:27 -0700 Subject: [PATCH 12/46] Stabilize `std::convert` and related code * Marks `#[stable]` the contents of the `std::convert` module. * Added methods `PathBuf::as_path`, `OsString::as_os_str`, `String::as_str`, `Vec::{as_slice, as_mut_slice}`. * Deprecates `OsStr::from_str` in favor of a new, stable, and more general `OsStr::new`. * Adds unstable methods `OsString::from_bytes` and `OsStr::{to_bytes, to_cstring}` for ergonomic FFI usage. [breaking-change] --- src/compiletest/compiletest.rs | 1 - src/libcollections/lib.rs | 1 - src/libcollections/string.rs | 9 +++- src/libcollections/vec.rs | 20 ++++---- src/libcore/convert.rs | 38 ++++++++------ src/librustc/lib.rs | 1 - src/librustc_back/lib.rs | 1 - src/librustc_driver/lib.rs | 1 - src/librustc_trans/lib.rs | 1 - src/librustdoc/lib.rs | 1 - src/libserialize/lib.rs | 1 - src/libstd/dynamic_lib.rs | 1 - src/libstd/env.rs | 1 - src/libstd/ffi/os_str.rs | 85 ++++++++++++++++++++++++++++--- src/libstd/lib.rs | 3 +- src/libstd/path.rs | 15 +++--- src/libstd/sys/unix/ext.rs | 9 +--- src/libstd/sys/unix/fs2.rs | 4 +- src/libstd/sys/unix/process2.rs | 2 +- src/libsyntax/lib.rs | 1 - src/libterm/lib.rs | 1 - src/libtest/lib.rs | 1 - src/rustbook/main.rs | 1 - src/test/run-pass/env-home-dir.rs | 1 - src/test/run-pass/issue-20797.rs | 2 - 25 files changed, 132 insertions(+), 70 deletions(-) diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index f0aacc1460b..7fd09f9e1f5 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -18,7 +18,6 @@ #![feature(std_misc)] #![feature(test)] #![feature(path_ext)] -#![feature(convert)] #![feature(str_char)] #![deny(warnings)] diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index c769b3df37f..367a7b41207 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -38,7 +38,6 @@ #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(step_by)] #![feature(str_char)] -#![feature(convert)] #![feature(slice_patterns)] #![feature(debug_builders)] #![cfg_attr(test, feature(rand, rustc_private, test, hash, collections))] diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 7131c1cd881..dff01039f7d 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -364,6 +364,14 @@ impl String { self.vec } + /// Extract a string slice containing the entire string. + #[inline] + #[unstable(feature = "convert", + reason = "waiting on RFC revision")] + pub fn as_str(&self) -> &str { + self + } + /// Pushes the given string onto this string buffer. /// /// # Examples @@ -848,7 +856,6 @@ impl<'a, 'b> PartialEq> for &'b str { #[allow(deprecated)] impl Str for String { #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn as_slice(&self) -> &str { unsafe { mem::transmute(&*self.vec) } } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 14bc7f65e09..6ee7b0a86c8 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -423,11 +423,18 @@ impl Vec { } } + /// Extract a slice containing the entire vector. + #[inline] + #[unstable(feature = "convert", + reason = "waiting on RFC revision")] + pub fn as_slice(&self) -> &[T] { + self + } + /// Deprecated: use `&mut s[..]` instead. #[inline] - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")] + #[unstable(feature = "convert", + reason = "waiting on RFC revision")] pub fn as_mut_slice(&mut self) -> &mut [T] { &mut self[..] } @@ -1640,13 +1647,6 @@ impl AsRef> for Vec { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Into> for Vec { - fn into(self) -> Vec { - self - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl AsRef<[T]> for Vec { fn as_ref(&self) -> &[T] { diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 21f9b1f5513..4a99f1a756a 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -14,33 +14,40 @@ //! conversions from one type to another. They follow the standard //! Rust conventions of `as`/`to`/`into`/`from`. -#![unstable(feature = "convert", - reason = "recently added, experimental traits")] +#![stable(feature = "rust1", since = "1.0.0")] use marker::Sized; /// A cheap, reference-to-reference conversion. +#[stable(feature = "rust1", since = "1.0.0")] pub trait AsRef { /// Perform the conversion. + #[stable(feature = "rust1", since = "1.0.0")] fn as_ref(&self) -> &T; } /// A cheap, mutable reference-to-mutable reference conversion. +#[stable(feature = "rust1", since = "1.0.0")] pub trait AsMut { /// Perform the conversion. + #[stable(feature = "rust1", since = "1.0.0")] fn as_mut(&mut self) -> &mut T; } /// A conversion that consumes `self`, which may or may not be /// expensive. +#[stable(feature = "rust1", since = "1.0.0")] pub trait Into: Sized { /// Perform the conversion. + #[stable(feature = "rust1", since = "1.0.0")] fn into(self) -> T; } /// Construct `Self` via a conversion. +#[stable(feature = "rust1", since = "1.0.0")] pub trait From { /// Perform the conversion. + #[stable(feature = "rust1", since = "1.0.0")] fn from(T) -> Self; } @@ -48,14 +55,8 @@ pub trait From { // GENERIC IMPLS //////////////////////////////////////////////////////////////////////////////// -// As implies Into -impl<'a, T: ?Sized, U: ?Sized> Into<&'a U> for &'a T where T: AsRef { - fn into(self) -> &'a U { - self.as_ref() - } -} - // As lifts over & +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized, U: ?Sized> AsRef for &'a T where T: AsRef { fn as_ref(&self) -> &U { >::as_ref(*self) @@ -63,6 +64,7 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef for &'a T where T: AsRef { } // As lifts over &mut +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized, U: ?Sized> AsRef for &'a mut T where T: AsRef { fn as_ref(&self) -> &U { >::as_ref(*self) @@ -77,14 +79,8 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef for &'a mut T where T: AsRef { // } // } -// AsMut implies Into -impl<'a, T: ?Sized, U: ?Sized> Into<&'a mut U> for &'a mut T where T: AsMut { - fn into(self) -> &'a mut U { - (*self).as_mut() - } -} - // AsMut lifts over &mut +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized, U: ?Sized> AsMut for &'a mut T where T: AsMut { fn as_mut(&mut self) -> &mut U { (*self).as_mut() @@ -100,28 +96,38 @@ impl<'a, T: ?Sized, U: ?Sized> AsMut for &'a mut T where T: AsMut { // } // From implies Into +#[stable(feature = "rust1", since = "1.0.0")] impl Into for T where U: From { fn into(self) -> U { U::from(self) } } +// From (and thus Into) is reflexive +#[stable(feature = "rust1", since = "1.0.0")] +impl From for T { + fn from(t: T) -> T { t } +} + //////////////////////////////////////////////////////////////////////////////// // CONCRETE IMPLS //////////////////////////////////////////////////////////////////////////////// +#[stable(feature = "rust1", since = "1.0.0")] impl AsRef<[T]> for [T] { fn as_ref(&self) -> &[T] { self } } +#[stable(feature = "rust1", since = "1.0.0")] impl AsMut<[T]> for [T] { fn as_mut(&mut self) -> &mut [T] { self } } +#[stable(feature = "rust1", since = "1.0.0")] impl AsRef for str { fn as_ref(&self) -> &str { self diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index f31f8e8d4ce..6215f823142 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -41,7 +41,6 @@ #![feature(path_ext)] #![feature(str_words)] #![feature(str_char)] -#![feature(convert)] #![feature(into_cow)] #![feature(slice_patterns)] #![cfg_attr(test, feature(test))] diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index fe457841e91..5d7457da7e0 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -46,7 +46,6 @@ #![feature(path_ext)] #![feature(std_misc)] #![feature(step_by)] -#![feature(convert)] #![cfg_attr(test, feature(test, rand))] extern crate syntax; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 456d5f7a60a..112f1502643 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -38,7 +38,6 @@ #![feature(io)] #![feature(set_stdio)] #![feature(unicode)] -#![feature(convert)] extern crate arena; extern crate flate; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index a3ac0473bfa..b0eacd1a55d 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -39,7 +39,6 @@ #![feature(unicode)] #![feature(path_ext)] #![feature(fs)] -#![feature(convert)] #![feature(path_relative_from)] #![allow(trivial_casts)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 431cb4a2898..98598509cbc 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -36,7 +36,6 @@ #![feature(file_path)] #![feature(path_ext)] #![feature(path_relative_from)] -#![feature(convert)] #![feature(slice_patterns)] extern crate arena; diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index b79323b3f96..2e86712c9bc 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -36,7 +36,6 @@ Core encoding and decoding interfaces. #![feature(std_misc)] #![feature(unicode)] #![feature(str_char)] -#![feature(convert)] #![cfg_attr(test, feature(test, old_io))] // test harness access diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index d8a95133d94..f9bb7e6cbd4 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -190,7 +190,6 @@ mod dl { use ffi::{CStr, OsStr}; use str; use libc; - use os::unix::prelude::*; use ptr; pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 71f072302fb..6553b40b745 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -327,7 +327,6 @@ pub struct JoinPathsError { /// # Examples /// /// ``` -/// # #![feature(convert)] /// use std::env; /// use std::path::PathBuf; /// diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 49dbac4585b..30e96ec465f 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -35,6 +35,7 @@ use core::prelude::*; use borrow::{Borrow, Cow, ToOwned}; +use ffi::CString; use fmt::{self, Debug}; use mem; use string::String; @@ -42,6 +43,7 @@ use ops; use cmp; use hash::{Hash, Hasher}; use old_path::{Path, GenericPath}; +use vec::Vec; use sys::os_str::{Buf, Slice}; use sys_common::{AsInner, IntoInner, FromInner}; @@ -83,6 +85,37 @@ impl OsString { OsString { inner: Buf::from_string(String::new()) } } + /// Construct an `OsString` from a byte sequence. + /// + /// # Platform behavior + /// + /// On Unix systems, any byte sequence can be successfully + /// converted into an `OsString`. + /// + /// On Windows system, only UTF-8 byte sequences will successfully + /// convert; non UTF-8 data will produce `None`. + #[unstable(feature = "convert", reason = "recently added")] + pub fn from_bytes(bytes: B) -> Option where B: Into> { + #[cfg(unix)] + fn from_bytes_inner(vec: Vec) -> Option { + use os::unix::ffi::OsStringExt; + Some(OsString::from_vec(vec)) + } + + #[cfg(windows)] + fn from_bytes_inner(vec: Vec) -> Option { + String::from_utf8(vec).ok().map(OsString::from) + } + + from_bytes_inner(bytes.into()) + } + + /// Convert to an `OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_os_str(&self) -> &OsStr { + self + } + /// Convert the `OsString` into a `String` if it contains valid Unicode data. /// /// On failure, ownership of the original `OsString` is returned. @@ -211,8 +244,16 @@ impl Hash for OsString { } impl OsStr { + /// Coerce into an `OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new + ?Sized>(s: &S) -> &OsStr { + s.as_ref() + } + /// Coerce directly from a `&str` slice to a `&OsStr` slice. #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", + reason = "use `OsStr::new` instead")] pub fn from_str(s: &str) -> &OsStr { unsafe { mem::transmute(Slice::from_str(s)) } } @@ -239,6 +280,36 @@ impl OsStr { OsString { inner: self.inner.to_owned() } } + /// Yield this `OsStr` as a byte slice. + /// + /// # Platform behavior + /// + /// On Unix systems, this is a no-op. + /// + /// On Windows systems, this returns `None` unless the `OsStr` is + /// valid unicode, in which case it produces UTF-8-encoded + /// data. This may entail checking validity. + #[unstable(feature = "convert", reason = "recently added")] + pub fn to_bytes(&self) -> Option<&[u8]> { + if cfg!(windows) { + self.to_str().map(|s| s.as_bytes()) + } else { + Some(self.bytes()) + } + } + + /// Create a `CString` containing this `OsStr` data. + /// + /// Fails if the `OsStr` contains interior nulls. + /// + /// This is a convenience for creating a `CString` from + /// `self.to_bytes()`, and inherits the platform behavior of the + /// `to_bytes` method. + #[unstable(feature = "convert", reason = "recently added")] + pub fn to_cstring(&self) -> Option { + self.to_bytes().and_then(|b| CString::new(b).ok()) + } + /// Get the underlying byte representation. /// /// Note: it is *crucial* that this API is private, to avoid @@ -258,14 +329,14 @@ impl PartialEq for OsStr { #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for OsStr { fn eq(&self, other: &str) -> bool { - *self == *OsStr::from_str(other) + *self == *OsStr::new(other) } } #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for str { fn eq(&self, other: &OsStr) -> bool { - *other == *OsStr::from_str(self) + *other == *OsStr::new(self) } } @@ -292,7 +363,7 @@ impl PartialOrd for OsStr { impl PartialOrd for OsStr { #[inline] fn partial_cmp(&self, other: &str) -> Option { - self.partial_cmp(OsStr::from_str(other)) + self.partial_cmp(OsStr::new(other)) } } @@ -359,7 +430,7 @@ impl AsOsStr for OsString { #[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl AsOsStr for str { fn as_os_str(&self) -> &OsStr { - OsStr::from_str(self) + unsafe { mem::transmute(Slice::from_str(self)) } } } @@ -367,7 +438,7 @@ impl AsOsStr for str { #[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl AsOsStr for String { fn as_os_str(&self) -> &OsStr { - OsStr::from_str(&self[..]) + unsafe { mem::transmute(Slice::from_str(self)) } } } @@ -388,14 +459,14 @@ impl AsRef for OsString { #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for str { fn as_ref(&self) -> &OsStr { - OsStr::from_str(self) + unsafe { mem::transmute(Slice::from_str(self)) } } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for String { fn as_ref(&self) -> &OsStr { - OsStr::from_str(&self[..]) + unsafe { mem::transmute(Slice::from_str(self)) } } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index b7cb8f9ed50..cd7fcc433a6 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -122,12 +122,11 @@ #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(macro_reexport)] #![feature(unique)] -#![feature(convert)] #![feature(allow_internal_unstable)] #![feature(str_char)] #![feature(into_cow)] -#![feature(slice_patterns)] #![feature(std_misc)] +#![feature(slice_patterns)] #![feature(debug_builders)] #![cfg_attr(test, feature(test, rustc_private, std_misc))] diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 58d3ae9f7cf..36a5d1465f0 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -35,7 +35,6 @@ //! To build or modify paths, use `PathBuf`: //! //! ```rust -//! # #![feature(convert)] //! use std::path::PathBuf; //! //! let mut path = PathBuf::from("c:\\"); @@ -521,9 +520,9 @@ impl<'a> Component<'a> { pub fn as_os_str(self) -> &'a OsStr { match self { Component::Prefix(p) => p.as_os_str(), - Component::RootDir => OsStr::from_str(MAIN_SEP_STR), - Component::CurDir => OsStr::from_str("."), - Component::ParentDir => OsStr::from_str(".."), + Component::RootDir => OsStr::new(MAIN_SEP_STR), + Component::CurDir => OsStr::new("."), + Component::ParentDir => OsStr::new(".."), Component::Normal(path) => path, } } @@ -893,7 +892,6 @@ impl<'a> cmp::Ord for Components<'a> { /// # Examples /// /// ``` -/// # #![feature(convert)] /// use std::path::PathBuf; /// /// let mut path = PathBuf::from("c:\\"); @@ -918,6 +916,12 @@ impl PathBuf { PathBuf { inner: OsString::new() } } + /// Coerce to a `Path` slice. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_path(&self) -> &Path { + self + } + /// Extend `self` with `path`. /// /// If `path` is absolute, it replaces the current path. @@ -985,7 +989,6 @@ impl PathBuf { /// # Examples /// /// ``` - /// # #![feature(convert)] /// use std::path::PathBuf; /// /// let mut buf = PathBuf::from("/"); diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index 0805949d560..d197d04c0a4 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -138,7 +138,7 @@ pub mod io { /// Unix-specific extension to the primitives in the `std::ffi` module #[stable(feature = "rust1", since = "1.0.0")] pub mod ffi { - use ffi::{CString, NulError, OsStr, OsString}; + use ffi::{OsStr, OsString}; use mem; use prelude::v1::*; use sys::os_str::Buf; @@ -175,10 +175,6 @@ pub mod ffi { /// Get the underlying byte view of the `OsStr` slice. #[stable(feature = "rust1", since = "1.0.0")] fn as_bytes(&self) -> &[u8]; - - /// Convert the `OsStr` slice into a `CString`. - #[stable(feature = "rust1", since = "1.0.0")] - fn to_cstring(&self) -> Result; } #[stable(feature = "rust1", since = "1.0.0")] @@ -189,9 +185,6 @@ pub mod ffi { fn as_bytes(&self) -> &[u8] { &self.as_inner().inner } - fn to_cstring(&self) -> Result { - CString::new(self.as_bytes()) - } } } diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs index 202e5ddaec4..c7bfb8604bc 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs2.rs @@ -276,8 +276,8 @@ impl File { } fn cstr(path: &Path) -> io::Result { - let cstring = try!(path.as_os_str().to_cstring()); - Ok(cstring) + path.as_os_str().to_cstring().ok_or( + io::Error::new(io::ErrorKind::InvalidInput, "path contained a null", None)) } pub fn mkdir(p: &Path) -> io::Result<()> { diff --git a/src/libstd/sys/unix/process2.rs b/src/libstd/sys/unix/process2.rs index 20c409154b8..c2a8b26aef4 100644 --- a/src/libstd/sys/unix/process2.rs +++ b/src/libstd/sys/unix/process2.rs @@ -54,7 +54,7 @@ impl Command { self.args.push(arg.to_cstring().unwrap()) } pub fn args<'a, I: Iterator>(&mut self, args: I) { - self.args.extend(args.map(|s| OsStrExt::to_cstring(s).unwrap())) + self.args.extend(args.map(|s| s.to_cstring().unwrap())) } fn init_env_map(&mut self) { if self.env.is_none() { diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index c471d9e3179..0980acd3433 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -37,7 +37,6 @@ #![feature(unicode)] #![feature(path_ext)] #![feature(str_char)] -#![feature(convert)] #![feature(into_cow)] #![feature(slice_patterns)] diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index ed2d00d6ad7..38d58f042b9 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -62,7 +62,6 @@ #![feature(std_misc)] #![feature(str_char)] #![feature(path_ext)] -#![feature(convert)] #![cfg_attr(windows, feature(libc))] #[macro_use] extern crate log; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index ee0d190d729..a08d125c233 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -44,7 +44,6 @@ #![feature(libc)] #![feature(set_stdio)] #![feature(os)] -#![feature(convert)] #![cfg_attr(test, feature(old_io))] extern crate getopts; diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs index 4a652f846ed..09fcd518c1e 100644 --- a/src/rustbook/main.rs +++ b/src/rustbook/main.rs @@ -15,7 +15,6 @@ #![feature(rustdoc)] #![feature(rustc_private)] #![feature(path_relative_from)] -#![feature(convert)] extern crate rustdoc; extern crate rustc_back; diff --git a/src/test/run-pass/env-home-dir.rs b/src/test/run-pass/env-home-dir.rs index 2d0128ba89e..7fb96112125 100644 --- a/src/test/run-pass/env-home-dir.rs +++ b/src/test/run-pass/env-home-dir.rs @@ -11,7 +11,6 @@ // pretty-expanded FIXME #23616 #![feature(path)] -#![feature(convert)] use std::env::*; use std::path::PathBuf; diff --git a/src/test/run-pass/issue-20797.rs b/src/test/run-pass/issue-20797.rs index d0720ec593f..45d31d4a7f1 100644 --- a/src/test/run-pass/issue-20797.rs +++ b/src/test/run-pass/issue-20797.rs @@ -12,8 +12,6 @@ // pretty-expanded FIXME #23616 -#![feature(convert)] - use std::default::Default; use std::io; use std::fs; From cf5616242a1d724a374e0da5f7e247765178a769 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 31 Mar 2015 14:55:25 -0400 Subject: [PATCH 13/46] Fix up iterator documentation with regards to for loop sugar Fixes #23851 --- src/libcore/iter.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 44d48f9f4bf..10507389b8d 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -25,23 +25,22 @@ //! the `FromIterator` trait for creating a container from an iterator, and much //! more. //! -//! ## Rust's `for` loop +//! # Rust's `for` loop //! -//! The special syntax used by rust's `for` loop is based around the `Iterator` -//! trait defined in this module. For loops can be viewed as a syntactical expansion +//! The special syntax used by rust's `for` loop is based around the `IntoIterator` +//! trait defined in this module. `for` loops can be viewed as a syntactical expansion //! into a `loop`, for example, the `for` loop in this example is essentially //! translated to the `loop` below. //! //! ``` //! let values = vec![1, 2, 3]; //! -//! // "Syntactical sugar" taking advantage of an iterator -//! for &x in values.iter() { +//! for x in values { //! println!("{}", x); //! } //! //! // Rough translation of the iteration without a `for` iterator. -//! let mut it = values.iter(); +//! let mut it = values.into_iter(); //! loop { //! match it.next() { //! Some(&x) => { @@ -52,7 +51,8 @@ //! } //! ``` //! -//! This `for` loop syntax can be applied to any iterator over any type. +//! Because `Iterator`s implement `IntoIterator`, this `for` loop syntax can be applied to any +//! iterator over any type. #![stable(feature = "rust1", since = "1.0.0")] @@ -1041,6 +1041,9 @@ pub trait FromIterator { } /// Conversion into an `Iterator` +/// +/// Implementing this trait allows you to use your type with Rust's `for` loop. See +/// the [module level documentation](../index.html) for more details. #[stable(feature = "rust1", since = "1.0.0")] pub trait IntoIterator { /// The type of the elements being iterated From 9ba7974b357c7f2f69d74c9f8a01e282d7f4da6f Mon Sep 17 00:00:00 2001 From: Darin Morrison Date: Tue, 31 Mar 2015 14:14:04 -0600 Subject: [PATCH 14/46] book: reword timer bit --- src/doc/trpl/concurrency.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/doc/trpl/concurrency.md b/src/doc/trpl/concurrency.md index 79cb3117c0e..6b814a68542 100644 --- a/src/doc/trpl/concurrency.md +++ b/src/doc/trpl/concurrency.md @@ -280,13 +280,15 @@ it returns an `Result`, and because this is just an example, we `unwrap()` it to get a reference to the data. Real code would have more robust error handling here. We're then free to mutate it, since we have the lock. -This timer bit is a bit awkward, however. We have picked a reasonable amount of -time to wait, but it's entirely possible that we've picked too high, and that -we could be taking less time. It's also possible that we've picked too low, -and that we aren't actually finishing this computation. +Lastly, while the threads are running, we wait on a short timer. But +this is not ideal: we may have picked a reasonable amount of time to +wait but it's more likely we'll either be waiting longer than +necessary or not long enough, depending on just how much time the +threads actually take to finish computing when the program runs. -Rust's standard library provides a few more mechanisms for two threads to -synchronize with each other. Let's talk about one: channels. +A more precise alternative to the timer would be to use one of the +mechanisms provided by the Rust standard library for synchronizing +threads with each other. Let's talk about one of them: channels. ## Channels From d9a6e86275d6f7ac6d9d0b4817dec6368e1537ef Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 31 Mar 2015 16:19:52 -0400 Subject: [PATCH 15/46] Fixup primitive.str docs Remove broken links that should just point to the current page, and while we're at it, re-wrap to 100 chars. --- src/libcollections/str.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 9ddf8988f1e..83578ea69a1 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -10,13 +10,12 @@ // // ignore-lexer-test FIXME #15679 -//! Unicode string manipulation (the [`str`](../primitive.str.html) type). +//! Unicode string manipulation (the `str` type). //! -//! Rust's [`str`](../primitive.str.html) type is one of the core primitive -//! types of the language. `&str` is the borrowed string type. This type of -//! string can only be created from other strings, unless it is a `&'static str` -//! (see below). It is not possible to move out of borrowed strings because they -//! are owned elsewhere. +//! Rust's `str` type is one of the core primitive types of the language. `&str` is the borrowed +//! string type. This type of string can only be created from other strings, unless it is a +//! `&'static str` (see below). It is not possible to move out of borrowed strings because they are +//! owned elsewhere. //! //! # Examples //! @@ -26,9 +25,8 @@ //! let s = "Hello, world."; //! ``` //! -//! This `&str` is a `&'static str`, which is the type of string literals. -//! They're `'static` because literals are available for the entire lifetime of -//! the program. +//! This `&str` is a `&'static str`, which is the type of string literals. They're `'static` +//! because literals are available for the entire lifetime of the program. //! //! You can get a non-`'static` `&str` by taking a slice of a `String`: //! @@ -39,13 +37,12 @@ //! //! # Representation //! -//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as -//! a stream of UTF-8 bytes. All [strings](../../reference.html#literals) are -//! guaranteed to be validly encoded UTF-8 sequences. Additionally, strings are -//! not null-terminated and can thus contain null bytes. +//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as a stream of UTF-8 +//! bytes. All [strings](../../reference.html#literals) are guaranteed to be validly encoded UTF-8 +//! sequences. Additionally, strings are not null-terminated and can thus contain null bytes. //! -//! The actual representation of `str`s have direct mappings to slices: `&str` -//! is the same as `&[u8]`. +//! The actual representation of `str`s have direct mappings to slices: `&str` is the same as +//! `&[u8]`. #![doc(primitive = "str")] #![stable(feature = "rust1", since = "1.0.0")] From 5cf126ae2f6af1cdac901f6995e3c2bab35e587f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 10 Mar 2015 17:59:23 -0700 Subject: [PATCH 16/46] std: Remove #[old_orphan_check] from PartialEq This is a deprecated attribute that is slated for removal, and it also affects all implementors of the trait. This commit removes the attribute and fixes up implementors accordingly. The primary implementation which was lost was the ability to compare `&[T]` and `Vec` (in that order). This change also modifies the `assert_eq!` macro to not consider both directions of equality, only the one given in the left/right forms to the macro. This modification is motivated due to the fact that `&[T] == Vec` no longer compiles, causing hundreds of errors in unit tests in the standard library (and likely throughout the community as well). cc #19470 [breaking-change] --- src/doc/trpl/macros.md | 6 +++--- src/libcollections/linked_list.rs | 2 +- src/libcollections/vec.rs | 22 +++++++++++----------- src/libcollectionstest/enum_set.rs | 22 +++++++++++----------- src/libcollectionstest/str.rs | 2 +- src/libcollectionstest/vec_deque.rs | 12 ++++++------ src/libcore/cmp.rs | 1 - src/libcore/cmp_macros.rs | 13 +++++-------- src/libcore/iter.rs | 11 +++++------ src/libcore/macros.rs | 12 +++++------- src/libcoretest/mem.rs | 2 +- src/libfmt_macros/lib.rs | 2 +- src/librustc_driver/test.rs | 11 +++++------ src/libstd/collections/hash/set.rs | 2 +- src/libstd/old_io/buffered.rs | 2 +- src/libstd/old_io/util.rs | 20 ++++++++++---------- src/libstd/old_path/posix.rs | 13 ++++++------- src/libsyntax/util/small_vector.rs | 6 +++--- src/test/run-fail/assert-eq-macro-panic.rs | 2 +- 19 files changed, 77 insertions(+), 86 deletions(-) diff --git a/src/doc/trpl/macros.md b/src/doc/trpl/macros.md index 7da36043f6c..7e19ec94ee7 100644 --- a/src/doc/trpl/macros.md +++ b/src/doc/trpl/macros.md @@ -37,7 +37,7 @@ number of elements. ```rust let x: Vec = vec![1, 2, 3]; -# assert_eq!(&[1,2,3], &x); +# assert_eq!(x, [1, 2, 3]); ``` This can't be an ordinary function, because it takes any number of arguments. @@ -51,7 +51,7 @@ let x: Vec = { temp_vec.push(3); temp_vec }; -# assert_eq!(&[1,2,3], &x); +# assert_eq!(x, [1, 2, 3]); ``` We can implement this shorthand, using a macro: [^actual] @@ -73,7 +73,7 @@ macro_rules! vec { }; } # fn main() { -# assert_eq!([1,2,3], vec![1,2,3]); +# assert_eq!(vec![1,2,3], [1, 2, 3]); # } ``` diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 52da4902b75..56a811cc4a6 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -1079,7 +1079,7 @@ mod test { thread::spawn(move || { check_links(&n); let a: &[_] = &[&1,&2,&3]; - assert_eq!(a, n.iter().collect::>()); + assert_eq!(a, &n.iter().collect::>()[..]); }).join().ok().unwrap(); } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 3595288a6c9..451565e8feb 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1533,22 +1533,22 @@ impl Extend for Vec { } __impl_slice_eq1! { Vec, Vec } -__impl_slice_eq2! { Vec, &'b [B] } -__impl_slice_eq2! { Vec, &'b mut [B] } -__impl_slice_eq2! { Cow<'a, [A]>, &'b [B], Clone } -__impl_slice_eq2! { Cow<'a, [A]>, &'b mut [B], Clone } -__impl_slice_eq2! { Cow<'a, [A]>, Vec, Clone } +__impl_slice_eq1! { Vec, &'b [B] } +__impl_slice_eq1! { Vec, &'b mut [B] } +__impl_slice_eq1! { Cow<'a, [A]>, &'b [B], Clone } +__impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B], Clone } +__impl_slice_eq1! { Cow<'a, [A]>, Vec, Clone } macro_rules! array_impls { ($($N: expr)+) => { $( // NOTE: some less important impls are omitted to reduce code bloat - __impl_slice_eq2! { Vec, [B; $N] } - __impl_slice_eq2! { Vec, &'b [B; $N] } - // __impl_slice_eq2! { Vec, &'b mut [B; $N] } - // __impl_slice_eq2! { Cow<'a, [A]>, [B; $N], Clone } - // __impl_slice_eq2! { Cow<'a, [A]>, &'b [B; $N], Clone } - // __impl_slice_eq2! { Cow<'a, [A]>, &'b mut [B; $N], Clone } + __impl_slice_eq1! { Vec, [B; $N] } + __impl_slice_eq1! { Vec, &'b [B; $N] } + // __impl_slice_eq1! { Vec, &'b mut [B; $N] } + // __impl_slice_eq1! { Cow<'a, [A]>, [B; $N], Clone } + // __impl_slice_eq1! { Cow<'a, [A]>, &'b [B; $N], Clone } + // __impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B; $N], Clone } )+ } } diff --git a/src/libcollectionstest/enum_set.rs b/src/libcollectionstest/enum_set.rs index f04367147cb..a748541fca5 100644 --- a/src/libcollectionstest/enum_set.rs +++ b/src/libcollectionstest/enum_set.rs @@ -153,19 +153,19 @@ fn test_iterator() { e1.insert(A); let elems: Vec<_> = e1.iter().collect(); - assert_eq!([A], elems); + assert_eq!(elems, [A]); e1.insert(C); let elems: Vec<_> = e1.iter().collect(); - assert_eq!([A,C], elems); + assert_eq!(elems, [A,C]); e1.insert(C); let elems: Vec<_> = e1.iter().collect(); - assert_eq!([A,C], elems); + assert_eq!(elems, [A,C]); e1.insert(B); let elems: Vec<_> = e1.iter().collect(); - assert_eq!([A,B,C], elems); + assert_eq!(elems, [A,B,C]); } /////////////////////////////////////////////////////////////////////////// @@ -183,35 +183,35 @@ fn test_operators() { let e_union = e1 | e2; let elems: Vec<_> = e_union.iter().collect(); - assert_eq!([A,B,C], elems); + assert_eq!(elems, [A,B,C]); let e_intersection = e1 & e2; let elems: Vec<_> = e_intersection.iter().collect(); - assert_eq!([C], elems); + assert_eq!(elems, [C]); // Another way to express intersection let e_intersection = e1 - (e1 - e2); let elems: Vec<_> = e_intersection.iter().collect(); - assert_eq!([C], elems); + assert_eq!(elems, [C]); let e_subtract = e1 - e2; let elems: Vec<_> = e_subtract.iter().collect(); - assert_eq!([A], elems); + assert_eq!(elems, [A]); // Bitwise XOR of two sets, aka symmetric difference let e_symmetric_diff = e1 ^ e2; let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!([A,B], elems); + assert_eq!(elems, [A,B]); // Another way to express symmetric difference let e_symmetric_diff = (e1 - e2) | (e2 - e1); let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!([A,B], elems); + assert_eq!(elems, [A,B]); // Yet another way to express symmetric difference let e_symmetric_diff = (e1 | e2) - (e1 & e2); let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!([A,B], elems); + assert_eq!(elems, [A,B]); } #[test] diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index 5cfa8009054..ef3373a3596 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -83,7 +83,7 @@ fn test_collect() { fn test_into_bytes() { let data = String::from_str("asdf"); let buf = data.into_bytes(); - assert_eq!(b"asdf", buf); + assert_eq!(buf, b"asdf"); } #[test] diff --git a/src/libcollectionstest/vec_deque.rs b/src/libcollectionstest/vec_deque.rs index fe752d5a7e1..f78356fe392 100644 --- a/src/libcollectionstest/vec_deque.rs +++ b/src/libcollectionstest/vec_deque.rs @@ -821,7 +821,7 @@ fn test_as_slices() { let (left, right) = ring.as_slices(); let expected: Vec<_> = (0..i+1).collect(); - assert_eq!(left, expected); + assert_eq!(left, &expected[..]); assert_eq!(right, []); } @@ -830,8 +830,8 @@ fn test_as_slices() { let (left, right) = ring.as_slices(); let expected_left: Vec<_> = (-last..j+1).rev().collect(); let expected_right: Vec<_> = (0..first).collect(); - assert_eq!(left, expected_left); - assert_eq!(right, expected_right); + assert_eq!(left, &expected_left[..]); + assert_eq!(right, &expected_right[..]); } assert_eq!(ring.len() as i32, cap); @@ -849,7 +849,7 @@ fn test_as_mut_slices() { let (left, right) = ring.as_mut_slices(); let expected: Vec<_> = (0..i+1).collect(); - assert_eq!(left, expected); + assert_eq!(left, &expected[..]); assert_eq!(right, []); } @@ -858,8 +858,8 @@ fn test_as_mut_slices() { let (left, right) = ring.as_mut_slices(); let expected_left: Vec<_> = (-last..j+1).rev().collect(); let expected_right: Vec<_> = (0..first).collect(); - assert_eq!(left, expected_left); - assert_eq!(right, expected_right); + assert_eq!(left, &expected_left[..]); + assert_eq!(right, &expected_right[..]); } assert_eq!(ring.len() as i32, cap); diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 9b8b59ec8ce..859cab4225e 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -64,7 +64,6 @@ use option::Option::{self, Some, None}; /// inverse of `ne`; that is, `!(a == b)` if and only if `a != b`. #[lang="eq"] #[stable(feature = "rust1", since = "1.0.0")] -#[old_orphan_check] pub trait PartialEq { /// This method tests for `self` and `other` values to be equal, and is used by `==`. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/cmp_macros.rs b/src/libcore/cmp_macros.rs index 18357bac9e6..95dab3d165a 100644 --- a/src/libcore/cmp_macros.rs +++ b/src/libcore/cmp_macros.rs @@ -15,8 +15,11 @@ #[macro_export] macro_rules! __impl_slice_eq1 { ($Lhs: ty, $Rhs: ty) => { + __impl_slice_eq1! { $Lhs, $Rhs, Sized } + }; + ($Lhs: ty, $Rhs: ty, $Bound: ident) => { #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A, B> PartialEq<$Rhs> for $Lhs where A: PartialEq { + impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq { #[inline] fn eq(&self, other: &$Rhs) -> bool { &self[..] == &other[..] } #[inline] @@ -31,13 +34,7 @@ macro_rules! __impl_slice_eq2 { __impl_slice_eq2! { $Lhs, $Rhs, Sized } }; ($Lhs: ty, $Rhs: ty, $Bound: ident) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq { - #[inline] - fn eq(&self, other: &$Rhs) -> bool { &self[..] == &other[..] } - #[inline] - fn ne(&self, other: &$Rhs) -> bool { &self[..] != &other[..] } - } + __impl_slice_eq1!($Lhs, $Rhs, $Bound); #[stable(feature = "rust1", since = "1.0.0")] impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq { diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 44d48f9f4bf..1495d1d584e 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -530,10 +530,9 @@ pub trait Iterator { /// # Examples /// /// ``` - /// # #![feature(core)] - /// let a = [1, 2, 3, 4, 5]; - /// let b: Vec<_> = a.iter().cloned().collect(); - /// assert_eq!(a, b); + /// let expected = [1, 2, 3, 4, 5]; + /// let actual: Vec<_> = expected.iter().cloned().collect(); + /// assert_eq!(actual, expected); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -927,8 +926,8 @@ pub trait Iterator { /// # #![feature(core)] /// let a = [(1, 2), (3, 4)]; /// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip(); - /// assert_eq!([1, 3], left); - /// assert_eq!([2, 4], right); + /// assert_eq!(left, [1, 3]); + /// assert_eq!(right, [2, 4]); /// ``` #[unstable(feature = "core", reason = "recent addition")] fn unzip(self) -> (FromA, FromB) where diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index d5a7c1d6b26..e8959299d72 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -66,10 +66,10 @@ macro_rules! assert { ); } -/// Asserts that two expressions are equal to each other, testing equality in -/// both directions. +/// Asserts that two expressions are equal to each other. /// -/// On panic, this macro will print the values of the expressions. +/// On panic, this macro will print the values of the expressions with their +/// debug representations. /// /// # Examples /// @@ -84,10 +84,8 @@ macro_rules! assert_eq { ($left:expr , $right:expr) => ({ match (&($left), &($right)) { (left_val, right_val) => { - // check both directions of equality.... - if !((*left_val == *right_val) && - (*right_val == *left_val)) { - panic!("assertion failed: `(left == right) && (right == left)` \ + if !(*left_val == *right_val) { + panic!("assertion failed: `(left == right)` \ (left: `{:?}`, right: `{:?}`)", *left_val, *right_val) } } diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs index fae36787c3d..5bc08376d25 100644 --- a/src/libcoretest/mem.rs +++ b/src/libcoretest/mem.rs @@ -103,7 +103,7 @@ fn test_transmute() { } unsafe { - assert_eq!([76], transmute::<_, Vec>("L".to_string())); + assert_eq!(transmute::<_, Vec>("L".to_string()), [76]); } } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 9b220409ef5..a7be6a7fcf0 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -446,7 +446,7 @@ mod tests { fn same(fmt: &'static str, p: &[Piece<'static>]) { let parser = Parser::new(fmt); - assert!(p == parser.collect::>>()); + assert!(parser.collect::>>() == p); } fn fmtdflt() -> FormatSpec<'static> { diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index fcb0b9bdd3c..b0fc5fbcb50 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -808,12 +808,11 @@ fn walk_ty() { let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty)); let uniq_ty = ty::mk_uniq(tcx, tup2_ty); let walked: Vec<_> = uniq_ty.walk().collect(); - assert_eq!([uniq_ty, - tup2_ty, - tup1_ty, int_ty, uint_ty, int_ty, uint_ty, - tup1_ty, int_ty, uint_ty, int_ty, uint_ty, - uint_ty], - walked); + assert_eq!(walked, [uniq_ty, + tup2_ty, + tup1_ty, int_ty, uint_ty, int_ty, uint_ty, + tup1_ty, int_ty, uint_ty, int_ty, uint_ty, + uint_ty]); }) } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 87380471c80..5fbc21797ab 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -1192,7 +1192,7 @@ mod test_set { }; let v = hs.into_iter().collect::>(); - assert!(['a', 'b'] == v || ['b', 'a'] == v); + assert!(v == ['a', 'b'] || v == ['b', 'a']); } #[test] diff --git a/src/libstd/old_io/buffered.rs b/src/libstd/old_io/buffered.rs index ad6cac62173..68aa7e4770f 100644 --- a/src/libstd/old_io/buffered.rs +++ b/src/libstd/old_io/buffered.rs @@ -548,7 +548,7 @@ mod test { let mut w = BufferedWriter::with_capacity(3, Vec::new()); w.write_all(&[0, 1]).unwrap(); let a: &[_] = &[]; - assert_eq!(a, &w.get_ref()[..]); + assert_eq!(&w.get_ref()[..], a); let w = w.into_inner(); let a: &[_] = &[0, 1]; assert_eq!(a, &w[..]); diff --git a/src/libstd/old_io/util.rs b/src/libstd/old_io/util.rs index 604099f1178..a5ecb98334a 100644 --- a/src/libstd/old_io/util.rs +++ b/src/libstd/old_io/util.rs @@ -334,7 +334,7 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2)); { let mut r = LimitReader::new(r.by_ref(), 4); - assert_eq!([0, 1, 2], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]); } } @@ -343,9 +343,9 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2)); { let mut r = LimitReader::new(r.by_ref(), 2); - assert_eq!([0, 1], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1]); } - assert_eq!([2], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [2]); } #[test] @@ -355,7 +355,7 @@ mod test { assert_eq!(3, r.limit()); assert_eq!(0, r.read_byte().unwrap()); assert_eq!(2, r.limit()); - assert_eq!([1, 2], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [1, 2]); assert_eq!(0, r.limit()); } @@ -364,7 +364,7 @@ mod test { let mut r = MemReader::new(vec![0, 1, 2, 3, 4, 5]); let mut r = LimitReader::new(r.by_ref(), 1); r.consume(2); - assert_eq!([], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), []); } #[test] @@ -380,7 +380,7 @@ mod test { let mut s = ZeroReader; let mut buf = vec![1, 2, 3]; assert_eq!(s.read(&mut buf), Ok(3)); - assert_eq!([0, 0, 0], buf); + assert_eq!(buf, [0, 0, 0]); } #[test] @@ -423,16 +423,16 @@ mod test { let rs = vec!(MemReader::new(vec!(0, 1)), MemReader::new(vec!()), MemReader::new(vec!(2, 3))); let mut r = ChainedReader::new(rs.into_iter()); - assert_eq!([0, 1, 2, 3], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1, 2, 3]); } #[test] fn test_tee_reader() { let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)), Vec::new()); - assert_eq!([0, 1, 2], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]); let (_, w) = r.into_inner(); - assert_eq!([0, 1, 2], w); + assert_eq!(w, [0, 1, 2]); } #[test] @@ -440,7 +440,7 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2, 3, 4)); let mut w = Vec::new(); copy(&mut r, &mut w).unwrap(); - assert_eq!([0, 1, 2, 3, 4], w); + assert_eq!(w, [0, 1, 2, 3, 4]); } #[test] diff --git a/src/libstd/old_path/posix.rs b/src/libstd/old_path/posix.rs index bbc1756bee6..67190de08c3 100644 --- a/src/libstd/old_path/posix.rs +++ b/src/libstd/old_path/posix.rs @@ -126,7 +126,7 @@ impl GenericPathUnsafe for Path { unsafe fn set_filename_unchecked(&mut self, filename: T) { let filename = filename.container_as_bytes(); match self.sepidx { - None if b".." == self.repr => { + None if self.repr == b".." => { let mut v = Vec::with_capacity(3 + filename.len()); v.push_all(dot_dot_static); v.push(SEP_BYTE); @@ -186,7 +186,7 @@ impl GenericPath for Path { fn dirname<'a>(&'a self) -> &'a [u8] { match self.sepidx { - None if b".." == self.repr => &self.repr, + None if self.repr == b".." => &self.repr, None => dot_static, Some(0) => &self.repr[..1], Some(idx) if &self.repr[idx+1..] == b".." => &self.repr, @@ -196,8 +196,7 @@ impl GenericPath for Path { fn filename<'a>(&'a self) -> Option<&'a [u8]> { match self.sepidx { - None if b"." == self.repr || - b".." == self.repr => None, + None if self.repr == b"." || self.repr == b".." => None, None => Some(&self.repr), Some(idx) if &self.repr[idx+1..] == b".." => None, Some(0) if self.repr[1..].is_empty() => None, @@ -207,13 +206,13 @@ impl GenericPath for Path { fn pop(&mut self) -> bool { match self.sepidx { - None if b"." == self.repr => false, + None if self.repr == b"." => false, None => { self.repr = vec![b'.']; self.sepidx = None; true } - Some(0) if b"/" == self.repr => false, + Some(0) if self.repr == b"/" => false, Some(idx) => { if idx == 0 { self.repr.truncate(idx+1); @@ -245,7 +244,7 @@ impl GenericPath for Path { } else { let mut ita = self.components(); let mut itb = other.components(); - if b"." == self.repr { + if self.repr == b"." { return match itb.next() { None => true, Some(b) => b != b".." diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index 5bd6591cfb0..1649934f4b1 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -226,13 +226,13 @@ mod test { fn test_move_iter() { let v = SmallVector::zero(); let v: Vec = v.into_iter().collect(); - assert_eq!(Vec::new(), v); + assert_eq!(v, Vec::new()); let v = SmallVector::one(1); - assert_eq!([1], v.into_iter().collect::>()); + assert_eq!(v.into_iter().collect::>(), [1]); let v = SmallVector::many(vec![1, 2, 3]); - assert_eq!([1, 2, 3], v.into_iter().collect::>()); + assert_eq!(v.into_iter().collect::>(), [1, 2, 3]); } #[test] diff --git a/src/test/run-fail/assert-eq-macro-panic.rs b/src/test/run-fail/assert-eq-macro-panic.rs index fd6d69efb4f..0b35062b186 100644 --- a/src/test/run-fail/assert-eq-macro-panic.rs +++ b/src/test/run-fail/assert-eq-macro-panic.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:assertion failed: `(left == right) && (right == left)` (left: `14`, right: `15`) +// error-pattern:assertion failed: `(left == right)` (left: `14`, right: `15`) fn main() { assert_eq!(14,15); From 608fff8582bba3ba777e3a1fc7c4ad2550bd7dcd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 31 Mar 2015 13:40:39 -0700 Subject: [PATCH 17/46] rustc: Remove old_orphan_check entirely --- src/librustc_typeck/coherence/orphan.rs | 30 ++++++++----------- src/libsyntax/feature_gate.rs | 17 ----------- .../deriving-encodable-decodable-box.rs | 2 +- ...riving-encodable-decodable-cell-refcell.rs | 2 +- src/test/run-pass/deriving-global.rs | 2 +- src/test/run-pass/issue-11881.rs | 2 +- src/test/run-pass/issue-14021.rs | 2 +- src/test/run-pass/issue-15734.rs | 2 +- src/test/run-pass/issue-3743.rs | 1 - 9 files changed, 19 insertions(+), 41 deletions(-) diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 7b76f3681c1..b450e6b398a 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -215,25 +215,21 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { match traits::orphan_check(self.tcx, def_id) { Ok(()) => { } Err(traits::OrphanCheckErr::NoLocalInputType) => { - if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") { - span_err!( - self.tcx.sess, item.span, E0117, - "the impl does not reference any \ - types defined in this crate; \ - only traits defined in the current crate can be \ - implemented for arbitrary types"); - return; - } + span_err!( + self.tcx.sess, item.span, E0117, + "the impl does not reference any \ + types defined in this crate; \ + only traits defined in the current crate can be \ + implemented for arbitrary types"); + return; } Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => { - if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") { - span_err!(self.tcx.sess, item.span, E0210, - "type parameter `{}` must be used as the type parameter for \ - some local type (e.g. `MyStruct`); only traits defined in \ - the current crate can be implemented for a type parameter", - param_ty.user_string(self.tcx)); - return; - } + span_err!(self.tcx.sess, item.span, E0210, + "type parameter `{}` must be used as the type parameter for \ + some local type (e.g. `MyStruct`); only traits defined in \ + the current crate can be implemented for a type parameter", + param_ty.user_string(self.tcx)); + return; } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 1b03a180720..7bad26f58f7 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -102,9 +102,6 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ // A way to temporarily opt out of opt in copy. This will *never* be accepted. ("opt_out_copy", "1.0.0", Removed), - // A way to temporarily opt out of the new orphan rules. This will *never* be accepted. - ("old_orphan_check", "1.0.0", Deprecated), - // OIBIT specific features ("optin_builtin_traits", "1.0.0", Active), @@ -277,9 +274,6 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ ("stable", Whitelisted), ("unstable", Whitelisted), - // FIXME: #19470 this shouldn't be needed forever - ("old_orphan_check", Whitelisted), - ("rustc_paren_sugar", Gated("unboxed_closures", "unboxed_closures are still evolving")), ("rustc_reflect_like", Gated("reflect", @@ -327,7 +321,6 @@ pub struct Features { pub allow_trace_macros: bool, pub allow_internal_unstable: bool, pub allow_custom_derive: bool, - pub old_orphan_check: bool, pub simd_ffi: bool, pub unmarked_api: bool, /// spans of #![feature] attrs for stable language features. for error reporting @@ -349,7 +342,6 @@ impl Features { allow_trace_macros: false, allow_internal_unstable: false, allow_custom_derive: false, - old_orphan_check: false, simd_ffi: false, unmarked_api: false, declared_stable_lang_features: Vec::new(), @@ -573,14 +565,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { }, _ => {} } - - if attr::contains_name(&i.attrs[..], - "old_orphan_check") { - self.gate_feature( - "old_orphan_check", - i.span, - "the new orphan check rules will eventually be strictly enforced"); - } } _ => {} @@ -737,7 +721,6 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, allow_trace_macros: cx.has_feature("trace_macros"), allow_internal_unstable: cx.has_feature("allow_internal_unstable"), allow_custom_derive: cx.has_feature("custom_derive"), - old_orphan_check: cx.has_feature("old_orphan_check"), simd_ffi: cx.has_feature("simd_ffi"), unmarked_api: cx.has_feature("unmarked_api"), declared_stable_lang_features: accepted_features, diff --git a/src/test/run-pass/deriving-encodable-decodable-box.rs b/src/test/run-pass/deriving-encodable-decodable-box.rs index 17f4d93e24c..6ccedb0ad98 100644 --- a/src/test/run-pass/deriving-encodable-decodable-box.rs +++ b/src/test/run-pass/deriving-encodable-decodable-box.rs @@ -12,7 +12,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -#![feature(old_orphan_check, rustc_private)] +#![feature(rustc_private)] extern crate serialize; diff --git a/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs index d116c2dfc2a..d216062bb2d 100644 --- a/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs +++ b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs @@ -13,7 +13,7 @@ // pretty-expanded FIXME #23616 -#![feature(old_orphan_check, rustc_private)] +#![feature(rustc_private)] extern crate serialize; diff --git a/src/test/run-pass/deriving-global.rs b/src/test/run-pass/deriving-global.rs index 2ca34e91b62..105d421b404 100644 --- a/src/test/run-pass/deriving-global.rs +++ b/src/test/run-pass/deriving-global.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(old_orphan_check, rand, rustc_private)] +#![feature(rand, rustc_private)] extern crate serialize; extern crate rand; diff --git a/src/test/run-pass/issue-11881.rs b/src/test/run-pass/issue-11881.rs index 811926826dd..35c25b33a97 100644 --- a/src/test/run-pass/issue-11881.rs +++ b/src/test/run-pass/issue-11881.rs @@ -10,7 +10,7 @@ // pretty-expanded FIXME #23616 -#![feature(old_orphan_check, rustc_private, old_io)] +#![feature(rustc_private, old_io)] extern crate rbml; extern crate serialize; diff --git a/src/test/run-pass/issue-14021.rs b/src/test/run-pass/issue-14021.rs index e773f03f212..907967d115d 100644 --- a/src/test/run-pass/issue-14021.rs +++ b/src/test/run-pass/issue-14021.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(old_orphan_check, rustc_private)] +#![feature(rustc_private)] extern crate serialize; diff --git a/src/test/run-pass/issue-15734.rs b/src/test/run-pass/issue-15734.rs index d058cb73711..67ce6a1c44f 100644 --- a/src/test/run-pass/issue-15734.rs +++ b/src/test/run-pass/issue-15734.rs @@ -13,7 +13,7 @@ // pretty-expanded FIXME #23616 -#![feature(old_orphan_check, core)] +#![feature(core)] use std::ops::Index; diff --git a/src/test/run-pass/issue-3743.rs b/src/test/run-pass/issue-3743.rs index 03699ff8d60..7f66b6b25b8 100644 --- a/src/test/run-pass/issue-3743.rs +++ b/src/test/run-pass/issue-3743.rs @@ -10,7 +10,6 @@ // If `Mul` used an associated type for its output, this test would // work more smoothly. -#![feature(old_orphan_check)] use std::ops::Mul; From e48c7c61eb241fadc0835c7bdd041e042c43f622 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 31 Mar 2015 17:44:45 -0400 Subject: [PATCH 18/46] Fix spelling --- src/doc/trpl/ownership.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/ownership.md b/src/doc/trpl/ownership.md index f4b5495ba63..223085cc40b 100644 --- a/src/doc/trpl/ownership.md +++ b/src/doc/trpl/ownership.md @@ -477,7 +477,7 @@ forbidden in item signatures to allow reasoning about the types just based in the item signature alone. However, for ergonomic reasons a very restricted secondary inference algorithm called “lifetime elision” applies in function signatures. It infers only based on the signature components themselves and not -based on the body of the function, only infers lifetime paramters, and does +based on the body of the function, only infers lifetime parameters, and does this with only three easily memorizable and unambiguous rules. This makes lifetime elision a shorthand for writing an item signature, while not hiding away the actual types involved as full local inference would if applied to it. From 71982aa65725a2e630b3abdbb5f48e1abf1acf91 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 31 Mar 2015 14:41:59 -0700 Subject: [PATCH 19/46] std: Add a process::exit function This commit is an implementation of [RFC #1011][rfc] which adds an `exit` function to the standard library for immediately terminating the current process with a specified exit code. [rfc]: https://github.com/rust-lang/rfcs/pull/1011 --- src/libstd/process.rs | 16 ++++++++++++++++ src/libstd/sys/unix/os.rs | 4 ++++ src/libstd/sys/windows/c.rs | 1 + src/libstd/sys/windows/os.rs | 4 ++++ src/test/run-pass/process-exit.rs | 31 +++++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+) create mode 100644 src/test/run-pass/process-exit.rs diff --git a/src/libstd/process.rs b/src/libstd/process.rs index b4bd513e8f0..5f29275df1f 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -527,6 +527,22 @@ impl Child { } } +/// Terminates the current process with the specified exit code. +/// +/// This function will never return and will immediately terminate the current +/// process. The exit code is passed through to the underlying OS and will be +/// available for consumption by another process. +/// +/// Note that because this function never returns, and that it terminates the +/// process, no destructors on the current stack or any other thread's stack +/// will be run. If a clean shutdown is needed it is recommended to only call +/// this function at a known point where there are no more destructors left +/// to run. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn exit(code: i32) -> ! { + ::sys::os::exit(code) +} + #[cfg(test)] mod tests { use io::ErrorKind; diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index fab443feebd..2ff7eba5732 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -505,3 +505,7 @@ pub fn home_dir() -> Option { } } } + +pub fn exit(code: i32) -> ! { + unsafe { libc::exit(code as c_int) } +} diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index b9be4eb6bf5..b930e35c064 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -433,6 +433,7 @@ extern "system" { TokenHandle: *mut libc::HANDLE) -> libc::BOOL; pub fn GetCurrentProcess() -> libc::HANDLE; pub fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; + pub fn ExitProcess(uExitCode: libc::UINT) -> !; } #[link(name = "userenv")] diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 167db1e8ac2..cbbce7f8f0a 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -379,3 +379,7 @@ pub fn home_dir() -> Option { }, super::os2path).ok() }) } + +pub fn exit(code: i32) -> ! { + unsafe { libc::ExitProcess(code as libc::UINT) } +} diff --git a/src/test/run-pass/process-exit.rs b/src/test/run-pass/process-exit.rs new file mode 100644 index 00000000000..9ef66ff2d71 --- /dev/null +++ b/src/test/run-pass/process-exit.rs @@ -0,0 +1,31 @@ +// 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::process::{self, Command, Stdio}; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "child" { + child(); + } else { + parent(); + } +} + +fn parent() { + let args: Vec = env::args().collect(); + let status = Command::new(&args[0]).arg("child").status().unwrap(); + assert_eq!(status.code(), Some(2)); +} + +fn child() -> i32 { + process::exit(2); +} From b9ab5fe7c29d0675ae03c87f1454fb52b36c18b4 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Tue, 31 Mar 2015 13:47:57 -0700 Subject: [PATCH 20/46] Stabilize a few remaining stragglers * The `io::Seek` trait, and `SeekFrom` enum. * The `Iterator::{partition, unsip}` methods. * The `Vec::into_boxed_slice` method. * The `LinkedList::append` method. * The `{or_insert, or_insert_with` methods in the `Entry` APIs. --- src/libcollections/btree/map.rs | 6 ++---- src/libcollections/linked_list.rs | 1 + src/libcollections/vec.rs | 2 +- src/libcore/iter.rs | 5 ++--- src/libstd/collections/hash/map.rs | 6 ++---- src/libstd/io/mod.rs | 10 ++++++---- 6 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index e1d007f0ac4..adfb284dabe 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -1134,8 +1134,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { } } - #[unstable(feature = "collections", - reason = "matches entry v3 specification, waiting for dust to settle")] + #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. pub fn or_insert(self, default: V) -> &'a mut V { @@ -1145,8 +1144,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { } } - #[unstable(feature = "collections", - reason = "matches entry v3 specification, waiting for dust to settle")] + #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the result of the default function if empty, /// and returns a mutable reference to the value in the entry. pub fn or_insert_with V>(self, default: F) -> &'a mut V { diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 52da4902b75..97512cbe7cc 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -252,6 +252,7 @@ impl LinkedList { /// } /// println!("{}", b.len()); // prints 0 /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn append(&mut self, other: &mut LinkedList) { match self.list_tail.resolve() { None => { diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 3595288a6c9..7fdf5b4151d 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -389,7 +389,7 @@ impl Vec { /// Note that this will drop any excess capacity. Calling this and /// converting back to a vector with `into_vec()` is equivalent to calling /// `shrink_to_fit()`. - #[unstable(feature = "collections")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_boxed_slice(mut self) -> Box<[T]> { self.shrink_to_fit(); unsafe { diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 44d48f9f4bf..18e1b9dde48 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -553,8 +553,7 @@ pub trait Iterator { /// assert_eq!(even, [2, 4]); /// assert_eq!(odd, [1, 3]); /// ``` - #[unstable(feature = "core", - reason = "recently added as part of collections reform")] + #[stable(feature = "rust1", since = "1.0.0")] fn partition(self, mut f: F) -> (B, B) where Self: Sized, B: Default + Extend, @@ -930,7 +929,7 @@ pub trait Iterator { /// assert_eq!([1, 3], left); /// assert_eq!([2, 4], right); /// ``` - #[unstable(feature = "core", reason = "recent addition")] + #[stable(feature = "rust1", since = "1.0.0")] fn unzip(self) -> (FromA, FromB) where FromA: Default + Extend, FromB: Default + Extend, diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index bc0f109de15..a636c1a812d 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1482,8 +1482,7 @@ impl<'a, K, V> Entry<'a, K, V> { } } - #[unstable(feature = "collections", - reason = "matches entry v3 specification, waiting for dust to settle")] + #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. pub fn or_insert(self, default: V) -> &'a mut V { @@ -1493,8 +1492,7 @@ impl<'a, K, V> Entry<'a, K, V> { } } - #[unstable(feature = "collections", - reason = "matches entry v3 specification, waiting for dust to settle")] + #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the result of the default function if empty, /// and returns a mutable reference to the value in the entry. pub fn or_insert_with V>(self, default: F) -> &'a mut V { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 830a88bb6c9..0e379b5ab43 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -441,9 +441,7 @@ pub trait Write { /// /// The stream typically has a fixed size, allowing seeking relative to either /// end or the current offset. -#[unstable(feature = "io", reason = "the central `seek` method may be split \ - into multiple methods instead of taking \ - an enum as an argument")] +#[stable(feature = "rust1", since = "1.0.0")] pub trait Seek { /// Seek to an offset, in bytes, in a stream /// @@ -459,14 +457,16 @@ pub trait Seek { /// # Errors /// /// Seeking to a negative offset is considered an error + #[stable(feature = "rust1", since = "1.0.0")] fn seek(&mut self, pos: SeekFrom) -> Result; } /// Enumeration of possible methods to seek within an I/O object. #[derive(Copy, PartialEq, Eq, Clone, Debug)] -#[unstable(feature = "io", reason = "awaiting the stability of Seek")] +#[stable(feature = "rust1", since = "1.0.0")] pub enum SeekFrom { /// Set the offset to the provided number of bytes. + #[stable(feature = "rust1", since = "1.0.0")] Start(u64), /// Set the offset to the size of this object plus the specified number of @@ -474,6 +474,7 @@ pub enum SeekFrom { /// /// It is possible to seek beyond the end of an object, but is an error to /// seek before byte 0. + #[stable(feature = "rust1", since = "1.0.0")] End(i64), /// Set the offset to the current position plus the specified number of @@ -481,6 +482,7 @@ pub enum SeekFrom { /// /// It is possible to seek beyond the end of an object, but is an error to /// seek before byte 0. + #[stable(feature = "rust1", since = "1.0.0")] Current(i64), } From d4a2c941809f303b97d153e06ba07e95cd245f88 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 30 Mar 2015 11:00:05 -0700 Subject: [PATCH 21/46] std: Clean out #[deprecated] APIs This commit cleans out a large amount of deprecated APIs from the standard library and some of the facade crates as well, updating all users in the compiler and in tests as it goes along. --- src/doc/reference.md | 4 - src/doc/trpl/iterators.md | 13 +- src/libcollections/bit.rs | 12 +- src/libcollections/borrow.rs | 20 - src/libcollections/lib.rs | 24 - src/libcollections/linked_list.rs | 6 +- src/libcollections/slice.rs | 71 - src/libcollections/str.rs | 87 +- src/libcollections/string.rs | 5 - src/libcollections/vec.rs | 5 - src/libcollections/vec_deque.rs | 14 +- src/libcollectionstest/bit/set.rs | 3 +- src/libcollectionstest/fmt.rs | 2 +- src/libcollectionstest/lib.rs | 2 +- src/libcollectionstest/slice.rs | 4 +- src/libcollectionstest/str.rs | 109 +- src/libcollectionstest/string.rs | 8 +- src/libcollectionstest/vec_deque.rs | 3 +- src/libcore/atomic.rs | 141 -- src/libcore/cell.rs | 34 - src/libcore/error.rs | 26 +- src/libcore/finally.rs | 111 - src/libcore/hash/sip.rs | 5 - src/libcore/iter.rs | 166 +- src/libcore/lib.rs | 1 - src/libcore/macros.rs | 2 +- src/libcore/marker.rs | 36 - src/libcore/option.rs | 21 - src/libcore/prelude.rs | 11 +- src/libcore/ptr.rs | 15 - src/libcore/raw.rs | 13 - src/libcore/slice.rs | 58 - src/libcore/str/mod.rs | 98 - src/libcore/str/pattern.rs | 170 +- src/libcoretest/cell.rs | 13 +- src/libcoretest/finally.rs | 62 - src/libcoretest/iter.rs | 14 +- src/libcoretest/lib.rs | 1 - src/libcoretest/str.rs | 18 +- src/librand/chacha.rs | 2 +- src/librustc/util/common.rs | 5 +- src/librustc_back/fs.rs | 5 +- src/librustc_back/lib.rs | 2 - src/librustc_back/sha2.rs | 6 +- src/librustc_back/tempdir.rs | 8 +- src/librustc_llvm/archive_ro.rs | 5 +- src/librustc_llvm/lib.rs | 2 +- src/librustdoc/flock.rs | 10 +- src/libstd/collections/hash/table.rs | 2 +- src/libstd/dynamic_lib.rs | 2 +- src/libstd/env.rs | 24 +- src/libstd/ffi/c_str.rs | 95 - src/libstd/ffi/mod.rs | 11 +- src/libstd/ffi/os_str.rs | 25 +- src/libstd/{fs/mod.rs => fs.rs} | 9 +- src/libstd/fs/tempdir.rs | 127 -- src/libstd/io/cursor.rs | 8 +- src/libstd/io/error.rs | 22 - src/libstd/lib.rs | 2 - src/libstd/net/tcp.rs | 18 +- src/libstd/net/udp.rs | 9 +- src/libstd/old_io/fs.rs | 5 +- src/libstd/old_io/mem.rs | 4 +- src/libstd/old_io/mod.rs | 2 +- src/libstd/old_io/pipe.rs | 6 +- src/libstd/old_io/process.rs | 36 +- src/libstd/old_io/tempfile.rs | 6 +- src/libstd/old_io/test.rs | 2 +- src/libstd/old_path/mod.rs | 5 +- src/libstd/old_path/posix.rs | 13 +- src/libstd/old_path/windows.rs | 2 - src/libstd/os.rs | 1821 +---------------- src/libstd/path.rs | 2 +- src/libstd/prelude/v1.rs | 9 +- src/libstd/process.rs | 52 +- src/libstd/rand/os.rs | 33 +- src/libstd/rt/args.rs | 14 +- src/libstd/sync/mod.rs | 3 - src/libstd/sync/poison.rs | 6 - src/libstd/sync/task_pool.rs | 217 -- src/libstd/sys/unix/backtrace.rs | 1 - src/libstd/sys/unix/fs.rs | 4 +- src/libstd/sys/unix/fs2.rs | 2 +- src/libstd/sys/unix/helper_signal.rs | 6 +- src/libstd/sys/unix/os.rs | 13 +- src/libstd/sys/unix/process.rs | 6 +- src/libstd/sys/unix/timer.rs | 5 +- src/libstd/sys/windows/os.rs | 13 +- src/libstd/sys/windows/process.rs | 16 +- src/libstd/thread/local.rs | 6 - src/libstd/thread/mod.rs | 104 +- src/libtest/lib.rs | 4 +- src/test/bench/shootout-binarytrees.rs | 5 +- src/test/bench/shootout-fannkuch-redux.rs | 6 +- src/test/bench/shootout-k-nucleotide-pipes.rs | 2 +- src/test/bench/shootout-spectralnorm.rs | 4 +- .../compile-fail/dropck_arr_cycle_checked.rs | 4 +- .../dropck_tarena_cycle_checked.rs | 4 +- .../compile-fail/dropck_vec_cycle_checked.rs | 4 +- src/test/compile-fail/estr-subtyping.rs | 2 +- src/test/compile-fail/issue-13058.rs | 4 +- src/test/compile-fail/issue-17651.rs | 2 +- ...me-inference-give-expl-lifetime-param-2.rs | 4 +- .../variance-deprecated-markers.rs | 35 - .../vec-must-not-hide-type-from-dropck.rs | 4 +- .../vec_refs_data_with_early_death.rs | 2 +- src/test/run-fail/rt-set-exit-status-panic.rs | 6 +- .../run-fail/rt-set-exit-status-panic2.rs | 6 +- src/test/run-fail/rt-set-exit-status.rs | 6 +- src/test/run-make/link-path-order/main.rs | 4 +- .../run-make/unicode-input/span_length.rs | 4 +- src/test/run-pass-fulldeps/compiler-calls.rs | 2 +- .../create-dir-all-bare.rs | 7 +- .../rename-directory.rs | 7 +- src/test/run-pass/backtrace.rs | 4 +- src/test/run-pass/capturing-logging.rs | 4 +- src/test/run-pass/child-outlives-parent.rs | 4 +- src/test/run-pass/clone-with-exterior.rs | 4 +- src/test/run-pass/comm.rs | 4 +- src/test/run-pass/core-run-destroy.rs | 4 +- .../run-pass/drop-with-type-ascription-2.rs | 2 +- src/test/run-pass/extern-call-scrub.rs | 4 +- src/test/run-pass/hashmap-memory.rs | 4 +- src/test/run-pass/init-large-type.rs | 4 +- src/test/run-pass/issue-13304.rs | 4 +- src/test/run-pass/issue-13494.rs | 5 +- src/test/run-pass/issue-14456.rs | 6 +- src/test/run-pass/issue-17351.rs | 4 + src/test/run-pass/issue-20454.rs | 6 +- src/test/run-pass/issue-2718.rs | 4 +- src/test/run-pass/issue-3609.rs | 4 +- src/test/run-pass/issue-8827.rs | 6 +- src/test/run-pass/issue-9396.rs | 4 +- src/test/run-pass/ivec-tag.rs | 4 +- .../kindck-implicit-close-over-mut-var.rs | 8 +- .../macro-with-braces-in-expr-position.rs | 4 +- ...o-traits-distinguished-via-where-clause.rs | 2 +- .../moves-based-on-type-capture-clause.rs | 4 +- src/test/run-pass/option-ext.rs | 2 +- .../out-of-stack-new-thread-no-split.rs | 4 +- src/test/run-pass/running-with-no-runtime.rs | 4 +- src/test/run-pass/rust-log-filter.rs | 4 +- .../run-pass/send-is-not-static-par-for.rs | 4 +- src/test/run-pass/send-resource.rs | 4 +- src/test/run-pass/stat.rs | 36 - .../run-pass/syntax-extension-source-utils.rs | 6 +- src/test/run-pass/task-comm-0.rs | 4 +- src/test/run-pass/task-comm-1.rs | 4 +- src/test/run-pass/task-comm-10.rs | 6 +- src/test/run-pass/task-comm-11.rs | 4 +- src/test/run-pass/task-comm-12.rs | 6 +- src/test/run-pass/task-comm-13.rs | 4 +- src/test/run-pass/task-comm-14.rs | 4 +- src/test/run-pass/task-comm-15.rs | 4 +- src/test/run-pass/task-comm-17.rs | 4 +- src/test/run-pass/task-comm-3.rs | 4 +- src/test/run-pass/task-comm-7.rs | 10 +- src/test/run-pass/task-comm-9.rs | 4 +- src/test/run-pass/task-life-0.rs | 4 +- src/test/run-pass/task-spawn-move-and-copy.rs | 4 +- src/test/run-pass/tcp-accept-stress.rs | 6 +- src/test/run-pass/tcp-connect-timeouts.rs | 4 +- src/test/run-pass/tempfile.rs | 8 +- src/test/run-pass/threads.rs | 4 +- src/test/run-pass/trait-bounds-in-arc.rs | 8 +- src/test/run-pass/variadic-ffi.rs | 4 +- 166 files changed, 602 insertions(+), 4014 deletions(-) delete mode 100644 src/libcore/finally.rs delete mode 100644 src/libcoretest/finally.rs rename src/libstd/{fs/mod.rs => fs.rs} (99%) delete mode 100644 src/libstd/fs/tempdir.rs delete mode 100644 src/libstd/sync/task_pool.rs delete mode 100644 src/test/compile-fail/variance-deprecated-markers.rs rename src/test/{run-pass => run-pass-fulldeps}/create-dir-all-bare.rs (86%) rename src/test/{run-pass => run-pass-fulldeps}/rename-directory.rs (90%) delete mode 100644 src/test/run-pass/stat.rs diff --git a/src/doc/reference.md b/src/doc/reference.md index 0bc4414999d..b3d5ad3b55d 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -977,7 +977,6 @@ An example of `use` declarations: ``` # #![feature(core)] -use std::iter::range_step; use std::option::Option::{Some, None}; use std::collections::hash_map::{self, HashMap}; @@ -985,9 +984,6 @@ fn foo(_: T){} fn bar(map1: HashMap, map2: hash_map::HashMap){} fn main() { - // Equivalent to 'std::iter::range_step(0, 10, 2);' - range_step(0, 10, 2); - // Equivalent to 'foo(vec![std::option::Option::Some(1.0f64), // std::option::Option::None]);' foo(vec![Some(1.0f64), None]); diff --git a/src/doc/trpl/iterators.md b/src/doc/trpl/iterators.md index 8d7b1c3bd83..55776bee3b5 100644 --- a/src/doc/trpl/iterators.md +++ b/src/doc/trpl/iterators.md @@ -243,11 +243,12 @@ for num in nums.iter() { ``` These two basic iterators should serve you well. There are some more -advanced iterators, including ones that are infinite. Like `count`: +advanced iterators, including ones that are infinite. Like using range syntax +and `step_by`: ```rust -# #![feature(core)] -std::iter::count(1, 5); +# #![feature(step_by)] +(1..).step_by(5); ``` This iterator counts up from one, adding five each time. It will give @@ -292,11 +293,11 @@ just use `for` instead. There are tons of interesting iterator adapters. `take(n)` will return an iterator over the next `n` elements of the original iterator, note that this has no side effect on the original iterator. Let's try it out with our infinite -iterator from before, `count()`: +iterator from before: ```rust -# #![feature(core)] -for i in std::iter::count(1, 5).take(5) { +# #![feature(step_by)] +for i in (1..).step_by(5).take(5) { println!("{}", i); } ``` diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 3ed8ca2bea9..8874ac6eb87 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -38,7 +38,7 @@ //! [sieve]: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes //! //! ``` -//! # #![feature(collections, core)] +//! # #![feature(collections, core, step_by)] //! use std::collections::{BitSet, BitVec}; //! use std::num::Float; //! use std::iter; @@ -60,7 +60,7 @@ //! if bv[i] { //! // Mark all multiples of i as non-prime (any multiples below i * i //! // will have been marked as non-prime previously) -//! for j in iter::range_step(i * i, max_prime, i) { bv.set(j, false) } +//! for j in (i * i..max_prime).step_by(i) { bv.set(j, false) } //! } //! } //! BitSet::from_bit_vec(bv) @@ -1264,14 +1264,6 @@ impl BitSet { BitSet { bit_vec: bit_vec } } - /// Deprecated: use `from_bit_vec`. - #[inline] - #[deprecated(since = "1.0.0", reason = "renamed to from_bit_vec")] - #[unstable(feature = "collections")] - pub fn from_bitv(bit_vec: BitVec) -> BitSet { - BitSet { bit_vec: bit_vec } - } - /// Returns the capacity in bits for this bit vector. Inserting any /// element less than this amount will not trigger a resizing. /// diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 88d59f699d1..b955e9b71e4 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -192,26 +192,6 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { Owned(owned) => owned } } - - /// Returns true if this `Cow` wraps a borrowed value - #[deprecated(since = "1.0.0", reason = "match on the enum instead")] - #[unstable(feature = "std_misc")] - pub fn is_borrowed(&self) -> bool { - match *self { - Borrowed(_) => true, - _ => false, - } - } - - /// Returns true if this `Cow` wraps an owned value - #[deprecated(since = "1.0.0", reason = "match on the enum instead")] - #[unstable(feature = "std_misc")] - pub fn is_owned(&self) -> bool { - match *self { - Owned(_) => true, - _ => false, - } - } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index c769b3df37f..bdc2cf96734 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -68,22 +68,6 @@ pub use string::String; pub use vec::Vec; pub use vec_map::VecMap; -#[deprecated(since = "1.0.0", reason = "renamed to vec_deque")] -#[unstable(feature = "collections")] -pub use vec_deque as ring_buf; - -#[deprecated(since = "1.0.0", reason = "renamed to linked_list")] -#[unstable(feature = "collections")] -pub use linked_list as dlist; - -#[deprecated(since = "1.0.0", reason = "renamed to bit_vec")] -#[unstable(feature = "collections")] -pub use bit_vec as bitv; - -#[deprecated(since = "1.0.0", reason = "renamed to bit_set")] -#[unstable(feature = "collections")] -pub use bit_set as bitv_set; - // Needed for the vec! macro pub use alloc::boxed; @@ -108,10 +92,6 @@ pub mod vec_map; reason = "RFC 509")] pub mod bit_vec { pub use bit::{BitVec, Iter}; - - #[deprecated(since = "1.0.0", reason = "renamed to BitVec")] - #[unstable(feature = "collections")] - pub use bit::BitVec as Bitv; } #[unstable(feature = "collections", @@ -119,10 +99,6 @@ pub mod bit_vec { pub mod bit_set { pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference}; pub use bit::SetIter as Iter; - - #[deprecated(since = "1.0.0", reason = "renamed to BitSet")] - #[unstable(feature = "collections")] - pub use bit::BitSet as BitvSet; } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 52da4902b75..392dc7346c6 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -32,10 +32,6 @@ use core::iter::{self, FromIterator, IntoIterator}; use core::mem; use core::ptr; -#[deprecated(since = "1.0.0", reason = "renamed to LinkedList")] -#[unstable(feature = "collections")] -pub use LinkedList as DList; - /// A doubly-linked list. #[stable(feature = "rust1", since = "1.0.0")] pub struct LinkedList { @@ -844,7 +840,7 @@ impl ExactSizeIterator for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for LinkedList { fn from_iter>(iter: T) -> LinkedList { - let mut ret = DList::new(); + let mut ret = LinkedList::new(); ret.extend(iter); ret } diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 050997f2dd3..d0e86f56d26 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -107,7 +107,6 @@ pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split}; pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; pub use core::slice::{bytes, mut_ref_slice, ref_slice}; pub use core::slice::{from_raw_parts, from_raw_parts_mut}; -pub use core::slice::{from_raw_buf, from_raw_mut_buf}; //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods @@ -281,33 +280,6 @@ impl [T] { cmp::min(self.len(), end-start) } - /// Deprecated: use `&s[start .. end]` notation instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &s[start .. end] instead")] - #[inline] - pub fn slice(&self, start: usize, end: usize) -> &[T] { - &self[start .. end] - } - - /// Deprecated: use `&s[start..]` notation instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &s[start..] instead")] - #[inline] - pub fn slice_from(&self, start: usize) -> &[T] { - &self[start ..] - } - - /// Deprecated: use `&s[..end]` notation instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &s[..end] instead")] - #[inline] - pub fn slice_to(&self, end: usize) -> &[T] { - &self[.. end] - } - /// Divides one slice into two at an index. /// /// The first will contain all indices from `[0, mid)` (excluding @@ -611,42 +583,6 @@ impl [T] { core_slice::SliceExt::get_mut(self, index) } - /// Deprecated: use `&mut s[..]` instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")] - #[allow(deprecated)] - pub fn as_mut_slice(&mut self) -> &mut [T] { - core_slice::SliceExt::as_mut_slice(self) - } - - /// Deprecated: use `&mut s[start .. end]` instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &mut s[start .. end] instead")] - #[inline] - pub fn slice_mut(&mut self, start: usize, end: usize) -> &mut [T] { - &mut self[start .. end] - } - - /// Deprecated: use `&mut s[start ..]` instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &mut s[start ..] instead")] - #[inline] - pub fn slice_from_mut(&mut self, start: usize) -> &mut [T] { - &mut self[start ..] - } - - /// Deprecated: use `&mut s[.. end]` instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &mut s[.. end] instead")] - #[inline] - pub fn slice_to_mut(&mut self, end: usize) -> &mut [T] { - &mut self[.. end] - } - /// Returns an iterator that allows modifying each value #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -937,13 +873,6 @@ impl [T] { core_slice::SliceExt::binary_search(self, x) } - /// Deprecated: use `binary_search` instead. - #[unstable(feature = "collections")] - #[deprecated(since = "1.0.0", reason = "use binary_search instead")] - pub fn binary_search_elem(&self, x: &T) -> Result where T: Ord { - self.binary_search(x) - } - /// Mutates the slice to the next lexicographic permutation. /// /// Returns `true` if successful and `false` if the slice is at the diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 9ddf8988f1e..35ec8af0a45 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -70,11 +70,11 @@ use vec::Vec; use slice::SliceConcatExt; pub use core::str::{FromStr, Utf8Error, Str}; -pub use core::str::{Lines, LinesAny, MatchIndices, SplitStr, CharRange}; +pub use core::str::{Lines, LinesAny, MatchIndices, CharRange}; pub use core::str::{Split, SplitTerminator, SplitN}; pub use core::str::{RSplit, RSplitN}; -pub use core::str::{from_utf8, CharEq, Chars, CharIndices, Bytes}; -pub use core::str::{from_utf8_unchecked, from_c_str, ParseBoolError}; +pub use core::str::{from_utf8, Chars, CharIndices, Bytes}; +pub use core::str::{from_utf8_unchecked, ParseBoolError}; pub use unicode::str::{Words, Graphemes, GraphemeIndices}; pub use core::str::Pattern; pub use core::str::{Searcher, ReverseSearcher, DoubleEndedSearcher, SearchStep}; @@ -536,22 +536,6 @@ impl str { core_str::StrExt::contains(&self[..], pat) } - /// Returns `true` if `self` contains a `char`. - /// - /// # Examples - /// - /// ``` - /// # #![feature(collections)] - /// assert!("hello".contains_char('e')); - /// - /// assert!(!"hello".contains_char('z')); - /// ``` - #[unstable(feature = "collections")] - #[deprecated(since = "1.0.0", reason = "use `contains()` with a char")] - pub fn contains_char<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { - core_str::StrExt::contains_char(&self[..], pat) - } - /// An iterator over the codepoints of `self`. /// /// # Examples @@ -778,25 +762,6 @@ impl str { core_str::StrExt::match_indices(&self[..], pat) } - /// An iterator over the substrings of `self` separated by a `&str`. - /// - /// # Examples - /// - /// ``` - /// # #![feature(collections)] - /// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect(); - /// assert_eq!(v, ["", "XXX", "YYY", ""]); - /// - /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect(); - /// assert_eq!(v, ["1", "", "2"]); - /// ``` - #[unstable(feature = "collections")] - #[deprecated(since = "1.0.0", reason = "use `split()` with a `&str`")] - #[allow(deprecated) /* for SplitStr */] - pub fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P> { - core_str::StrExt::split_str(&self[..], pat) - } - /// An iterator over the lines of a string, separated by `\n`. /// /// This does not include the empty string after a trailing `\n`. @@ -848,31 +813,6 @@ impl str { pub fn lines_any(&self) -> LinesAny { core_str::StrExt::lines_any(&self[..]) } - - /// Deprecated: use `s[a .. b]` instead. - #[unstable(feature = "collections", - reason = "use slice notation [a..b] instead")] - #[deprecated(since = "1.0.0", reason = "use slice notation [a..b] instead")] - pub fn slice(&self, begin: usize, end: usize) -> &str { - &self[begin..end] - } - - /// Deprecated: use `s[a..]` instead. - #[unstable(feature = "collections", - reason = "use slice notation [a..b] instead")] - #[deprecated(since = "1.0.0", reason = "use slice notation [a..] instead")] - pub fn slice_from(&self, begin: usize) -> &str { - &self[begin..] - } - - /// Deprecated: use `s[..a]` instead. - #[unstable(feature = "collections", - reason = "use slice notation [a..b] instead")] - #[deprecated(since = "1.0.0", reason = "use slice notation [..a] instead")] - pub fn slice_to(&self, end: usize) -> &str { - &self[..end] - } - /// Returns a slice of the string from the character range [`begin`..`end`). /// /// That is, start at the `begin`-th code point of the string and continue @@ -1306,27 +1246,6 @@ impl str { core_str::StrExt::rfind(&self[..], pat) } - /// Returns the byte index of the first matching substring if it exists. - /// - /// Returns `None` if it doesn't exist. - /// - /// The pattern can be a simple `&str`, or a closure that determines the split. - /// - /// # Examples - /// - /// ``` - /// # #![feature(collections)] - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.find_str("老虎 L"), Some(6)); - /// assert_eq!(s.find_str("muffin man"), None); - /// ``` - #[unstable(feature = "collections")] - #[deprecated(since = "1.0.0", reason = "use `find()` with a `&str`")] - pub fn find_str<'a, P: Pattern<'a>>(&'a self, needle: P) -> Option { - core_str::StrExt::find_str(&self[..], needle) - } - /// Retrieves the first character from a `&str` and returns it. /// /// This does not allocate a new string; instead, it returns a slice that points one character diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index dbf214a712b..7ae5c6b5e66 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1072,11 +1072,6 @@ impl<'a> Str for Cow<'a, str> { } } -/// A clone-on-write string -#[deprecated(since = "1.0.0", reason = "use Cow<'a, str> instead")] -#[stable(feature = "rust1", since = "1.0.0")] -pub type CowString<'a> = Cow<'a, str>; - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Write for String { #[inline] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 3595288a6c9..288cfc77d89 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1679,11 +1679,6 @@ impl<'a> From<&'a str> for Vec { // Clone-on-write //////////////////////////////////////////////////////////////////////////////// -/// A clone-on-write vector -#[deprecated(since = "1.0.0", reason = "use Cow<'a, [T]> instead")] -#[unstable(feature = "collections")] -pub type CowVec<'a, T> = Cow<'a, [T]>; - #[unstable(feature = "collections")] impl<'a, T> FromIterator for Cow<'a, [T]> where T: Clone { fn from_iter>(it: I) -> Cow<'a, [T]> { diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 392e5092e3b..99a19b2a00b 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -36,10 +36,6 @@ use core::cmp; use alloc::heap; -#[deprecated(since = "1.0.0", reason = "renamed to VecDeque")] -#[unstable(feature = "collections")] -pub use VecDeque as RingBuf; - const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 const MINIMUM_CAPACITY: usize = 1; // 2 - 1 @@ -1902,7 +1898,7 @@ mod test { // len is the length *after* insertion for len in 1..cap { // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); + let expected = (0..).take(len).collect(); for tail_pos in 0..cap { for to_insert in 0..len { tester.tail = tail_pos; @@ -1935,7 +1931,7 @@ mod test { // len is the length *after* removal for len in 0..cap - 1 { // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); + let expected = (0..).take(len).collect(); for tail_pos in 0..cap { for to_remove in 0..len + 1 { tester.tail = tail_pos; @@ -1973,7 +1969,7 @@ mod test { for len in 0..cap + 1 { // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); + let expected = (0..).take(len).collect(); for tail_pos in 0..max_cap + 1 { tester.tail = tail_pos; tester.head = tail_pos; @@ -2006,9 +2002,9 @@ mod test { // index to split at for at in 0..len + 1 { // 0, 1, 2, .., at - 1 (may be empty) - let expected_self = iter::count(0, 1).take(at).collect(); + let expected_self = (0..).take(at).collect(); // at, at + 1, .., len - 1 (may be empty) - let expected_other = iter::count(at, 1).take(len - at).collect(); + let expected_other = (at..).take(len - at).collect(); for tail_pos in 0..cap { tester.tail = tail_pos; diff --git a/src/libcollectionstest/bit/set.rs b/src/libcollectionstest/bit/set.rs index 4b4995d5fa7..19ea25ee345 100644 --- a/src/libcollectionstest/bit/set.rs +++ b/src/libcollectionstest/bit/set.rs @@ -10,7 +10,6 @@ use std::cmp::Ordering::{Equal, Greater, Less}; use std::collections::{BitSet, BitVec}; -use std::iter::range_step; #[test] fn test_bit_set_show() { @@ -42,7 +41,7 @@ fn test_bit_set_iterator() { assert_eq!(idxs, [0, 2, 3]); let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect(); - let real: Vec<_> = range_step(0, 10000, 2).collect(); + let real: Vec<_> = (0..10000).step_by(2).collect(); let idxs: Vec<_> = long.iter().collect(); assert_eq!(idxs, real); diff --git a/src/libcollectionstest/fmt.rs b/src/libcollectionstest/fmt.rs index 9a9aa71b58b..70e21c65a18 100644 --- a/src/libcollectionstest/fmt.rs +++ b/src/libcollectionstest/fmt.rs @@ -13,5 +13,5 @@ use std::fmt; #[test] fn test_format() { let s = fmt::format(format_args!("Hello, {}!", "world")); - assert_eq!(s.as_slice(), "Hello, world!"); + assert_eq!(s, "Hello, world!"); } diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index f03a073e274..456c658a9c6 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(deprecated)] #![feature(box_syntax)] #![feature(collections)] #![feature(core)] @@ -21,6 +20,7 @@ #![feature(unicode)] #![feature(unsafe_destructor)] #![feature(into_cow)] +#![feature(step_by)] #![cfg_attr(test, feature(str_char))] #[macro_use] extern crate log; diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index 4168fe88a4b..041d9fba57c 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -59,7 +59,7 @@ fn test_from_elem() { // Test on-heap from_elem. v = vec![20; 6]; { - let v = v.as_slice(); + let v = &v[..]; assert_eq!(v[0], 20); assert_eq!(v[1], 20); assert_eq!(v[2], 20); @@ -685,7 +685,7 @@ fn test_capacity() { #[test] fn test_slice_2() { let v = vec![1, 2, 3, 4, 5]; - let v = v.slice(1, 3); + let v = &v[1..3]; assert_eq!(v.len(), 2); assert_eq!(v[0], 2); assert_eq!(v[1], 3); diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index 5cfa8009054..72a9f596d88 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -89,32 +89,32 @@ fn test_into_bytes() { #[test] fn test_find_str() { // byte positions - assert_eq!("".find_str(""), Some(0)); - assert!("banana".find_str("apple pie").is_none()); + assert_eq!("".find(""), Some(0)); + assert!("banana".find("apple pie").is_none()); let data = "abcabc"; - assert_eq!(data[0..6].find_str("ab"), Some(0)); - assert_eq!(data[2..6].find_str("ab"), Some(3 - 2)); - assert!(data[2..4].find_str("ab").is_none()); + assert_eq!(data[0..6].find("ab"), Some(0)); + assert_eq!(data[2..6].find("ab"), Some(3 - 2)); + assert!(data[2..4].find("ab").is_none()); let string = "ประเทศไทย中华Việt Nam"; let mut data = String::from_str(string); data.push_str(string); - assert!(data.find_str("ไท华").is_none()); - assert_eq!(data[0..43].find_str(""), Some(0)); - assert_eq!(data[6..43].find_str(""), Some(6 - 6)); + assert!(data.find("ไท华").is_none()); + assert_eq!(data[0..43].find(""), Some(0)); + assert_eq!(data[6..43].find(""), Some(6 - 6)); - assert_eq!(data[0..43].find_str("ประ"), Some( 0)); - assert_eq!(data[0..43].find_str("ทศไ"), Some(12)); - assert_eq!(data[0..43].find_str("ย中"), Some(24)); - assert_eq!(data[0..43].find_str("iệt"), Some(34)); - assert_eq!(data[0..43].find_str("Nam"), Some(40)); + assert_eq!(data[0..43].find("ประ"), Some( 0)); + assert_eq!(data[0..43].find("ทศไ"), Some(12)); + assert_eq!(data[0..43].find("ย中"), Some(24)); + assert_eq!(data[0..43].find("iệt"), Some(34)); + assert_eq!(data[0..43].find("Nam"), Some(40)); - assert_eq!(data[43..86].find_str("ประ"), Some(43 - 43)); - assert_eq!(data[43..86].find_str("ทศไ"), Some(55 - 43)); - assert_eq!(data[43..86].find_str("ย中"), Some(67 - 43)); - assert_eq!(data[43..86].find_str("iệt"), Some(77 - 43)); - assert_eq!(data[43..86].find_str("Nam"), Some(83 - 43)); + assert_eq!(data[43..86].find("ประ"), Some(43 - 43)); + assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43)); + assert_eq!(data[43..86].find("ย中"), Some(67 - 43)); + assert_eq!(data[43..86].find("iệt"), Some(77 - 43)); + assert_eq!(data[43..86].find("Nam"), Some(83 - 43)); } #[test] @@ -297,16 +297,16 @@ fn test_replace_2d() { #[test] fn test_slice() { - assert_eq!("ab", "abc".slice(0, 2)); - assert_eq!("bc", "abc".slice(1, 3)); - assert_eq!("", "abc".slice(1, 1)); - assert_eq!("\u{65e5}", "\u{65e5}\u{672c}".slice(0, 3)); + assert_eq!("ab", &"abc"[0..2]); + assert_eq!("bc", &"abc"[1..3]); + assert_eq!("", &"abc"[1..1]); + assert_eq!("\u{65e5}", &"\u{65e5}\u{672c}"[0..3]); let data = "ประเทศไทย中华"; - assert_eq!("ป", data.slice(0, 3)); - assert_eq!("ร", data.slice(3, 6)); - assert_eq!("", data.slice(3, 3)); - assert_eq!("华", data.slice(30, 33)); + assert_eq!("ป", &data[0..3]); + assert_eq!("ร", &data[3..6]); + assert_eq!("", &data[3..3]); + assert_eq!("华", &data[30..33]); fn a_million_letter_x() -> String { let mut i = 0; @@ -328,23 +328,23 @@ fn test_slice() { } let letters = a_million_letter_x(); assert!(half_a_million_letter_x() == - String::from_str(letters.slice(0, 3 * 500000))); + String::from_str(&letters[0..3 * 500000])); } #[test] fn test_slice_2() { let ss = "中华Việt Nam"; - assert_eq!("华", ss.slice(3, 6)); - assert_eq!("Việt Nam", ss.slice(6, 16)); + assert_eq!("华", &ss[3..6]); + assert_eq!("Việt Nam", &ss[6..16]); - assert_eq!("ab", "abc".slice(0, 2)); - assert_eq!("bc", "abc".slice(1, 3)); - assert_eq!("", "abc".slice(1, 1)); + assert_eq!("ab", &"abc"[0..2]); + assert_eq!("bc", &"abc"[1..3]); + assert_eq!("", &"abc"[1..1]); - assert_eq!("中", ss.slice(0, 3)); - assert_eq!("华V", ss.slice(3, 7)); - assert_eq!("", ss.slice(3, 3)); + assert_eq!("中", &ss[0..3]); + assert_eq!("华V", &ss[3..7]); + assert_eq!("", &ss[3..3]); /*0: 中 3: 华 6: V @@ -360,20 +360,20 @@ fn test_slice_2() { #[test] #[should_panic] fn test_slice_fail() { - "中华Việt Nam".slice(0, 2); + &"中华Việt Nam"[0..2]; } #[test] fn test_slice_from() { - assert_eq!("abcd".slice_from(0), "abcd"); - assert_eq!("abcd".slice_from(2), "cd"); - assert_eq!("abcd".slice_from(4), ""); + assert_eq!(&"abcd"[0..], "abcd"); + assert_eq!(&"abcd"[2..], "cd"); + assert_eq!(&"abcd"[4..], ""); } #[test] fn test_slice_to() { - assert_eq!("abcd".slice_to(0), ""); - assert_eq!("abcd".slice_to(2), "ab"); - assert_eq!("abcd".slice_to(4), "abcd"); + assert_eq!(&"abcd"[..0], ""); + assert_eq!(&"abcd"[..2], "ab"); + assert_eq!(&"abcd"[..4], "abcd"); } #[test] @@ -660,10 +660,10 @@ fn test_contains() { #[test] fn test_contains_char() { - assert!("abc".contains_char('b')); - assert!("a".contains_char('a')); - assert!(!"abc".contains_char('d')); - assert!(!"".contains_char('a')); + assert!("abc".contains('b')); + assert!("a".contains('a')); + assert!(!"abc".contains('d')); + assert!(!"".contains('a')); } #[test] @@ -1445,9 +1445,9 @@ fn test_graphemes() { } #[test] -fn test_split_strator() { +fn test_splitator() { fn t(s: &str, sep: &str, u: &[&str]) { - let v: Vec<&str> = s.split_str(sep).collect(); + let v: Vec<&str> = s.split(sep).collect(); assert_eq!(v, u); } t("--1233345--", "12345", &["--1233345--"]); @@ -1466,19 +1466,6 @@ fn test_split_strator() { t("zzzzz", "zz", &["","","z"]); } -#[test] -fn test_str_default() { - use std::default::Default; - - fn t() { - let s: S = Default::default(); - assert_eq!(s.as_slice(), ""); - } - - t::<&str>(); - t::(); -} - #[test] fn test_str_container() { fn sum_len(v: &[&str]) -> usize { diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs index 4768d5e92ac..5d6aa8ac0dc 100644 --- a/src/libcollectionstest/string.rs +++ b/src/libcollectionstest/string.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::borrow::IntoCow; +use std::borrow::{IntoCow, Cow}; use std::iter::repeat; use std::str::Utf8Error; -use std::string::{CowString, as_string}; +use std::string::as_string; use test::Bencher; @@ -52,11 +52,11 @@ fn test_from_utf8() { #[test] fn test_from_utf8_lossy() { let xs = b"hello"; - let ys: CowString = "hello".into_cow(); + let ys: Cow = "hello".into_cow(); assert_eq!(String::from_utf8_lossy(xs), ys); let xs = "ศไทย中华Việt Nam".as_bytes(); - let ys: CowString = "ศไทย中华Việt Nam".into_cow(); + let ys: Cow = "ศไทย中华Việt Nam".into_cow(); assert_eq!(String::from_utf8_lossy(xs), ys); let xs = b"Hello\xC2 There\xFF Goodbye"; diff --git a/src/libcollectionstest/vec_deque.rs b/src/libcollectionstest/vec_deque.rs index fe752d5a7e1..ec03ce620fd 100644 --- a/src/libcollectionstest/vec_deque.rs +++ b/src/libcollectionstest/vec_deque.rs @@ -18,7 +18,6 @@ use self::Taggy::*; use self::Taggypar::*; #[test] -#[allow(deprecated)] fn test_simple() { let mut d = VecDeque::new(); assert_eq!(d.len(), 0); @@ -545,7 +544,7 @@ fn test_from_iter() { let u: Vec<_> = deq.iter().cloned().collect(); assert_eq!(u, v); - let seq = iter::count(0, 2).take(256); + let seq = (0..).step_by(2).take(256); let deq: VecDeque<_> = seq.collect(); for (i, &x) in deq.iter().enumerate() { assert_eq!(2*i, x); diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 91b4b46ac39..8c396a4e7fb 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -1062,144 +1062,3 @@ pub fn fence(order: Ordering) { } } } - -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "renamed to AtomicIsize")] -#[allow(missing_docs)] -pub struct AtomicInt { - v: UnsafeCell, -} - -#[allow(deprecated)] -unsafe impl Sync for AtomicInt {} - -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "renamed to AtomicUsize")] -#[allow(missing_docs)] -pub struct AtomicUint { - v: UnsafeCell, -} - -#[allow(deprecated)] -unsafe impl Sync for AtomicUint {} - -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "use ATOMIC_ISIZE_INIT instead")] -#[allow(missing_docs, deprecated)] -pub const ATOMIC_INT_INIT: AtomicInt = - AtomicInt { v: UnsafeCell { value: 0 } }; -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "use ATOMIC_USIZE_INIT instead")] -#[allow(missing_docs, deprecated)] -pub const ATOMIC_UINT_INIT: AtomicUint = - AtomicUint { v: UnsafeCell { value: 0, } }; - -#[allow(missing_docs, deprecated)] -impl AtomicInt { - #[inline] - pub fn new(v: isize) -> AtomicInt { - AtomicInt {v: UnsafeCell::new(v)} - } - - #[inline] - pub fn load(&self, order: Ordering) -> isize { - unsafe { atomic_load(self.v.get(), order) } - } - - #[inline] - pub fn store(&self, val: isize, order: Ordering) { - unsafe { atomic_store(self.v.get(), val, order); } - } - - #[inline] - pub fn swap(&self, val: isize, order: Ordering) -> isize { - unsafe { atomic_swap(self.v.get(), val, order) } - } - - #[inline] - pub fn compare_and_swap(&self, old: isize, new: isize, order: Ordering) -> isize { - unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } - } - - #[inline] - pub fn fetch_add(&self, val: isize, order: Ordering) -> isize { - unsafe { atomic_add(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_sub(&self, val: isize, order: Ordering) -> isize { - unsafe { atomic_sub(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_and(&self, val: isize, order: Ordering) -> isize { - unsafe { atomic_and(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_or(&self, val: isize, order: Ordering) -> isize { - unsafe { atomic_or(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_xor(&self, val: isize, order: Ordering) -> isize { - unsafe { atomic_xor(self.v.get(), val, order) } - } -} - -#[allow(missing_docs, deprecated)] -impl AtomicUint { - #[inline] - pub fn new(v: usize) -> AtomicUint { - AtomicUint { v: UnsafeCell::new(v) } - } - - #[inline] - pub fn load(&self, order: Ordering) -> usize { - unsafe { atomic_load(self.v.get(), order) } - } - - #[inline] - pub fn store(&self, val: usize, order: Ordering) { - unsafe { atomic_store(self.v.get(), val, order); } - } - - #[inline] - pub fn swap(&self, val: usize, order: Ordering) -> usize { - unsafe { atomic_swap(self.v.get(), val, order) } - } - - #[inline] - pub fn compare_and_swap(&self, old: usize, new: usize, order: Ordering) -> usize { - unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } - } - - #[inline] - pub fn fetch_add(&self, val: usize, order: Ordering) -> usize { - unsafe { atomic_add(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_sub(&self, val: usize, order: Ordering) -> usize { - unsafe { atomic_sub(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_and(&self, val: usize, order: Ordering) -> usize { - unsafe { atomic_and(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_or(&self, val: usize, order: Ordering) -> usize { - unsafe { atomic_or(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_xor(&self, val: usize, order: Ordering) -> usize { - unsafe { atomic_xor(self.v.get(), val, order) } - } -} diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 9e6dbce0325..906c87f3ffd 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -343,23 +343,6 @@ impl RefCell { } } - /// Attempts to immutably borrow the wrapped value. - /// - /// The borrow lasts until the returned `Ref` exits scope. Multiple - /// immutable borrows can be taken out at the same time. - /// - /// Returns `None` if the value is currently mutably borrowed. - #[unstable(feature = "core", reason = "may be renamed or removed")] - #[deprecated(since = "1.0.0", - reason = "dispatch on `cell.borrow_state()` instead")] - #[inline] - pub fn try_borrow<'a>(&'a self) -> Option> { - match BorrowRef::new(&self.borrow) { - Some(b) => Some(Ref { _value: unsafe { &*self.value.get() }, _borrow: b }), - None => None, - } - } - /// Immutably borrows the wrapped value. /// /// The borrow lasts until the returned `Ref` exits scope. Multiple @@ -407,23 +390,6 @@ impl RefCell { } } - /// Mutably borrows the wrapped value. - /// - /// The borrow lasts until the returned `RefMut` exits scope. The value - /// cannot be borrowed while this borrow is active. - /// - /// Returns `None` if the value is currently borrowed. - #[unstable(feature = "core", reason = "may be renamed or removed")] - #[deprecated(since = "1.0.0", - reason = "dispatch on `cell.borrow_state()` instead")] - #[inline] - pub fn try_borrow_mut<'a>(&'a self) -> Option> { - match BorrowRefMut::new(&self.borrow) { - Some(b) => Some(RefMut { _value: unsafe { &mut *self.value.get() }, _borrow: b }), - None => None, - } - } - /// Mutably borrows the wrapped value. /// /// The borrow lasts until the returned `RefMut` exits scope. The value diff --git a/src/libcore/error.rs b/src/libcore/error.rs index 9430aa00668..bd5d8d32725 100644 --- a/src/libcore/error.rs +++ b/src/libcore/error.rs @@ -50,30 +50,30 @@ //! ``` //! #![feature(core)] //! use std::error::FromError; -//! use std::{io, str}; //! use std::fs::File; +//! use std::io; //! //! enum MyError { //! Io(io::Error), -//! Utf8(str::Utf8Error), +//! CustomError, //! } //! //! impl FromError for MyError { -//! fn from_error(err: io::Error) -> MyError { MyError::Io(err) } +//! fn from_error(err: io::Error) -> MyError { +//! MyError::Io(err) +//! } //! } //! -//! impl FromError for MyError { -//! fn from_error(err: str::Utf8Error) -> MyError { MyError::Utf8(err) } -//! } -//! -//! #[allow(unused_variables)] //! fn open_and_map() -> Result<(), MyError> { -//! let b = b"foo.txt"; -//! let s = try!(str::from_utf8(b)); -//! let f = try!(File::open(s)); -//! +//! let f = try!(File::open("foo.txt")); +//! let m = try!(work_with_file(&f)); //! // do something interesting here... -//! Ok(()) +//! # Ok(()) +//! } +//! +//! fn work_with_file(file: &File) -> Result<(), MyError> { +//! // ... +//! # return Ok(()) //! } //! ``` diff --git a/src/libcore/finally.rs b/src/libcore/finally.rs deleted file mode 100644 index 93a7d2bb17b..00000000000 --- a/src/libcore/finally.rs +++ /dev/null @@ -1,111 +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. - -//! The Finally trait provides a method, `finally` on -//! stack closures that emulates Java-style try/finally blocks. -//! -//! Using the `finally` method is sometimes convenient, but the type rules -//! prohibit any shared, mutable state between the "try" case and the -//! "finally" case. For advanced cases, the `try_finally` function can -//! also be used. See that function for more details. -//! -//! # Examples -//! -//! ``` -//! # #![feature(core)] -//! # #![feature(unboxed_closures)] -//! -//! use std::finally::Finally; -//! -//! (|| { -//! // ... -//! }).finally(|| { -//! // this code is always run -//! }) -//! ``` - -#![unstable(feature = "core")] -#![deprecated(since = "1.0.0", - reason = "It is unclear if this module is more robust than implementing \ - Drop on a custom type, and this module is being removed with no \ - replacement. Use a custom Drop implementation to regain existing \ - functionality.")] -#![allow(deprecated)] - -use ops::{Drop, FnMut, FnOnce}; - -/// A trait for executing a destructor unconditionally after a block of code, -/// regardless of whether the blocked fails. -pub trait Finally { - /// Executes this object, unconditionally running `dtor` after this block of - /// code has run. - fn finally(&mut self, dtor: F) -> T where F: FnMut(); -} - -impl Finally for F where F: FnMut() -> T { - fn finally(&mut self, mut dtor: G) -> T where G: FnMut() { - try_finally(&mut (), self, |_, f| (*f)(), |_| dtor()) - } -} - -/// The most general form of the `finally` functions. The function -/// `try_fn` will be invoked first; whether or not it panics, the -/// function `finally_fn` will be invoked next. The two parameters -/// `mutate` and `drop` are used to thread state through the two -/// closures. `mutate` is used for any shared, mutable state that both -/// closures require access to; `drop` is used for any state that the -/// `try_fn` requires ownership of. -/// -/// **WARNING:** While shared, mutable state between the try and finally -/// function is often necessary, one must be very careful; the `try` -/// function could have panicked at any point, so the values of the shared -/// state may be inconsistent. -/// -/// # Examples -/// -/// ``` -/// # #![feature(core)] -/// use std::finally::try_finally; -/// -/// struct State<'a> { buffer: &'a mut [u8], len: usize } -/// # let mut buf = []; -/// let mut state = State { buffer: &mut buf, len: 0 }; -/// try_finally( -/// &mut state, (), -/// |state, ()| { -/// // use state.buffer, state.len -/// }, -/// |state| { -/// // use state.buffer, state.len to cleanup -/// }) -/// ``` -pub fn try_finally(mutate: &mut T, drop: U, try_fn: F, finally_fn: G) -> R where - F: FnOnce(&mut T, U) -> R, - G: FnMut(&mut T), -{ - let f = Finallyalizer { - mutate: mutate, - dtor: finally_fn, - }; - try_fn(&mut *f.mutate, drop) -} - -struct Finallyalizer<'a, A:'a, F> where F: FnMut(&mut A) { - mutate: &'a mut A, - dtor: F, -} - -#[unsafe_destructor] -impl<'a, A, F> Drop for Finallyalizer<'a, A, F> where F: FnMut(&mut A) { - #[inline] - fn drop(&mut self) { - (self.dtor)(self.mutate); - } -} diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index e65fbac926b..6820a7025fc 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -114,11 +114,6 @@ impl SipHasher { state } - /// Returns the computed hash. - #[unstable(feature = "hash")] - #[deprecated(since = "1.0.0", reason = "renamed to finish")] - pub fn result(&self) -> u64 { self.finish() } - fn reset(&mut self) { self.length = 0; self.v0 = self.k0 ^ 0x736f6d6570736575; diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 44d48f9f4bf..6af26e254b3 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -66,8 +66,7 @@ use marker; use mem; use num::{Int, Zero, One, ToPrimitive}; use ops::{Add, Sub, FnMut, RangeFrom}; -use option::Option; -use option::Option::{Some, None}; +use option::Option::{self, Some, None}; use marker::Sized; use usize; @@ -433,7 +432,7 @@ pub trait Iterator { /// # #![feature(core)] /// let xs = [2, 3]; /// let ys = [0, 1, 0, 1, 2]; - /// let it = xs.iter().flat_map(|&x| std::iter::count(0, 1).take(x)); + /// let it = xs.iter().flat_map(|&x| (0..).take(x)); /// // Check that `it` has the same elements as `ys` /// for (i, x) in it.enumerate() { /// assert_eq!(x, ys[i]); @@ -1244,10 +1243,10 @@ pub trait MultiplicativeIterator { /// /// ``` /// # #![feature(core)] - /// use std::iter::{count, MultiplicativeIterator}; + /// use std::iter::MultiplicativeIterator; /// /// fn factorial(n: usize) -> usize { - /// count(1, 1).take_while(|&i| i <= n).product() + /// (1..).take_while(|&i| i <= n).product() /// } /// assert!(factorial(0) == 1); /// assert!(factorial(1) == 1); @@ -2544,26 +2543,6 @@ impl ::ops::Range { } } -/// An infinite iterator starting at `start` and advancing by `step` with each -/// iteration -#[unstable(feature = "core", - reason = "may be renamed or replaced by range notation adapters")] -#[deprecated(since = "1.0.0-beta", reason = "use range notation and step_by")] -pub type Counter = StepBy>; - -/// Deprecated: use `(start..).step_by(step)` instead. -#[inline] -#[unstable(feature = "core", - reason = "may be renamed or replaced by range notation adapters")] -#[deprecated(since = "1.0.0-beta", reason = "use (start..).step_by(step) instead")] -#[allow(deprecated)] -pub fn count(start: A, step: A) -> Counter { - StepBy { - range: RangeFrom { start: start }, - step_by: step, - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for StepBy> where A: Clone, @@ -2584,108 +2563,12 @@ impl Iterator for StepBy> where } } -/// An iterator over the range [start, stop) -#[allow(deprecated)] -#[derive(Clone)] -#[unstable(feature = "core", - reason = "will be replaced by range notation")] -#[deprecated(since = "1.0.0-beta", reason = "use range notation")] -pub struct Range { - state: A, - stop: A, - one: A, -} - -/// Deprecated: use `(start..stop)` instead. -#[inline] -#[unstable(feature = "core", reason = "will be replaced by range notation")] -#[deprecated(since = "1.0.0-beta", reason = "use (start..stop) instead")] -#[allow(deprecated)] -pub fn range(start: A, stop: A) -> Range { - Range { - state: start, - stop: stop, - one: Int::one(), - } -} - -// FIXME: #10414: Unfortunate type bound -#[unstable(feature = "core", - reason = "will be replaced by range notation")] -#[deprecated(since = "1.0.0-beta", reason = "use range notation")] -#[allow(deprecated)] -impl Iterator for Range { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - if self.state < self.stop { - let result = self.state.clone(); - self.state = self.state + self.one; - Some(result) - } else { - None - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - // This first checks if the elements are representable as i64. If they aren't, try u64 (to - // handle cases like range(huge, huger)). We don't use usize/isize because the difference of - // the i64/u64 might lie within their range. - let bound = match self.state.to_i64() { - Some(a) => { - let sz = self.stop.to_i64().map(|b| b.checked_sub(a)); - match sz { - Some(Some(bound)) => bound.to_usize(), - _ => None, - } - }, - None => match self.state.to_u64() { - Some(a) => { - let sz = self.stop.to_u64().map(|b| b.checked_sub(a)); - match sz { - Some(Some(bound)) => bound.to_usize(), - _ => None - } - }, - None => None - } - }; - - match bound { - Some(b) => (b, Some(b)), - // Standard fallback for unbounded/unrepresentable bounds - None => (0, None) - } - } -} - -/// `Int` is required to ensure the range will be the same regardless of -/// the direction it is consumed. -#[unstable(feature = "core", - reason = "will be replaced by range notation")] -#[deprecated(since = "1.0.0-beta", reason = "use range notation")] -#[allow(deprecated)] -impl DoubleEndedIterator for Range { - #[inline] - fn next_back(&mut self) -> Option { - if self.stop > self.state { - self.stop = self.stop - self.one; - Some(self.stop.clone()) - } else { - None - } - } -} - /// An iterator over the range [start, stop] #[derive(Clone)] #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -#[allow(deprecated)] pub struct RangeInclusive { - range: Range, + range: ops::Range, done: bool, } @@ -2693,17 +2576,15 @@ pub struct RangeInclusive { #[inline] #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -#[allow(deprecated)] pub fn range_inclusive(start: A, stop: A) -> RangeInclusive { RangeInclusive { - range: range(start, stop), + range: start..stop, done: false, } } #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -#[allow(deprecated)] impl Iterator for RangeInclusive { type Item = A; @@ -2712,9 +2593,9 @@ impl Iterator for RangeInclusive { match self.range.next() { Some(x) => Some(x), None => { - if !self.done && self.range.state == self.range.stop { + if !self.done && self.range.start == self.range.end { self.done = true; - Some(self.range.stop.clone()) + Some(self.range.end.clone()) } else { None } @@ -2740,43 +2621,22 @@ impl Iterator for RangeInclusive { #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -#[allow(deprecated)] impl DoubleEndedIterator for RangeInclusive { #[inline] fn next_back(&mut self) -> Option { - if self.range.stop > self.range.state { - let result = self.range.stop.clone(); - self.range.stop = self.range.stop - self.range.one; + if self.range.end > self.range.start { + let result = self.range.end.clone(); + self.range.end = self.range.end - A::one(); Some(result) - } else if !self.done && self.range.state == self.range.stop { + } else if !self.done && self.range.start == self.range.end { self.done = true; - Some(self.range.stop.clone()) + Some(self.range.end.clone()) } else { None } } } -/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping. -#[unstable(feature = "core", - reason = "likely to be replaced by range notation and adapters")] -#[deprecated(since = "1.0.0-beta", reason = "use range notation and step_by")] -pub type RangeStep = StepBy>; - -/// Deprecated: use `(start..stop).step_by(step)` instead. -#[inline] -#[unstable(feature = "core", - reason = "likely to be replaced by range notation and adapters")] -#[deprecated(since = "1.0.0-beta", - reason = "use `(start..stop).step_by(step)` instead")] -#[allow(deprecated)] -pub fn range_step(start: A, stop: A, step: A) -> RangeStep { - StepBy { - step_by: step, - range: ::ops::Range { start: start, end: stop }, - } -} - #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl Iterator for StepBy> { diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index cf5cb0c2f5e..5e8b7fba1f1 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -136,7 +136,6 @@ pub mod atomic; pub mod cell; pub mod char; pub mod panicking; -pub mod finally; pub mod iter; pub mod option; pub mod raw; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index d5a7c1d6b26..07fac66d41c 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -233,7 +233,7 @@ macro_rules! writeln { /// ``` /// # #![feature(core)] /// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3 -/// for i in std::iter::count(0, 1) { +/// for i in 0.. { /// if 3*i < i { panic!("u32 overflow"); } /// if x < 3*i { return i-1; } /// } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 3f4b39da4b3..339670435f1 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -415,42 +415,6 @@ mod impls { unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {} } -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<&'a ()>`")] -#[lang="contravariant_lifetime"] -pub struct ContravariantLifetime<'a>; - -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData`")] -#[lang="covariant_lifetime"] -pub struct CovariantLifetime<'a>; - -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData>`")] -#[lang="invariant_lifetime"] -pub struct InvariantLifetime<'a>; - -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData`")] -#[lang="contravariant_type"] -pub struct ContravariantType; - -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData`")] -#[lang="covariant_type"] -pub struct CovariantType; - -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData>`")] -#[lang="invariant_type"] -pub struct InvariantType; - /// A marker trait indicates a type that can be reflected over. This /// trait is implemented for all types. Its purpose is to ensure that /// when you write a generic function that will employ reflection, diff --git a/src/libcore/option.rs b/src/libcore/option.rs index c5102ede29f..6db7c9bd99d 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -154,8 +154,6 @@ use mem; use ops::FnOnce; use result::Result::{Ok, Err}; use result::Result; -#[allow(deprecated)] -use slice::AsSlice; use slice; // Note that this is not a lang item per se, but it has a hidden dependency on @@ -765,25 +763,6 @@ impl Option { // Trait implementations ///////////////////////////////////////////////////////////////////////////// -#[unstable(feature = "core", - reason = "waiting on the stability of the trait itself")] -#[deprecated(since = "1.0.0", - reason = "use the inherent method instead")] -#[allow(deprecated)] -impl AsSlice for Option { - /// Convert from `Option` to `&[T]` (without copying) - #[inline] - fn as_slice<'a>(&'a self) -> &'a [T] { - match *self { - Some(ref x) => slice::ref_slice(x), - None => { - let result: &[_] = &[]; - result - } - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Default for Option { #[inline] diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 448b90c0dbd..e60bc494081 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -37,10 +37,11 @@ pub use char::CharExt; pub use clone::Clone; pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; pub use convert::{AsRef, AsMut, Into, From}; -pub use iter::Extend; -pub use iter::{Iterator, DoubleEndedIterator}; -pub use iter::{ExactSizeIterator}; +pub use iter::{Iterator, DoubleEndedIterator, Extend, ExactSizeIterator}; pub use option::Option::{self, Some, None}; pub use result::Result::{self, Ok, Err}; -pub use slice::{AsSlice, SliceExt}; -pub use str::{Str, StrExt}; +pub use slice::SliceExt; +pub use str::StrExt; + +#[allow(deprecated)] pub use slice::AsSlice; +#[allow(deprecated)] pub use str::Str; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 41a70ef708f..ff51e25fcbf 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -157,21 +157,6 @@ pub fn null() -> *const T { 0 as *const T } #[stable(feature = "rust1", since = "1.0.0")] pub fn null_mut() -> *mut T { 0 as *mut T } -/// Zeroes out `count * size_of::` bytes of memory at `dst`. `count` may be -/// `0`. -/// -/// # Safety -/// -/// Beyond accepting a raw pointer, this is unsafe because it will not drop the -/// contents of `dst`, and may be used to create invalid instances of `T`. -#[inline] -#[unstable(feature = "core", - reason = "may play a larger role in std::ptr future extensions")] -#[deprecated(since = "1.0.0", reason = "use `write_bytes` instead")] -pub unsafe fn zero_memory(dst: *mut T, count: usize) { - write_bytes(dst, 0, count); -} - /// Swaps the values at two mutable locations of the same type, without /// deinitialising either. They may overlap, unlike `mem::swap` which is /// otherwise equivalent. diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index 8502a9c53c4..47d1f3a1a3c 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -64,19 +64,6 @@ pub struct Slice { impl Copy for Slice {} -/// The representation of an old closure. -#[repr(C)] -#[derive(Copy)] -#[unstable(feature = "core")] -#[deprecated(reason = "unboxed new closures do not have a universal representation; \ - `&Fn` (etc) trait objects should use `TraitObject` instead", - since= "1.0.0")] -#[allow(deprecated) /* for deriving Copy impl */] -pub struct Closure { - pub code: *mut (), - pub env: *mut (), -} - /// The representation of a trait object like `&SomeTrait`. /// /// This struct has the same layout as types like `&SomeTrait` and diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 223a0bdae36..d8856130fab 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -88,10 +88,6 @@ pub trait SliceExt { fn len(&self) -> usize; fn is_empty(&self) -> bool { self.len() == 0 } fn get_mut<'a>(&'a mut self, index: usize) -> Option<&'a mut Self::Item>; - #[unstable(feature = "core", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")] - fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Self::Item]; fn iter_mut<'a>(&'a mut self) -> IterMut<'a, Self::Item>; fn first_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>; fn tail_mut<'a>(&'a mut self) -> &'a mut [Self::Item]; @@ -263,12 +259,6 @@ impl SliceExt for [T] { if index < self.len() { Some(&mut self[index]) } else { None } } - #[inline] - #[unstable(feature = "core", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")] - fn as_mut_slice(&mut self) -> &mut [T] { self } - #[inline] fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { unsafe { @@ -1502,54 +1492,6 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] { transmute(RawSlice { data: p, len: len }) } -/// Forms a slice from a pointer and a length. -/// -/// The pointer given is actually a reference to the base of the slice. This -/// reference is used to give a concrete lifetime to tie the returned slice to. -/// Typically this should indicate that the slice is valid for as long as the -/// pointer itself is valid. -/// -/// The `len` argument is the number of **elements**, not the number of bytes. -/// -/// This function is unsafe as there is no guarantee that the given pointer is -/// valid for `len` elements, nor whether the lifetime provided is a suitable -/// lifetime for the returned slice. -/// -/// # Examples -/// -/// ``` -/// #![feature(core)] -/// use std::slice; -/// -/// // manifest a slice out of thin air! -/// let ptr = 0x1234 as *const usize; -/// let amt = 10; -/// unsafe { -/// let slice = slice::from_raw_buf(&ptr, amt); -/// } -/// ``` -#[inline] -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "use from_raw_parts")] -pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: usize) -> &'a [T] { - transmute(RawSlice { data: *p, len: len }) -} - -/// Performs the same functionality as `from_raw_buf`, except that a mutable -/// slice is returned. -/// -/// This function is unsafe for the same reasons as `from_raw_buf`, as well as -/// not being able to provide a non-aliasing guarantee of the returned mutable -/// slice. -#[inline] -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "use from_raw_parts_mut")] -pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: usize) -> &'a mut [T] { - transmute(RawSlice { data: *p, len: len }) -} - // // Submodules // diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f9e2b47d9b6..934c4515614 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -28,8 +28,6 @@ use iter::ExactSizeIterator; use iter::{Map, Iterator, DoubleEndedIterator}; use marker::Sized; use mem; -#[allow(deprecated)] -use num::Int; use ops::{Fn, FnMut, FnOnce}; use option::Option::{self, None, Some}; use raw::{Repr, Slice}; @@ -243,78 +241,6 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str { mem::transmute(v) } -/// Constructs a static string slice from a given raw pointer. -/// -/// This function will read memory starting at `s` until it finds a 0, and then -/// transmute the memory up to that point as a string slice, returning the -/// corresponding `&'static str` value. -/// -/// This function is unsafe because the caller must ensure the C string itself -/// has the static lifetime and that the memory `s` is valid up to and including -/// the first null byte. -/// -/// # Panics -/// -/// This function will panic if the string pointed to by `s` is not valid UTF-8. -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "use std::ffi::c_str_to_bytes + str::from_utf8")] -pub unsafe fn from_c_str(s: *const i8) -> &'static str { - let s = s as *const u8; - let mut len: usize = 0; - while *s.offset(len as isize) != 0 { - len += 1; - } - let v: &'static [u8] = ::mem::transmute(Slice { data: s, len: len }); - from_utf8(v).ok().expect("from_c_str passed invalid utf-8 data") -} - -/// Something that can be used to compare against a character -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "use `Pattern` instead")] -// NB: Rather than removing it, make it private and move it into self::pattern -pub trait CharEq { - /// Determine if the splitter should split at the given character - fn matches(&mut self, char) -> bool; - /// Indicate if this is only concerned about ASCII characters, - /// which can allow for a faster implementation. - fn only_ascii(&self) -> bool; -} - -#[allow(deprecated) /* for CharEq */ ] -impl CharEq for char { - #[inline] - fn matches(&mut self, c: char) -> bool { *self == c } - - #[inline] - fn only_ascii(&self) -> bool { (*self as u32) < 128 } -} - -#[allow(deprecated) /* for CharEq */ ] -impl CharEq for F where F: FnMut(char) -> bool { - #[inline] - fn matches(&mut self, c: char) -> bool { (*self)(c) } - - #[inline] - fn only_ascii(&self) -> bool { false } -} - -#[allow(deprecated) /* for CharEq */ ] -impl<'a> CharEq for &'a [char] { - #[inline] - #[allow(deprecated) /* for CharEq */ ] - fn matches(&mut self, c: char) -> bool { - self.iter().any(|&m| { let mut m = m; m.matches(c) }) - } - - #[inline] - #[allow(deprecated) /* for CharEq */ ] - fn only_ascii(&self) -> bool { - self.iter().all(|m| m.only_ascii()) - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Error for Utf8Error { fn description(&self) -> &str { @@ -1047,22 +973,6 @@ impl<'a, P: Pattern<'a>> Iterator for MatchIndices<'a, P> { } } -/// An iterator over the substrings of a string separated by a given -/// search string -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", reason = "use `Split` with a `&str`")] -pub struct SplitStr<'a, P: Pattern<'a>>(Split<'a, P>); -#[allow(deprecated)] -impl<'a, P: Pattern<'a>> Iterator for SplitStr<'a, P> { - type Item = &'a str; - - #[inline] - #[allow(deprecated)] - fn next(&mut self) -> Option<&'a str> { - Iterator::next(&mut self.0) - } -} - impl<'a, 'b> OldMatchIndices<'a, 'b> { #[inline] #[allow(dead_code)] @@ -1444,8 +1354,6 @@ pub trait StrExt { fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> where P::Searcher: ReverseSearcher<'a>; fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P>; - #[allow(deprecated) /* for SplitStr */] - fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P>; fn lines<'a>(&'a self) -> Lines<'a>; fn lines_any<'a>(&'a self) -> LinesAny<'a>; fn char_len(&self) -> usize; @@ -1565,12 +1473,6 @@ impl StrExt for str { MatchIndices(pat.into_searcher(self)) } - #[inline] - #[allow(deprecated) /* for SplitStr */ ] - fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P> { - SplitStr(self.split(pat)) - } - #[inline] fn lines(&self) -> Lines { Lines { inner: self.split_terminator('\n').0 } diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index 98b6533980d..922ab2c14a6 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(deprecated) /* for CharEq */ ] - use prelude::*; -use super::CharEq; // Pattern @@ -228,6 +225,40 @@ pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {} // Impl for a CharEq wrapper +#[doc(hidden)] +trait CharEq { + fn matches(&mut self, char) -> bool; + fn only_ascii(&self) -> bool; +} + +impl CharEq for char { + #[inline] + fn matches(&mut self, c: char) -> bool { *self == c } + + #[inline] + fn only_ascii(&self) -> bool { (*self as u32) < 128 } +} + +impl CharEq for F where F: FnMut(char) -> bool { + #[inline] + fn matches(&mut self, c: char) -> bool { (*self)(c) } + + #[inline] + fn only_ascii(&self) -> bool { false } +} + +impl<'a> CharEq for &'a [char] { + #[inline] + fn matches(&mut self, c: char) -> bool { + self.iter().any(|&m| { let mut m = m; m.matches(c) }) + } + + #[inline] + fn only_ascii(&self) -> bool { + self.iter().all(|m| m.only_ascii()) + } +} + struct CharEqPattern(C); struct CharEqSearcher<'a, C: CharEq> { @@ -425,65 +456,116 @@ fn str_search_step(mut m: &mut StrSearcher, } } -macro_rules! associated_items { - ($t:ty, $s:ident, $e:expr) => { - // FIXME: #22463 - //type Searcher = $t; - - fn into_searcher(self, haystack: &'a str) -> $t { - let $s = self; - $e.into_searcher(haystack) +macro_rules! char_eq_pattern_impl { + ($wrapper:ty, $wrapper_ident:ident) => { + fn into_searcher(self, haystack: &'a str) -> $wrapper { + $wrapper_ident(CharEqPattern(self).into_searcher(haystack)) } - #[inline] fn is_contained_in(self, haystack: &'a str) -> bool { - let $s = self; - $e.is_contained_in(haystack) + CharEqPattern(self).is_contained_in(haystack) } - #[inline] fn is_prefix_of(self, haystack: &'a str) -> bool { - let $s = self; - $e.is_prefix_of(haystack) + CharEqPattern(self).is_prefix_of(haystack) } - - // FIXME: #21750 - /*#[inline] + #[inline] fn is_suffix_of(self, haystack: &'a str) -> bool - where $t: ReverseSearcher<'a> + where $wrapper: ReverseSearcher<'a> { - let $s = self; - $e.is_suffix_of(haystack) - }*/ + CharEqPattern(self).is_suffix_of(haystack) + } } } -// CharEq delegation impls +// Pattern for char -/// Searches for chars that are equal to a given char impl<'a> Pattern<'a> for char { - type Searcher = as Pattern<'a>>::Searcher; - associated_items!( as Pattern<'a>>::Searcher, - s, CharEqPattern(s)); + type Searcher = CharSearcher<'a>; + char_eq_pattern_impl!(CharSearcher<'a>, CharSearcher); } -/// Searches for chars that are equal to any of the chars in the array +pub struct CharSearcher<'a>(CharEqSearcher<'a, char>); + +unsafe impl<'a> Searcher<'a> for CharSearcher<'a> { + #[inline] + fn haystack(&self) -> &'a str { self.0.haystack() } + #[inline] + fn next(&mut self) -> SearchStep { self.0.next() } +} +unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { + #[inline] + fn next_back(&mut self) -> SearchStep { self.0.next_back() } +} +impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {} + +// Pattern for &[char] + impl<'a, 'b> Pattern<'a> for &'b [char] { - type Searcher = as Pattern<'a>>::Searcher; - associated_items!( as Pattern<'a>>::Searcher, - s, CharEqPattern(s)); + type Searcher = CharSliceSearcher<'a, 'b>; + char_eq_pattern_impl!(CharSliceSearcher<'a, 'b>, CharSliceSearcher); } -/// A convenience impl that delegates to the impl for `&str` +pub struct CharSliceSearcher<'a, 'b>(CharEqSearcher<'a, &'b [char]>); + +unsafe impl<'a, 'b> Searcher<'a> for CharSliceSearcher<'a, 'b> { + #[inline] + fn haystack(&self) -> &'a str { self.0.haystack() } + #[inline] + fn next(&mut self) -> SearchStep { self.0.next() } +} +unsafe impl<'a, 'b> ReverseSearcher<'a> for CharSliceSearcher<'a, 'b> { + #[inline] + fn next_back(&mut self) -> SearchStep { self.0.next_back() } +} +impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {} + +// Pattern for predicates + +impl<'a, F: FnMut(char) -> bool> Pattern<'a> for F { + type Searcher = CharPredSearcher<'a, F>; + char_eq_pattern_impl!(CharPredSearcher<'a, F>, CharPredSearcher); +} + +pub struct CharPredSearcher<'a, F: FnMut(char) -> bool>(CharEqSearcher<'a, F>); + +unsafe impl<'a, F> Searcher<'a> for CharPredSearcher<'a, F> + where F: FnMut(char) -> bool +{ + #[inline] + fn haystack(&self) -> &'a str { self.0.haystack() } + #[inline] + fn next(&mut self) -> SearchStep { self.0.next() } +} +unsafe impl<'a, F> ReverseSearcher<'a> for CharPredSearcher<'a, F> + where F: FnMut(char) -> bool +{ + #[inline] + fn next_back(&mut self) -> SearchStep { self.0.next_back() } +} +impl<'a, F> DoubleEndedSearcher<'a> for CharPredSearcher<'a, F> + where F: FnMut(char) -> bool +{} + +// Pattern for &&str + impl<'a, 'b> Pattern<'a> for &'b &'b str { - type Searcher = <&'b str as Pattern<'a>>::Searcher; - associated_items!(<&'b str as Pattern<'a>>::Searcher, - s, (*s)); -} - -/// Searches for chars that match the given predicate -impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool { - type Searcher = as Pattern<'a>>::Searcher; - associated_items!( as Pattern<'a>>::Searcher, - s, CharEqPattern(s)); + type Searcher = <&'b str as Pattern<'a>>::Searcher; + #[inline] + fn into_searcher(self, haystack: &'a str) + -> <&'b str as Pattern<'a>>::Searcher { + (*self).into_searcher(haystack) + } + #[inline] + fn is_contained_in(self, haystack: &'a str) -> bool { + (*self).is_contained_in(haystack) + } + #[inline] + fn is_prefix_of(self, haystack: &'a str) -> bool { + (*self).is_prefix_of(haystack) + } + #[inline] + fn is_suffix_of(self, haystack: &'a str) -> bool { + (*self).is_suffix_of(haystack) + } } diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index fff3cc14ead..85dd1039003 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -59,7 +59,6 @@ fn double_imm_borrow() { fn no_mut_then_imm_borrow() { let x = RefCell::new(0); let _b1 = x.borrow_mut(); - assert!(x.try_borrow().is_none()); assert_eq!(x.borrow_state(), BorrowState::Writing); } @@ -67,7 +66,6 @@ fn no_mut_then_imm_borrow() { fn no_imm_then_borrow_mut() { let x = RefCell::new(0); let _b1 = x.borrow(); - assert!(x.try_borrow_mut().is_none()); assert_eq!(x.borrow_state(), BorrowState::Reading); } @@ -76,7 +74,6 @@ fn no_double_borrow_mut() { let x = RefCell::new(0); assert_eq!(x.borrow_state(), BorrowState::Unused); let _b1 = x.borrow_mut(); - assert!(x.try_borrow_mut().is_none()); assert_eq!(x.borrow_state(), BorrowState::Writing); } @@ -105,7 +102,7 @@ fn double_borrow_single_release_no_borrow_mut() { { let _b2 = x.borrow(); } - assert!(x.try_borrow_mut().is_none()); + assert_eq!(x.borrow_state(), BorrowState::Reading); } #[test] @@ -122,14 +119,14 @@ fn clone_ref_updates_flag() { let x = RefCell::new(0); { let b1 = x.borrow(); - assert!(x.try_borrow_mut().is_none()); + assert_eq!(x.borrow_state(), BorrowState::Reading); { let _b2 = clone_ref(&b1); - assert!(x.try_borrow_mut().is_none()); + assert_eq!(x.borrow_state(), BorrowState::Reading); } - assert!(x.try_borrow_mut().is_none()); + assert_eq!(x.borrow_state(), BorrowState::Reading); } - assert!(x.try_borrow_mut().is_some()); + assert_eq!(x.borrow_state(), BorrowState::Unused); } #[test] diff --git a/src/libcoretest/finally.rs b/src/libcoretest/finally.rs deleted file mode 100644 index 2a48395271d..00000000000 --- a/src/libcoretest/finally.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 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. - -#![allow(deprecated)] - -use core::finally::{try_finally, Finally}; -use std::thread; - -#[test] -fn test_success() { - let mut i = 0; - try_finally( - &mut i, (), - |i, ()| { - *i = 10; - }, - |i| { - assert!(!thread::panicking()); - assert_eq!(*i, 10); - *i = 20; - }); - assert_eq!(i, 20); -} - -#[test] -#[should_panic] -fn test_fail() { - let mut i = 0; - try_finally( - &mut i, (), - |i, ()| { - *i = 10; - panic!(); - }, - |i| { - assert!(thread::panicking()); - assert_eq!(*i, 10); - }) -} - -#[test] -fn test_retval() { - let mut closure = || 10; - // FIXME(#16640) `: i32` annotation shouldn't be necessary - let i: i32 = closure.finally(|| { }); - assert_eq!(i, 10); -} - -#[test] -fn test_compact() { - fn do_some_fallible_work() {} - fn but_always_run_this_function() { } - let mut f = do_some_fallible_work; - f.finally(but_always_run_this_function); -} diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 15938a5dcb4..af80d347f02 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -72,7 +72,7 @@ fn test_multi_iter() { #[test] fn test_counter_from_iter() { - let it = count(0, 5).take(10); + let it = (0..).step_by(5).take(10); let xs: Vec = FromIterator::from_iter(it); assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); } @@ -90,7 +90,7 @@ fn test_iterator_chain() { } assert_eq!(i, expected.len()); - let ys = count(30, 10).take(4); + let ys = (30..).step_by(10).take(4); let it = xs.iter().cloned().chain(ys); let mut i = 0; for x in it { @@ -102,7 +102,7 @@ fn test_iterator_chain() { #[test] fn test_filter_map() { - let it = count(0, 1).take(10) + let it = (0..).step_by(1).take(10) .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None }); assert_eq!(it.collect::>(), [0*0, 2*2, 4*4, 6*6, 8*8]); } @@ -244,7 +244,7 @@ fn test_iterator_scan() { fn test_iterator_flat_map() { let xs = [0, 3, 6]; let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let it = xs.iter().flat_map(|&x| count(x, 1).take(3)); + let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3)); let mut i = 0; for x in it { assert_eq!(x, ys[i]); @@ -291,13 +291,13 @@ fn test_unfoldr() { #[test] fn test_cycle() { let cycle_len = 3; - let it = count(0, 1).take(cycle_len).cycle(); + let it = (0..).step_by(1).take(cycle_len).cycle(); assert_eq!(it.size_hint(), (usize::MAX, None)); for (i, x) in it.take(100).enumerate() { assert_eq!(i % cycle_len, x); } - let mut it = count(0, 1).take(0).cycle(); + let mut it = (0..).step_by(1).take(0).cycle(); assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next(), None); } @@ -360,7 +360,7 @@ fn test_iterator_min() { #[test] fn test_iterator_size_hint() { - let c = count(0, 1); + let c = (0..).step_by(1); let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let v2 = &[10, 11, 12]; let vi = v.iter(); diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 9cc3063dee6..7ae0dcbb5f9 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -39,7 +39,6 @@ mod atomic; mod cell; mod char; mod cmp; -mod finally; mod fmt; mod hash; mod iter; diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs index 38cab4f0e09..c935b554574 100644 --- a/src/libcoretest/str.rs +++ b/src/libcoretest/str.rs @@ -163,9 +163,9 @@ fn starts_short_long() { #[test] fn contains_weird_cases() { - assert!("* \t".contains_char(' ')); - assert!(!"* \t".contains_char('?')); - assert!(!"* \t".contains_char('\u{1F4A9}')); + assert!("* \t".contains(' ')); + assert!(!"* \t".contains('?')); + assert!(!"* \t".contains('\u{1F4A9}')); } #[test] @@ -347,11 +347,11 @@ malesuada sollicitudin quam eu fermentum!"); make_test!(chars_count, s, s.chars().count()); make_test!(contains_bang_str, s, s.contains("!")); - make_test!(contains_bang_char, s, s.contains_char('!')); + make_test!(contains_bang_char, s, s.contains('!')); make_test!(match_indices_a_str, s, s.match_indices("a").count()); - make_test!(split_str_a_str, s, s.split_str("a").count()); + make_test!(split_a_str, s, s.split("a").count()); make_test!(trim_ascii_char, s, { use std::ascii::AsciiExt; @@ -368,11 +368,11 @@ malesuada sollicitudin quam eu fermentum!"); make_test!(find_underscore_char, s, s.find('_')); make_test!(rfind_underscore_char, s, s.rfind('_')); - make_test!(find_underscore_str, s, s.find_str("_")); + make_test!(find_underscore_str, s, s.find("_")); make_test!(find_zzz_char, s, s.find('\u{1F4A4}')); make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}')); - make_test!(find_zzz_str, s, s.find_str("\u{1F4A4}")); + make_test!(find_zzz_str, s, s.find("\u{1F4A4}")); make_test!(split_space_char, s, s.split(' ').count()); make_test!(split_terminator_space_char, s, s.split_terminator(' ').count()); @@ -380,6 +380,6 @@ malesuada sollicitudin quam eu fermentum!"); make_test!(splitn_space_char, s, s.splitn(10, ' ').count()); make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count()); - make_test!(split_str_space_str, s, s.split_str(" ").count()); - make_test!(split_str_ad_str, s, s.split_str("ad").count()); + make_test!(split_space_str, s, s.split(" ").count()); + make_test!(split_ad_str, s, s.split("ad").count()); } diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 91abb548d2e..44187a4fc99 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -198,7 +198,7 @@ impl Rand for ChaChaRng { for word in &mut key { *word = other.gen(); } - SeedableRng::from_seed(key.as_slice()) + SeedableRng::from_seed(&key[..]) } } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 60ae053dbaf..d71a68e2050 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -228,8 +228,9 @@ pub fn memoized(cache: &RefCell>, arg: T, f: F) -> #[cfg(unix)] pub fn path2cstr(p: &Path) -> CString { use std::os::unix::prelude::*; - use std::ffi::AsOsStr; - CString::new(p.as_os_str().as_bytes()).unwrap() + use std::ffi::OsStr; + let p: &OsStr = p.as_ref(); + CString::new(p.as_bytes()).unwrap() } #[cfg(windows)] pub fn path2cstr(p: &Path) -> CString { diff --git a/src/librustc_back/fs.rs b/src/librustc_back/fs.rs index 6d8891dd4fe..d3f3b1dad78 100644 --- a/src/librustc_back/fs.rs +++ b/src/librustc_back/fs.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::io; +use std::env; #[allow(deprecated)] use std::old_path::{self, GenericPath}; #[allow(deprecated)] use std::old_io; use std::path::{Path, PathBuf}; @@ -29,9 +30,9 @@ pub fn realpath(original: &Path) -> io::Result { #[allow(deprecated)] fn old_realpath(original: &old_path::Path) -> old_io::IoResult { use std::old_io::fs; - use std::os; const MAX_LINKS_FOLLOWED: usize = 256; - let original = try!(os::getcwd()).join(original); + let original = old_path::Path::new(env::current_dir().unwrap() + .to_str().unwrap()).join(original); // Right now lstat on windows doesn't work quite well if cfg!(windows) { diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index fe457841e91..0814d53acd1 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -39,12 +39,10 @@ #![feature(io)] #![feature(old_io)] #![feature(old_path)] -#![feature(os)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(rand)] #![feature(path_ext)] -#![feature(std_misc)] #![feature(step_by)] #![feature(convert)] #![cfg_attr(test, feature(test, rand))] diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs index 8f0387059e4..898f20e7451 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -14,7 +14,7 @@ #![allow(deprecated)] // to_be32 -use std::iter::{range_step, repeat}; +use std::iter::repeat; use std::num::Int; use std::slice::bytes::{MutableByteVector, copy_memory}; use serialize::hex::ToHex; @@ -368,7 +368,7 @@ impl Engine256State { // Putting the message schedule inside the same loop as the round calculations allows for // the compiler to generate better code. - for t in range_step(0, 48, 8) { + for t in (0..48).step_by(8) { schedule_round!(t + 16); schedule_round!(t + 17); schedule_round!(t + 18); @@ -388,7 +388,7 @@ impl Engine256State { sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7); } - for t in range_step(48, 64, 8) { + for t in (48..64).step_by(8) { sha2_round!(a, b, c, d, e, f, g, h, K32, t); sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1); sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2); diff --git a/src/librustc_back/tempdir.rs b/src/librustc_back/tempdir.rs index d4503ae7fc9..6935499f5a0 100644 --- a/src/librustc_back/tempdir.rs +++ b/src/librustc_back/tempdir.rs @@ -11,7 +11,7 @@ use std::env; use std::io::{self, Error, ErrorKind}; use std::fs; -use std::path::{self, PathBuf, AsPath}; +use std::path::{self, PathBuf, Path}; use std::rand::{thread_rng, Rng}; /// A wrapper for a path to temporary directory implementing automatic @@ -36,10 +36,10 @@ impl TempDir { /// /// If no directory can be created, `Err` is returned. #[allow(deprecated)] // rand usage - pub fn new_in(tmpdir: &P, prefix: &str) - -> io::Result { + pub fn new_in>(tmpdir: P, prefix: &str) + -> io::Result { let storage; - let mut tmpdir = tmpdir.as_path(); + let mut tmpdir = tmpdir.as_ref(); if !tmpdir.is_absolute() { let cur_dir = try!(env::current_dir()); storage = cur_dir.join(tmpdir); diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs index cc6a85e86ce..647f4bc6a40 100644 --- a/src/librustc_llvm/archive_ro.rs +++ b/src/librustc_llvm/archive_ro.rs @@ -42,8 +42,9 @@ impl ArchiveRO { #[cfg(unix)] fn path2cstr(p: &Path) -> CString { use std::os::unix::prelude::*; - use std::ffi::AsOsStr; - CString::new(p.as_os_str().as_bytes()).unwrap() + use std::ffi::OsStr; + let p: &OsStr = p.as_ref(); + CString::new(p.as_bytes()).unwrap() } #[cfg(windows)] fn path2cstr(p: &Path) -> CString { diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index c7b5b2e7534..cba2188ef79 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -30,7 +30,7 @@ #![feature(libc)] #![feature(link_args)] #![feature(staged_api)] -#![cfg_attr(unix, feature(std_misc))] +#![cfg_attr(unix, feature(convert))] extern crate libc; #[macro_use] #[no_link] extern crate rustc_bitflags; diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index 8c85eaff23c..f8c56b68577 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -20,7 +20,7 @@ pub use self::imp::Lock; #[cfg(unix)] mod imp { - use std::ffi::{AsOsStr, CString}; + use std::ffi::{CString, OsStr}; use std::os::unix::prelude::*; use std::path::Path; use std::io; @@ -116,7 +116,8 @@ mod imp { impl Lock { pub fn new(p: &Path) -> Lock { - let buf = CString::new(p.as_os_str().as_bytes()).unwrap(); + let os: &OsStr = p.as_ref(); + let buf = CString::new(os.as_bytes()).unwrap(); let fd = unsafe { libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT, libc::S_IRWXU) @@ -164,9 +165,9 @@ mod imp { #[cfg(windows)] mod imp { use libc; - use std::ffi::AsOsStr; use std::io; use std::mem; + use std::ffi::OsStr; use std::os::windows::prelude::*; use std::path::Path; use std::ptr; @@ -194,7 +195,8 @@ mod imp { impl Lock { pub fn new(p: &Path) -> Lock { - let mut p_16: Vec<_> = p.as_os_str().encode_wide().collect(); + let p: &OsStr = p.as_ref(); + let mut p_16: Vec<_> = p.encode_wide().collect(); p_16.push(0); let handle = unsafe { libc::CreateFileW(p_16.as_ptr(), diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index aa3195cbf01..053ceceb496 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -15,7 +15,7 @@ use self::BucketState::*; use clone::Clone; use cmp; use hash::{Hash, Hasher}; -use iter::{Iterator, ExactSizeIterator, count}; +use iter::{Iterator, ExactSizeIterator}; use marker::{Copy, Send, Sync, Sized, self}; use mem::{min_align_of, size_of}; use mem; diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index d8a95133d94..9a68a60361c 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -18,7 +18,7 @@ use prelude::v1::*; use env; -use ffi::{AsOsStr, CString, OsString}; +use ffi::{CString, OsString}; use mem; use path::{Path, PathBuf}; diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 71f072302fb..ec0e4b6737f 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -20,7 +20,7 @@ use prelude::v1::*; use iter::IntoIterator; use error::Error; -use ffi::{OsString, AsOsStr}; +use ffi::{OsStr, OsString}; use fmt; use io; use path::{Path, PathBuf}; @@ -176,7 +176,7 @@ impl Iterator for VarsOs { /// } /// ``` #[stable(feature = "env", since = "1.0.0")] -pub fn var(key: &K) -> Result where K: AsOsStr { +pub fn var(key: &K) -> Result where K: AsRef { match var_os(key) { Some(s) => s.into_string().map_err(VarError::NotUnicode), None => Err(VarError::NotPresent) @@ -198,9 +198,9 @@ pub fn var(key: &K) -> Result where K: AsOsStr { /// } /// ``` #[stable(feature = "env", since = "1.0.0")] -pub fn var_os(key: &K) -> Option where K: AsOsStr { +pub fn var_os(key: &K) -> Option where K: AsRef { let _g = ENV_LOCK.lock(); - os_imp::getenv(key.as_os_str()) + os_imp::getenv(key.as_ref()) } /// Possible errors from the `env::var` method. @@ -255,17 +255,17 @@ impl Error for VarError { /// ``` #[stable(feature = "env", since = "1.0.0")] pub fn set_var(k: &K, v: &V) - where K: AsOsStr, V: AsOsStr + where K: AsRef, V: AsRef { let _g = ENV_LOCK.lock(); - os_imp::setenv(k.as_os_str(), v.as_os_str()) + os_imp::setenv(k.as_ref(), v.as_ref()) } /// Remove a variable from the environment entirely. #[stable(feature = "env", since = "1.0.0")] -pub fn remove_var(k: &K) where K: AsOsStr { +pub fn remove_var(k: &K) where K: AsRef { let _g = ENV_LOCK.lock(); - os_imp::unsetenv(k.as_os_str()) + os_imp::unsetenv(k.as_ref()) } /// An iterator over `Path` instances for parsing an environment variable @@ -296,8 +296,8 @@ pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> } /// } /// ``` #[stable(feature = "env", since = "1.0.0")] -pub fn split_paths(unparsed: &T) -> SplitPaths { - SplitPaths { inner: os_imp::split_paths(unparsed.as_os_str()) } +pub fn split_paths + ?Sized>(unparsed: &T) -> SplitPaths { + SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) } } #[stable(feature = "env", since = "1.0.0")] @@ -340,7 +340,7 @@ pub struct JoinPathsError { /// ``` #[stable(feature = "env", since = "1.0.0")] pub fn join_paths(paths: I) -> Result - where I: IntoIterator, T: AsOsStr + where I: IntoIterator, T: AsRef { os_imp::join_paths(paths.into_iter()).map_err(|e| { JoinPathsError { inner: e } @@ -740,7 +740,7 @@ mod tests { let mut rng = rand::thread_rng(); let n = format!("TEST{}", rng.gen_ascii_chars().take(10) .collect::()); - let n = OsString::from_string(n); + let n = OsString::from(n); assert!(var_os(&n).is_none()); n } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index a00f7708025..544d6bcc2c6 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -132,15 +132,6 @@ pub struct CStr { #[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 -/// be converted to a vector of bytes. -#[deprecated(since = "1.0.0", reason = "use std::convert::Into> instead")] -#[unstable(feature = "std_misc")] -pub trait IntoBytes { - /// Consumes this container, returning a vector of bytes. - fn into_bytes(self) -> Vec; -} - impl CString { /// Create a new C-compatible string from a container of bytes. /// @@ -178,57 +169,6 @@ impl CString { } } - /// Create a new C-compatible string from a byte slice. - /// - /// This method will copy the data of the slice provided into a new - /// allocation, ensuring that there is a trailing 0 byte. - /// - /// # Examples - /// - /// ```no_run - /// # #![feature(libc)] - /// extern crate libc; - /// use std::ffi::CString; - /// - /// extern { fn puts(s: *const libc::c_char); } - /// - /// fn main() { - /// let to_print = CString::new("Hello!").unwrap(); - /// unsafe { - /// puts(to_print.as_ptr()); - /// } - /// } - /// ``` - /// - /// # Panics - /// - /// This function will panic if the provided slice contains any - /// interior nul bytes. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", reason = "use CString::new instead")] - #[allow(deprecated)] - pub fn from_slice(v: &[u8]) -> CString { - CString::from_vec(v.to_vec()) - } - - /// Create a C-compatible string from a byte vector. - /// - /// This method will consume ownership of the provided vector, appending a 0 - /// byte to the end after verifying that there are no interior 0 bytes. - /// - /// # Panics - /// - /// This function will panic if the provided slice contains any - /// interior nul bytes. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", reason = "use CString::new instead")] - pub fn from_vec(v: Vec) -> CString { - match v.iter().position(|x| *x == 0) { - Some(i) => panic!("null byte found in slice at: {}", i), - None => unsafe { CString::from_vec_unchecked(v) }, - } - } - /// Create a C-compatible string from a byte vector without checking for /// interior 0 bytes. /// @@ -424,41 +364,6 @@ impl Ord for CStr { } } -/// Deprecated in favor of `CStr` -#[unstable(feature = "std_misc")] -#[deprecated(since = "1.0.0", reason = "use CStr::from_ptr(p).to_bytes() instead")] -pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] { - let len = libc::strlen(*raw); - slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize) -} - -/// Deprecated in favor of `CStr` -#[unstable(feature = "std_misc")] -#[deprecated(since = "1.0.0", - reason = "use CStr::from_ptr(p).to_bytes_with_nul() instead")] -pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) - -> &'a [u8] { - let len = libc::strlen(*raw) + 1; - slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize) -} - -#[allow(deprecated)] -impl<'a> IntoBytes for &'a str { - fn into_bytes(self) -> Vec { self.as_bytes().to_vec() } -} -#[allow(deprecated)] -impl<'a> IntoBytes for &'a [u8] { - fn into_bytes(self) -> Vec { self.to_vec() } -} -#[allow(deprecated)] -impl IntoBytes for String { - fn into_bytes(self) -> Vec { self.into_bytes() } -} -#[allow(deprecated)] -impl IntoBytes for Vec { - fn into_bytes(self) -> Vec { self } -} - #[cfg(test)] mod tests { use prelude::v1::*; diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index f17dc654249..1b7e913d46c 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -13,17 +13,10 @@ #![stable(feature = "rust1", since = "1.0.0")] #[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; +pub use self::c_str::{CString, CStr, NulError}; #[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; +pub use self::os_str::{OsString, OsStr}; mod c_str; mod os_str; diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 49dbac4585b..d9a6a1006f4 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -29,7 +29,7 @@ //! for conversion to/from various other string types. Eventually these types //! will offer a full-fledged string API. -#![unstable(feature = "os", +#![unstable(feature = "os_str", reason = "recently added as part of path/io reform")] use core::prelude::*; @@ -61,22 +61,6 @@ pub struct OsStr { } impl OsString { - /// Constructs an `OsString` at no cost by consuming a `String`. - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", reason = "use `from` instead")] - pub fn from_string(s: String) -> OsString { - OsString::from(s) - } - - /// 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")] - #[deprecated(since = "1.0.0", reason = "use `from` instead")] - pub fn from_str(s: &str) -> OsString { - OsString::from(s) - } - /// Constructs a new empty `OsString`. #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> OsString { @@ -91,13 +75,6 @@ impl OsString { 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) { diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs.rs similarity index 99% rename from src/libstd/fs/mod.rs rename to src/libstd/fs.rs index a3128ef0f8d..071e5b5c28c 100644 --- a/src/libstd/fs/mod.rs +++ b/src/libstd/fs.rs @@ -25,11 +25,6 @@ use sys::fs2 as fs_imp; use sys_common::{AsInnerMut, FromInner, AsInner}; use vec::Vec; -#[allow(deprecated)] -pub use self::tempdir::TempDir; - -mod tempdir; - /// A reference to an open file on the filesystem. /// /// An instance of a `File` can be read and/or written depending on what options @@ -1327,7 +1322,7 @@ mod tests { check!(fs::copy(&input, &out)); let mut v = Vec::new(); check!(check!(File::open(&out)).read_to_end(&mut v)); - assert_eq!(v.as_slice(), b"hello"); + assert_eq!(v, b"hello"); assert_eq!(check!(input.metadata()).permissions(), check!(out.metadata()).permissions()); @@ -1622,7 +1617,7 @@ mod tests { check!(check!(File::create(&tmpdir.join("test"))).write(&bytes)); let mut v = Vec::new(); check!(check!(File::open(&tmpdir.join("test"))).read_to_end(&mut v)); - assert!(v == bytes.as_slice()); + assert!(v == &bytes[..]); } #[test] diff --git a/src/libstd/fs/tempdir.rs b/src/libstd/fs/tempdir.rs deleted file mode 100644 index 8cc1dde98a0..00000000000 --- a/src/libstd/fs/tempdir.rs +++ /dev/null @@ -1,127 +0,0 @@ -// 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. - -#![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::*; - -use env; -use io::{self, Error, ErrorKind}; -use fs; -use path::{self, PathBuf}; -use 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: usize = 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_ref(); - 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::AlreadyExists => {} - Err(e) => return Err(e) - } - } - - Err(Error::new(ErrorKind::AlreadyExists, - "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/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index d8e403376bd..ad81143b7b4 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -281,19 +281,19 @@ mod tests { #[test] fn test_slice_reader() { let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; - let mut reader = &mut in_buf.as_slice(); + let mut reader = &mut &in_buf[..]; let mut buf = []; assert_eq!(reader.read(&mut buf), Ok(0)); let mut buf = [0]; assert_eq!(reader.read(&mut buf), Ok(1)); assert_eq!(reader.len(), 7); let b: &[_] = &[0]; - assert_eq!(buf.as_slice(), b); + assert_eq!(&buf[..], b); let mut buf = [0; 4]; assert_eq!(reader.read(&mut buf), Ok(4)); assert_eq!(reader.len(), 3); let b: &[_] = &[1, 2, 3, 4]; - assert_eq!(buf.as_slice(), b); + assert_eq!(&buf[..], b); assert_eq!(reader.read(&mut buf), Ok(3)); let b: &[_] = &[5, 6, 7]; assert_eq!(&buf[..3], b); @@ -303,7 +303,7 @@ mod tests { #[test] fn test_buf_reader() { let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; - let mut reader = Cursor::new(in_buf.as_slice()); + let mut reader = Cursor::new(&in_buf[..]); let mut buf = []; assert_eq!(reader.read(&mut buf), Ok(0)); assert_eq!(reader.position(), 0); diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index f445ace081e..615df771e9b 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -9,7 +9,6 @@ // except according to those terms. use boxed::Box; -use clone::Clone; use error; use fmt; use option::Option::{self, Some, None}; @@ -179,27 +178,6 @@ impl Error { Repr::Custom(ref c) => c.kind, } } - - /// Returns a short description for this error message - #[unstable(feature = "io")] - #[deprecated(since = "1.0.0", reason = "use the Error trait's description \ - method instead")] - pub fn description(&self) -> &str { - match self.repr { - Repr::Os(..) => "os error", - Repr::Custom(ref c) => c.desc, - } - } - - /// Returns a detailed error message for this error (if one is available) - #[unstable(feature = "io")] - #[deprecated(since = "1.0.0", reason = "use the to_string() method instead")] - pub fn detail(&self) -> Option { - match self.repr { - Repr::Os(code) => Some(sys::os::error_string(code)), - Repr::Custom(ref s) => s.detail.clone(), - } - } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index b7cb8f9ed50..578e057cbb6 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -173,8 +173,6 @@ pub use core::clone; #[cfg(not(test))] pub use core::cmp; pub use core::convert; pub use core::default; -#[allow(deprecated)] -pub use core::finally; pub use core::hash; pub use core::intrinsics; pub use core::iter; diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 869faa795f9..9611e40e1e9 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -100,13 +100,6 @@ impl TcpStream { self.0.peer_addr() } - /// Returns the socket address of the local half of this TCP connection. - #[unstable(feature = "net")] - #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] - pub fn socket_addr(&self) -> io::Result { - self.0.socket_addr() - } - /// Returns the socket address of the local half of this TCP connection. #[stable(feature = "rust1", since = "1.0.0")] pub fn local_addr(&self) -> io::Result { @@ -195,13 +188,6 @@ impl TcpListener { self.0.socket_addr() } - /// Deprecated, renamed to local_addr - #[unstable(feature = "net")] - #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] - pub fn socket_addr(&self) -> io::Result { - self.0.socket_addr() - } - /// Create a new independently owned handle to the underlying socket. /// /// The returned `TcpListener` is a reference to the same socket that this @@ -349,7 +335,7 @@ mod tests { let _t = thread::spawn(move|| { let mut stream = t!(TcpStream::connect(&addr)); t!(stream.write(&[99])); - tx.send(t!(stream.socket_addr())).unwrap(); + tx.send(t!(stream.local_addr())).unwrap(); }); let (mut stream, addr) = t!(acceptor.accept()); @@ -499,7 +485,7 @@ mod tests { fn socket_and_peer_name_ip4() { each_ip(&mut |addr| { let listener = t!(TcpListener::bind(&addr)); - let so_name = t!(listener.socket_addr()); + let so_name = t!(listener.local_addr()); assert_eq!(addr, so_name); let _t = thread::spawn(move|| { t!(listener.accept()); diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 81151114962..85831c2de34 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -80,13 +80,6 @@ impl UdpSocket { } } - /// Returns the socket address that this socket was created from. - #[unstable(feature = "net")] - #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] - pub fn socket_addr(&self) -> io::Result { - self.0.socket_addr() - } - /// Returns the socket address that this socket was created from. #[stable(feature = "rust1", since = "1.0.0")] pub fn local_addr(&self) -> io::Result { @@ -203,7 +196,7 @@ mod tests { fn socket_name_ip4() { each_ip(&mut |addr, _| { let server = t!(UdpSocket::bind(&addr)); - assert_eq!(addr, t!(server.socket_addr())); + assert_eq!(addr, t!(server.local_addr())); }) } diff --git a/src/libstd/old_io/fs.rs b/src/libstd/old_io/fs.rs index 6aa63c395c6..bef6ea53e50 100644 --- a/src/libstd/old_io/fs.rs +++ b/src/libstd/old_io/fs.rs @@ -951,7 +951,8 @@ mod test { pub fn tmpdir() -> TempDir { use os; use rand; - let ret = os::tmpdir().join(format!("rust-{}", rand::random::())); + let temp = Path::new(::env::temp_dir().to_str().unwrap()); + let ret = temp.join(format!("rust-{}", rand::random::())); check!(old_io::fs::mkdir(&ret, old_io::USER_RWX)); TempDir(ret) } @@ -1639,7 +1640,7 @@ mod test { check!(File::create(&tmpdir.join("test")).write(&bytes)); let actual = check!(File::open(&tmpdir.join("test")).read_to_end()); - assert!(actual == bytes.as_slice()); + assert!(actual == &bytes[..]); } #[test] diff --git a/src/libstd/old_io/mem.rs b/src/libstd/old_io/mem.rs index 64803191d4f..c92e74fbc56 100644 --- a/src/libstd/old_io/mem.rs +++ b/src/libstd/old_io/mem.rs @@ -399,7 +399,7 @@ impl<'a> Buffer for BufReader<'a> { mod test { extern crate test as test_crate; use old_io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek, Buffer}; - use prelude::v1::{Ok, Err, Vec, AsSlice}; + use prelude::v1::{Ok, Err, Vec}; use prelude::v1::Iterator; use old_io; use iter::repeat; @@ -744,7 +744,7 @@ mod test { wr.write(&[5; 10]).unwrap(); } } - assert_eq!(buf.as_slice(), [5; 100].as_slice()); + assert_eq!(&buf[..], &[5; 100][..]); }); } diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index df8ac78f7e5..9d7e1082d33 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -274,7 +274,7 @@ use mem::transmute; use ops::FnOnce; use option::Option; use option::Option::{Some, None}; -use os; +use sys::os; use boxed::Box; use result::Result; use result::Result::{Ok, Err}; diff --git a/src/libstd/old_io/pipe.rs b/src/libstd/old_io/pipe.rs index 26f24600479..fd1df49473e 100644 --- a/src/libstd/old_io/pipe.rs +++ b/src/libstd/old_io/pipe.rs @@ -124,9 +124,9 @@ mod test { use os; use old_io::pipe::PipeStream; - let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() }; - let out = PipeStream::open(writer); - let mut input = PipeStream::open(reader); + let (reader, writer) = unsafe { ::sys::os::pipe().unwrap() }; + let out = PipeStream::open(writer.unwrap()); + let mut input = PipeStream::open(reader.unwrap()); let (tx, rx) = channel(); let _t = thread::spawn(move|| { let mut out = out; diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index 06940bf6860..d0fa7dd6882 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -246,7 +246,7 @@ impl Command { None => { // if the env is currently just inheriting from the parent's, // materialize the parent's env into a hashtable. - self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| { + self.env = Some(::env::vars().map(|(k, v)| { (EnvKey(CString::new(k).unwrap()), CString::new(v).unwrap()) }).collect()); @@ -764,11 +764,9 @@ impl Drop for Process { #[cfg(test)] mod tests { + use prelude::v1::*; use old_io::{Truncate, Write, TimedOut, timer, process, FileNotFound}; use old_io::{Reader, Writer}; - use prelude::v1::{Ok, Err, drop, Some, None, Vec}; - use prelude::v1::{String, Clone}; - use prelude::v1::{Str, AsSlice, ToString}; use old_path::{GenericPath, Path}; use old_io::fs::PathExtensions; use old_io::timer::*; @@ -1003,7 +1001,7 @@ mod tests { let prog = pwd_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); - let parent_dir = os::getcwd().unwrap(); + let parent_dir = Path::new(::env::current_dir().unwrap().to_str().unwrap()); let child_dir = Path::new(output.trim()); let parent_stat = parent_dir.stat().unwrap(); @@ -1018,7 +1016,7 @@ mod tests { use os; // test changing to the parent of os::getcwd() because we know // the path exists (and os::getcwd() is not expected to be root) - let parent_dir = os::getcwd().unwrap().dir_path(); + let parent_dir = Path::new(::env::current_dir().unwrap().to_str().unwrap()); let prog = pwd_cmd().cwd(&parent_dir).spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); @@ -1058,11 +1056,11 @@ mod tests { let prog = env_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); - let r = os::env(); - for &(ref k, ref v) in &r { + let r = ::env::vars(); + for (k, v) in r { // don't check windows magical empty-named variables assert!(k.is_empty() || - output.contains(&format!("{}={}", *k, *v)), + output.contains(&format!("{}={}", k, v)), "output doesn't contain `{}={}`\n{}", k, v, output); } @@ -1076,16 +1074,12 @@ mod tests { let mut prog = env_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); - let r = os::env(); - for &(ref k, ref v) in &r { + let r = env::vars(); + for (k, v) in r { // don't check android RANDOM variables - if *k != "RANDOM".to_string() { - assert!(output.contains(&format!("{}={}", - *k, - *v)) || - output.contains(&format!("{}=\'{}\'", - *k, - *v))); + if k != "RANDOM".to_string() { + assert!(output.contains(&format!("{}={}", k, v)) || + output.contains(&format!("{}=\'{}\'", k, v))); } } } @@ -1100,9 +1094,9 @@ mod tests { // PATH to our sub-process. let path_val: String; let mut new_env = vec![("RUN_TEST_NEW_ENV", "123")]; - match os::getenv("PATH") { - None => {} - Some(val) => { + match ::env::var("PATH") { + Err(..) => {} + Ok(val) => { path_val = val; new_env.push(("PATH", &path_val)) } diff --git a/src/libstd/old_io/tempfile.rs b/src/libstd/old_io/tempfile.rs index 0a2cc517a06..94faa5540bb 100644 --- a/src/libstd/old_io/tempfile.rs +++ b/src/libstd/old_io/tempfile.rs @@ -100,7 +100,8 @@ impl TempDir { #[allow(deprecated)] pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult { if !tmpdir.is_absolute() { - let cur_dir = try!(::os::getcwd()); + let cur_dir = ::env::current_dir().unwrap(); + let cur_dir = Path::new(cur_dir.to_str().unwrap()); return TempDir::new_in(&cur_dir.join(tmpdir), prefix); } @@ -136,7 +137,8 @@ impl TempDir { /// If no directory can be created, `Err` is returned. #[allow(deprecated)] pub fn new(prefix: &str) -> IoResult { - TempDir::new_in(&::os::tmpdir(), prefix) + let tmp = Path::new(::env::temp_dir().to_str().unwrap()); + TempDir::new_in(&tmp, prefix) } /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper. diff --git a/src/libstd/old_io/test.rs b/src/libstd/old_io/test.rs index db409ecde45..8c46e2c06b8 100644 --- a/src/libstd/old_io/test.rs +++ b/src/libstd/old_io/test.rs @@ -43,7 +43,7 @@ fn next_test_unix_socket() -> String { pub fn next_test_unix() -> Path { let string = next_test_unix_socket(); if cfg!(unix) { - ::os::tmpdir().join(string) + Path::new(::env::temp_dir().to_str().unwrap()).join(string) } else { Path::new(format!("{}{}", r"\\.\pipe\", string)) } diff --git a/src/libstd/old_path/mod.rs b/src/libstd/old_path/mod.rs index c405df2824e..9c88533d3ba 100644 --- a/src/libstd/old_path/mod.rs +++ b/src/libstd/old_path/mod.rs @@ -69,12 +69,13 @@ use core::marker::Sized; use ffi::CString; use clone::Clone; +use borrow::Cow; use fmt; use iter::Iterator; use option::Option; use option::Option::{None, Some}; use str; -use string::{String, CowString}; +use string::String; use vec::Vec; /// Typedef for POSIX file paths. @@ -907,7 +908,7 @@ impl<'a, P: GenericPath> Display<'a, P> { /// If the path is not UTF-8, invalid sequences will be replaced with the /// Unicode replacement char. This involves allocation. #[inline] - pub fn as_cow(&self) -> CowString<'a> { + pub fn as_cow(&self) -> Cow<'a, str> { String::from_utf8_lossy(if self.filename { match self.path.filename() { None => { diff --git a/src/libstd/old_path/posix.rs b/src/libstd/old_path/posix.rs index bbc1756bee6..f215e73202c 100644 --- a/src/libstd/old_path/posix.rs +++ b/src/libstd/old_path/posix.rs @@ -20,7 +20,7 @@ use iter::{Iterator, Map}; use marker::Sized; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; -use slice::{AsSlice, Split, SliceConcatExt}; +use slice::{Split, SliceConcatExt}; use str::{self, FromStr}; use vec::Vec; @@ -339,11 +339,11 @@ impl Path { /// Returns a normalized byte vector representation of a path, by removing all empty /// components, and unnecessary . and .. components. - fn normalize>(v: &V) -> Vec { + fn normalize(v: &[u8]) -> Vec { // borrowck is being very picky let val = { - let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == SEP_BYTE; - let v_ = if is_abs { &v.as_slice()[1..] } else { v.as_slice() }; + let is_abs = !v.is_empty() && v[0] == SEP_BYTE; + let v_ = if is_abs { &v[1..] } else { v }; let comps = normalize_helper(v_, is_abs); match comps { None => None, @@ -371,7 +371,7 @@ impl Path { } }; match val { - None => v.as_slice().to_vec(), + None => v.to_vec(), Some(val) => val } } @@ -446,8 +446,7 @@ mod tests { use clone::Clone; use option::Option::{self, Some, None}; use old_path::GenericPath; - use slice::AsSlice; - use str::{self, Str}; + use str; use string::ToString; use vec::Vec; use iter::Iterator; diff --git a/src/libstd/old_path/windows.rs b/src/libstd/old_path/windows.rs index bd67855bf1b..0b88f368b39 100644 --- a/src/libstd/old_path/windows.rs +++ b/src/libstd/old_path/windows.rs @@ -1129,8 +1129,6 @@ mod tests { use iter::Iterator; use option::Option::{self, Some, None}; use old_path::GenericPath; - use slice::AsSlice; - use str::Str; use string::ToString; use vec::Vec; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index e19c734b8a3..ee0f04cb991 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -8,1826 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Higher-level interfaces to libc::* functions and operating system services. -//! -//! In general these take and return rust types, use rust idioms (enums, -//! closures, vectors) rather than C idioms, and do more extensive safety -//! checks. -//! -//! This module is not meant to only contain 1:1 mappings to libc entries; any -//! os-interface code that is reasonably useful and broadly applicable can go -//! here. Including utility routines that merely build on other os code. -//! -//! We assume the general case is that users do not care, and do not want to be -//! made to care, which operating system they are on. While they may want to -//! special case various special cases -- and so we will not _hide_ the facts of -//! which OS the user is on -- they should be given the opportunity to write -//! OS-ignorant code by default. +//! OS-specific functionality -#![unstable(feature = "os")] -#![deprecated(since = "1.0.0", reason = "replaced with std::env APIs")] - -#![allow(missing_docs)] -#![allow(non_snake_case)] -#![allow(unused_imports)] -#![allow(deprecated)] - -use self::MemoryMapKind::*; -use self::MapOption::*; -use self::MapError::*; - -use boxed::Box; -use clone::Clone; -use convert::From; -use env; -use error::{FromError, Error}; -use ffi::{OsString, OsStr}; -use fmt; -use iter::Iterator; -use libc::{c_void, c_int, c_char}; -use libc; -use marker::{Copy, Send}; -use old_io::{IoResult, IoError}; -use ops::{Drop, FnOnce}; -use option::Option::{Some, None}; -use option::Option; -use old_path::{Path, GenericPath, BytesContainer}; -use path::{self, PathBuf}; -use ptr; -use result::Result::{Err, Ok}; -use result::Result; -use slice::AsSlice; -use str::Str; -use str; -use string::{String, ToString}; -use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering}; -use sys::os as os_imp; -use sys; -use vec::Vec; - -#[cfg(unix)] use ffi::{self, CString}; +#![stable(feature = "os", since = "1.0.0")] #[cfg(unix)] pub use sys::ext as unix; #[cfg(windows)] pub use sys::ext as windows; - -fn err2old(new: ::io::Error) -> IoError { - IoError { - kind: ::old_io::OtherIoError, - desc: "os error", - detail: Some(new.to_string()), - } -} - -#[cfg(windows)] -fn path2new(path: &Path) -> PathBuf { - PathBuf::from(path.as_str().unwrap()) -} -#[cfg(unix)] -fn path2new(path: &Path) -> PathBuf { - use os::unix::prelude::*; - PathBuf::from(::from_bytes(path.as_vec())) -} - -#[cfg(unix)] -fn path2old(path: &path::Path) -> Path { - use os::unix::prelude::*; - use ffi::AsOsStr; - Path::new(path.as_os_str().as_bytes()) -} -#[cfg(windows)] -fn path2old(path: &path::Path) -> Path { - Path::new(path.to_str().unwrap()) -} - -/// Get the number of cores available -pub fn num_cpus() -> usize { - unsafe { - return rust_get_num_cpus() as usize; - } - - extern { - fn rust_get_num_cpus() -> libc::uintptr_t; - } -} - -pub const TMPBUF_SZ : usize = 1000; - -/// Returns the current working directory as a `Path`. -/// -/// # Errors -/// -/// Returns an `Err` if the current working directory value is invalid. -/// Possible cases: -/// -/// * Current directory does not exist. -/// * There are insufficient permissions to access the current directory. -/// * The internal buffer is not large enough to hold the path. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// // We assume that we are in a valid directory. -/// let current_working_directory = os::getcwd().unwrap(); -/// println!("The current directory is {:?}", current_working_directory.display()); -/// ``` -#[unstable(feature = "os")] -pub fn getcwd() -> IoResult { - env::current_dir().map_err(err2old).map(|s| path2old(&s)) -} - -/// Returns a vector of (variable, value) pairs, for all the environment -/// variables of the current process. -/// -/// Invalid UTF-8 bytes are replaced with \uFFFD. See `String::from_utf8_lossy()` -/// for details. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os)] -/// use std::os; -/// -/// // We will iterate through the references to the element returned by os::env(); -/// for &(ref key, ref value) in os::env().iter() { -/// println!("'{}': '{}'", key, value ); -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "use env::vars instead")] -#[unstable(feature = "os")] -pub fn env() -> Vec<(String,String)> { - env::vars_os().map(|(k, v)| { - (k.to_string_lossy().into_owned(), v.to_string_lossy().into_owned()) - }).collect() -} - -/// Returns a vector of (variable, value) byte-vector pairs for all the -/// environment variables of the current process. -#[deprecated(since = "1.0.0", reason = "use env::vars_os instead")] -#[unstable(feature = "os")] -pub fn env_as_bytes() -> Vec<(Vec, Vec)> { - env::vars_os().map(|(k, v)| (byteify(k), byteify(v))).collect() -} - -/// Fetches the environment variable `n` from the current process, returning -/// None if the variable isn't set. -/// -/// Any invalid UTF-8 bytes in the value are replaced by \uFFFD. See -/// `String::from_utf8_lossy()` for details. -/// -/// # Panics -/// -/// Panics if `n` has any interior NULs. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os)] -/// use std::os; -/// -/// let key = "HOME"; -/// match os::getenv(key) { -/// Some(val) => println!("{}: {}", key, val), -/// None => println!("{} is not defined in the environment.", key) -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "use env::var instead")] -#[unstable(feature = "os")] -pub fn getenv(n: &str) -> Option { - env::var(n).ok() -} - -/// Fetches the environment variable `n` byte vector from the current process, -/// returning None if the variable isn't set. -/// -/// # Panics -/// -/// Panics if `n` has any interior NULs. -#[deprecated(since = "1.0.0", reason = "use env::var_os instead")] -#[unstable(feature = "os")] -pub fn getenv_as_bytes(n: &str) -> Option> { - env::var_os(n).map(byteify) -} - -#[cfg(unix)] -fn byteify(s: OsString) -> Vec { - use os::unix::prelude::*; - s.into_vec() -} -#[cfg(windows)] -fn byteify(s: OsString) -> Vec { - s.to_string_lossy().as_bytes().to_vec() -} - -/// Sets the environment variable `n` to the value `v` for the currently running -/// process. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os)] -/// use std::os; -/// -/// let key = "KEY"; -/// os::setenv(key, "VALUE"); -/// match os::getenv(key) { -/// Some(ref val) => println!("{}: {}", key, val), -/// None => println!("{} is not defined in the environment.", key) -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::set_var")] -#[unstable(feature = "os")] -pub fn setenv(n: &str, v: T) { - #[cfg(unix)] - fn _setenv(n: &str, v: &[u8]) { - use os::unix::prelude::*; - let v: OsString = OsStringExt::from_vec(v.to_vec()); - env::set_var(n, &v) - } - - #[cfg(windows)] - fn _setenv(n: &str, v: &[u8]) { - let v = str::from_utf8(v).unwrap(); - env::set_var(n, v) - } - - _setenv(n, v.container_as_bytes()) -} - -/// Remove a variable from the environment entirely. -#[deprecated(since = "1.0.0", reason = "renamed to env::remove_var")] -#[unstable(feature = "os")] -pub fn unsetenv(n: &str) { - env::remove_var(n) -} - -/// Parses input according to platform conventions for the `PATH` -/// environment variable. -/// -/// # Examples -/// -/// ``` -/// # #![feature(old_path, os)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// let key = "PATH"; -/// match os::getenv_as_bytes(key) { -/// Some(paths) => { -/// for path in os::split_paths(paths).iter() { -/// println!("'{}'", path.display()); -/// } -/// } -/// None => println!("{} is not defined in the environment.", key) -/// } -/// ``` -#[unstable(feature = "os")] -pub fn split_paths(unparsed: T) -> Vec { - let b = unparsed.container_as_bytes(); - let s = str::from_utf8(b).unwrap(); - env::split_paths(s).map(|s| path2old(&s)).collect() -} - -/// Joins a collection of `Path`s appropriately for the `PATH` -/// environment variable. -/// -/// Returns a `Vec` on success, since `Path`s are not utf-8 -/// encoded on all platforms. -/// -/// Returns an `Err` (containing an error message) if one of the input -/// `Path`s contains an invalid character for constructing the `PATH` -/// variable (a double quote on Windows or a colon on Unix). -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path, core)] -/// use std::os; -/// use std::old_path::Path; -/// -/// let key = "PATH"; -/// let mut paths = os::getenv_as_bytes(key).map_or(Vec::new(), os::split_paths); -/// paths.push(Path::new("/home/xyz/bin")); -/// os::setenv(key, os::join_paths(paths.as_slice()).unwrap()); -/// ``` -#[unstable(feature = "os")] -pub fn join_paths(paths: &[T]) -> Result, &'static str> { - env::join_paths(paths.iter().map(|s| { - str::from_utf8(s.container_as_bytes()).unwrap() - })).map(|s| { - s.to_string_lossy().into_owned().into_bytes() - }).map_err(|_| "failed to join paths") -} - -/// A low-level OS in-memory pipe. -#[derive(Copy)] -pub struct Pipe { - /// A file descriptor representing the reading end of the pipe. Data written - /// on the `out` file descriptor can be read from this file descriptor. - pub reader: c_int, - /// A file descriptor representing the write end of the pipe. Data written - /// to this file descriptor can be read from the `input` file descriptor. - pub writer: c_int, -} - -/// Creates a new low-level OS in-memory pipe. -/// -/// This function can fail to succeed if there are no more resources available -/// to allocate a pipe. -/// -/// This function is also unsafe as there is no destructor associated with the -/// `Pipe` structure will return. If it is not arranged for the returned file -/// descriptors to be closed, the file descriptors will leak. For safe handling -/// of this scenario, use `std::old_io::PipeStream` instead. -pub unsafe fn pipe() -> IoResult { - let (reader, writer) = try!(sys::os::pipe()); - Ok(Pipe { - reader: reader.unwrap(), - writer: writer.unwrap(), - }) -} - -/// Returns the proper dll filename for the given basename of a file -/// as a String. -#[cfg(not(target_os="ios"))] -#[deprecated(since = "1.0.0", reason = "this function will be removed, use the constants directly")] -#[unstable(feature = "os")] -#[allow(deprecated)] -pub fn dll_filename(base: &str) -> String { - format!("{}{}{}", consts::DLL_PREFIX, base, consts::DLL_SUFFIX) -} - -/// Optionally returns the filesystem path to the current executable which is -/// running but with the executable name. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// match os::self_exe_name() { -/// Some(exe_path) => println!("Path of this executable is: {}", exe_path.display()), -/// None => println!("Unable to get the path of this executable!") -/// }; -/// ``` -#[unstable(feature = "os")] -pub fn self_exe_name() -> Option { - env::current_exe().ok().map(|p| path2old(&p)) -} - -/// Optionally returns the filesystem path to the current executable which is -/// running. -/// -/// Like self_exe_name() but without the binary's name. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// match os::self_exe_path() { -/// Some(exe_path) => println!("Executable's Path is: {}", exe_path.display()), -/// None => println!("Impossible to fetch the path of this executable.") -/// }; -/// ``` -#[unstable(feature = "os")] -pub fn self_exe_path() -> Option { - env::current_exe().ok().map(|p| { let mut p = path2old(&p); p.pop(); p }) -} - -/// Optionally returns the path to the current user's home directory if known. -/// -/// # Unix -/// -/// Returns the value of the 'HOME' environment variable if it is set -/// and not equal to the empty string. -/// -/// # Windows -/// -/// Returns the value of the 'HOME' environment variable if it is -/// set and not equal to the empty string. Otherwise, returns the value of the -/// 'USERPROFILE' environment variable if it is set and not equal to the empty -/// string. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// match os::homedir() { -/// Some(ref p) => println!("{}", p.display()), -/// None => println!("Impossible to get your home dir!") -/// } -/// ``` -#[unstable(feature = "os")] -#[allow(deprecated)] -pub fn homedir() -> Option { - #[inline] - #[cfg(unix)] - fn _homedir() -> Option { - aux_homedir("HOME") - } - - #[inline] - #[cfg(windows)] - fn _homedir() -> Option { - aux_homedir("HOME").or(aux_homedir("USERPROFILE")) - } - - #[inline] - fn aux_homedir(home_name: &str) -> Option { - match getenv_as_bytes(home_name) { - Some(p) => { - if p.is_empty() { None } else { Path::new_opt(p) } - }, - _ => None - } - } - _homedir() -} - -/// Returns the path to a temporary directory. -/// -/// On Unix, returns the value of the 'TMPDIR' environment variable if it is -/// set, otherwise for non-Android it returns '/tmp'. If Android, since there -/// is no global temporary folder (it is usually allocated per-app), we return -/// '/data/local/tmp'. -/// -/// On Windows, returns the value of, in order, the 'TMP', 'TEMP', -/// 'USERPROFILE' environment variable if any are set and not the empty -/// string. Otherwise, tmpdir returns the path to the Windows directory. -#[unstable(feature = "os")] -#[allow(deprecated)] -pub fn tmpdir() -> Path { - return lookup(); - - fn getenv_nonempty(v: &str) -> Option { - match getenv(v) { - Some(x) => - if x.is_empty() { - None - } else { - Path::new_opt(x) - }, - _ => None - } - } - - #[cfg(unix)] - fn lookup() -> Path { - let default = if cfg!(target_os = "android") { - Path::new("/data/local/tmp") - } else { - Path::new("/tmp") - }; - - getenv_nonempty("TMPDIR").unwrap_or(default) - } - - #[cfg(windows)] - fn lookup() -> Path { - getenv_nonempty("TMP").or( - getenv_nonempty("TEMP").or( - getenv_nonempty("USERPROFILE").or( - getenv_nonempty("WINDIR")))).unwrap_or(Path::new("C:\\Windows")) - } -} - -/// Convert a relative path to an absolute path -/// -/// If the given path is relative, return it prepended with the current working -/// directory. If the given path is already an absolute path, return it -/// as is. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// // Assume we're in a path like /home/someuser -/// let rel_path = Path::new(".."); -/// let abs_path = os::make_absolute(&rel_path).unwrap(); -/// println!("The absolute path is {}", abs_path.display()); -/// // Prints "The absolute path is /home" -/// ``` -// NB: this is here rather than in path because it is a form of environment -// querying; what it does depends on the process working directory, not just -// the input paths. -#[deprecated(since = "1.0.0", reason = "use env::current_dir + .join directly")] -#[unstable(feature = "os")] -pub fn make_absolute(p: &Path) -> IoResult { - if p.is_absolute() { - Ok(p.clone()) - } else { - env::current_dir().map_err(err2old).map(|cwd| { - let mut cwd = path2old(&cwd); - cwd.push(p); - cwd - }) - } -} - -/// Changes the current working directory to the specified path, returning -/// whether the change was completed successfully or not. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// let root = Path::new("/"); -/// assert!(os::change_dir(&root).is_ok()); -/// println!("Successfully changed working directory to {}!", root.display()); -/// ``` -#[unstable(feature = "os")] -pub fn change_dir(p: &Path) -> IoResult<()> { - sys::os::chdir(&path2new(p)).map_err(err2old) -} - -/// Returns the platform-specific value of errno -pub fn errno() -> i32 { - sys::os::errno() as i32 -} - -/// Return the string corresponding to an `errno()` value of `errnum`. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os)] -/// use std::os; -/// -/// // Same as println!("{}", last_os_error()); -/// println!("{}", os::error_string(os::errno() as i32)); -/// ``` -pub fn error_string(errnum: i32) -> String { - return sys::os::error_string(errnum); -} - -/// Get a string representing the platform-dependent last error -pub fn last_os_error() -> String { - error_string(errno()) -} - -/// Sets the process exit code -/// -/// Sets the exit code returned by the process if all supervised tasks -/// terminate successfully (without panicking). If the current root task panics -/// and is supervised by the scheduler then any user-specified exit status is -/// ignored and the process exits with the default panic status. -/// -/// Note that this is not synchronized against modifications of other threads. -#[deprecated(since = "1.0.0", reason = "renamed to env::set_exit_status")] -#[unstable(feature = "os")] -pub fn set_exit_status(code: isize) { - env::set_exit_status(code as i32) -} - -/// Fetches the process's current exit code. This defaults to 0 and can change -/// by calling `set_exit_status`. -#[deprecated(since = "1.0.0", reason = "renamed to env::get_exit_status")] -#[unstable(feature = "os")] -pub fn get_exit_status() -> isize { - env::get_exit_status() as isize -} - -#[cfg(target_os = "macos")] -unsafe fn load_argc_and_argv(argc: isize, - argv: *const *const c_char) -> Vec> { - use ffi::CStr; - - (0..argc).map(|i| { - CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec() - }).collect() -} - -/// Returns the command line arguments -/// -/// Returns a list of the command line arguments. -#[cfg(target_os = "macos")] -fn real_args_as_bytes() -> Vec> { - unsafe { - let (argc, argv) = (*_NSGetArgc() as isize, - *_NSGetArgv() as *const *const c_char); - load_argc_and_argv(argc, argv) - } -} - -// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs -// and use underscores in their names - they're most probably -// are considered private and therefore should be avoided -// Here is another way to get arguments using Objective C -// runtime -// -// In general it looks like: -// res = Vec::new() -// let args = [[NSProcessInfo processInfo] arguments] -// for i in 0..[args count] -// res.push([args objectAtIndex:i]) -// res -#[cfg(target_os = "ios")] -fn real_args_as_bytes() -> Vec> { - use ffi::CStr; - use iter::range; - use mem; - - #[link(name = "objc")] - extern { - fn sel_registerName(name: *const libc::c_uchar) -> Sel; - fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId; - fn objc_getClass(class_name: *const libc::c_uchar) -> NsId; - } - - #[link(name = "Foundation", kind = "framework")] - extern {} - - type Sel = *const libc::c_void; - type NsId = *const libc::c_void; - - let mut res = Vec::new(); - - unsafe { - let processInfoSel = sel_registerName("processInfo\0".as_ptr()); - let argumentsSel = sel_registerName("arguments\0".as_ptr()); - let utf8Sel = sel_registerName("UTF8String\0".as_ptr()); - let countSel = sel_registerName("count\0".as_ptr()); - let objectAtSel = sel_registerName("objectAtIndex:\0".as_ptr()); - - let klass = objc_getClass("NSProcessInfo\0".as_ptr()); - let info = objc_msgSend(klass, processInfoSel); - let args = objc_msgSend(info, argumentsSel); - - let cnt: isize = mem::transmute(objc_msgSend(args, countSel)); - for i in 0..cnt { - let tmp = objc_msgSend(args, objectAtSel, i); - let utf_c_str: *const libc::c_char = - mem::transmute(objc_msgSend(tmp, utf8Sel)); - res.push(CStr::from_ptr(utf_c_str).to_bytes().to_vec()); - } - } - - res -} - -#[cfg(any(target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "openbsd"))] -fn real_args_as_bytes() -> Vec> { - use rt; - rt::args::clone().unwrap_or_else(|| vec![]) -} - -#[cfg(not(windows))] -fn real_args() -> Vec { - real_args_as_bytes().into_iter() - .map(|v| { - String::from_utf8_lossy(&v).into_owned() - }).collect() -} - -#[cfg(windows)] -fn real_args() -> Vec { - use slice; - use iter::range; - - let mut nArgs: c_int = 0; - let lpArgCount: *mut c_int = &mut nArgs; - let lpCmdLine = unsafe { GetCommandLineW() }; - let szArgList = unsafe { CommandLineToArgvW(lpCmdLine, lpArgCount) }; - - let args: Vec<_> = (0..nArgs as usize).map(|i| unsafe { - // Determine the length of this argument. - let ptr = *szArgList.offset(i as isize); - let mut len = 0; - while *ptr.offset(len as isize) != 0 { len += 1; } - - // Push it onto the list. - let ptr = ptr as *const u16; - let buf = slice::from_raw_parts(ptr, len); - let opt_s = String::from_utf16(sys::truncate_utf16_at_nul(buf)); - opt_s.ok().expect("CommandLineToArgvW returned invalid UTF-16") - }).collect(); - - unsafe { - LocalFree(szArgList as *mut c_void); - } - - return args -} - -#[cfg(windows)] -fn real_args_as_bytes() -> Vec> { - real_args().into_iter().map(|s| s.into_bytes()).collect() -} - -type LPCWSTR = *const u16; - -#[cfg(windows)] -#[link_name="kernel32"] -extern "system" { - fn GetCommandLineW() -> LPCWSTR; - fn LocalFree(ptr: *mut c_void); -} - -#[cfg(windows)] -#[link_name="shell32"] -extern "system" { - fn CommandLineToArgvW(lpCmdLine: LPCWSTR, - pNumArgs: *mut c_int) -> *mut *mut u16; -} - -/// Returns the arguments which this program was started with (normally passed -/// via the command line). -/// -/// The first element is traditionally the path to the executable, but it can be -/// set to arbitrary text, and it may not even exist, so this property should not -/// be relied upon for security purposes. -/// -/// The arguments are interpreted as utf-8, with invalid bytes replaced with \uFFFD. -/// See `String::from_utf8_lossy` for details. -/// # Examples -/// -/// ``` -/// # #![feature(os)] -/// use std::os; -/// -/// // Prints each argument on a separate line -/// for argument in os::args().iter() { -/// println!("{}", argument); -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "use std::env::args() instead")] -#[unstable(feature = "os")] -pub fn args() -> Vec { - real_args() -} - -/// Returns the arguments which this program was started with (normally passed -/// via the command line) as byte vectors. -#[deprecated(since = "1.0.0", reason = "use env::args_os instead")] -#[unstable(feature = "os")] -pub fn args_as_bytes() -> Vec> { - real_args_as_bytes() -} - -#[cfg(target_os = "macos")] -extern { - // These functions are in crt_externs.h. - fn _NSGetArgc() -> *mut c_int; - fn _NSGetArgv() -> *mut *mut *mut c_char; -} - -/// Returns the page size of the current architecture in bytes. -#[deprecated(since = "1.0.0", reason = "renamed to env::page_size")] -#[unstable(feature = "os")] -pub fn page_size() -> usize { - sys::os::page_size() -} - -/// A memory mapped file or chunk of memory. This is a very system-specific -/// interface to the OS's memory mapping facilities (`mmap` on POSIX, -/// `VirtualAlloc`/`CreateFileMapping` on Windows). It makes no attempt at -/// abstracting platform differences, besides in error values returned. Consider -/// yourself warned. -/// -/// The memory map is released (unmapped) when the destructor is run, so don't -/// let it leave scope by accident if you want it to stick around. -pub struct MemoryMap { - data: *mut u8, - len: usize, - kind: MemoryMapKind, -} - -/// Type of memory map -#[allow(raw_pointer_derive)] -#[derive(Copy)] -pub enum MemoryMapKind { - /// Virtual memory map. Usually used to change the permissions of a given - /// chunk of memory. Corresponds to `VirtualAlloc` on Windows. - MapFile(*const u8), - /// Virtual memory map. Usually used to change the permissions of a given - /// chunk of memory, or for allocation. Corresponds to `VirtualAlloc` on - /// Windows. - MapVirtual -} - -/// Options the memory map is created with -#[allow(raw_pointer_derive)] -#[derive(Copy)] -pub enum MapOption { - /// The memory should be readable - MapReadable, - /// The memory should be writable - MapWritable, - /// The memory should be executable - MapExecutable, - /// Create a map for a specific address range. Corresponds to `MAP_FIXED` on - /// POSIX. - MapAddr(*const u8), - /// Create a memory mapping for a file with a given HANDLE. - #[cfg(windows)] - MapFd(libc::HANDLE), - /// Create a memory mapping for a file with a given fd. - #[cfg(not(windows))] - MapFd(c_int), - /// When using `MapFd`, the start of the map is `usize` bytes from the start - /// of the file. - MapOffset(usize), - /// On POSIX, this can be used to specify the default flags passed to - /// `mmap`. By default it uses `MAP_PRIVATE` and, if not using `MapFd`, - /// `MAP_ANON`. This will override both of those. This is platform-specific - /// (the exact values used) and ignored on Windows. - MapNonStandardFlags(c_int), -} - -/// Possible errors when creating a map. -#[derive(Copy, Debug)] -pub enum MapError { - /// # The following are POSIX-specific - /// - /// fd was not open for reading or, if using `MapWritable`, was not open for - /// writing. - ErrFdNotAvail, - /// fd was not valid - ErrInvalidFd, - /// Either the address given by `MapAddr` or offset given by `MapOffset` was - /// not a multiple of `MemoryMap::granularity` (unaligned to page size). - ErrUnaligned, - /// With `MapFd`, the fd does not support mapping. - ErrNoMapSupport, - /// If using `MapAddr`, the address + `min_len` was outside of the process's - /// address space. If using `MapFd`, the target of the fd didn't have enough - /// resources to fulfill the request. - ErrNoMem, - /// A zero-length map was requested. This is invalid according to - /// [POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html). - /// Not all platforms obey this, but this wrapper does. - ErrZeroLength, - /// Unrecognized error. The inner value is the unrecognized errno. - ErrUnknown(isize), - /// # The following are Windows-specific - /// - /// Unsupported combination of protection flags - /// (`MapReadable`/`MapWritable`/`MapExecutable`). - ErrUnsupProt, - /// When using `MapFd`, `MapOffset` was given (Windows does not support this - /// at all) - ErrUnsupOffset, - /// When using `MapFd`, there was already a mapping to the file. - ErrAlreadyExists, - /// Unrecognized error from `VirtualAlloc`. The inner value is the return - /// value of GetLastError. - ErrVirtualAlloc(i32), - /// Unrecognized error from `CreateFileMapping`. The inner value is the - /// return value of `GetLastError`. - ErrCreateFileMappingW(i32), - /// Unrecognized error from `MapViewOfFile`. The inner value is the return - /// value of `GetLastError`. - ErrMapViewOfFile(i32) -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for MapError { - fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result { - let str = match *self { - ErrFdNotAvail => "fd not available for reading or writing", - ErrInvalidFd => "Invalid fd", - ErrUnaligned => { - "Unaligned address, invalid flags, negative length or \ - unaligned offset" - } - ErrNoMapSupport=> "File doesn't support mapping", - ErrNoMem => "Invalid address, or not enough available memory", - ErrUnsupProt => "Protection mode unsupported", - ErrUnsupOffset => "Offset in virtual memory mode is unsupported", - ErrAlreadyExists => "File mapping for specified file already exists", - ErrZeroLength => "Zero-length mapping not allowed", - ErrUnknown(code) => { - return write!(out, "Unknown error = {}", code) - }, - ErrVirtualAlloc(code) => { - return write!(out, "VirtualAlloc failure = {}", code) - }, - ErrCreateFileMappingW(code) => { - return write!(out, "CreateFileMappingW failure = {}", code) - }, - ErrMapViewOfFile(code) => { - return write!(out, "MapViewOfFile failure = {}", code) - } - }; - write!(out, "{}", str) - } -} - -impl Error for MapError { - fn description(&self) -> &str { "memory map error" } -} - -// Round up `from` to be divisible by `to` -fn round_up(from: usize, to: usize) -> usize { - let r = if from % to == 0 { - from - } else { - from + to - (from % to) - }; - if r == 0 { - to - } else { - r - } -} - -#[cfg(unix)] -impl MemoryMap { - /// Create a new mapping with the given `options`, at least `min_len` bytes - /// long. `min_len` must be greater than zero; see the note on - /// `ErrZeroLength`. - pub fn new(min_len: usize, options: &[MapOption]) -> Result { - use libc::off_t; - - if min_len == 0 { - return Err(ErrZeroLength) - } - let mut addr: *const u8 = ptr::null(); - let mut prot = 0; - let mut flags = libc::MAP_PRIVATE; - let mut fd = -1; - let mut offset = 0; - let mut custom_flags = false; - let len = round_up(min_len, env::page_size()); - - for &o in options { - match o { - MapReadable => { prot |= libc::PROT_READ; }, - MapWritable => { prot |= libc::PROT_WRITE; }, - MapExecutable => { prot |= libc::PROT_EXEC; }, - MapAddr(addr_) => { - flags |= libc::MAP_FIXED; - addr = addr_; - }, - MapFd(fd_) => { - flags |= libc::MAP_FILE; - fd = fd_; - }, - MapOffset(offset_) => { offset = offset_ as off_t; }, - MapNonStandardFlags(f) => { custom_flags = true; flags = f }, - } - } - if fd == -1 && !custom_flags { flags |= libc::MAP_ANON; } - - let r = unsafe { - libc::mmap(addr as *mut c_void, len as libc::size_t, prot, flags, - fd, offset) - }; - if r == libc::MAP_FAILED { - Err(match errno() as c_int { - libc::EACCES => ErrFdNotAvail, - libc::EBADF => ErrInvalidFd, - libc::EINVAL => ErrUnaligned, - libc::ENODEV => ErrNoMapSupport, - libc::ENOMEM => ErrNoMem, - code => ErrUnknown(code as isize) - }) - } else { - Ok(MemoryMap { - data: r as *mut u8, - len: len, - kind: if fd == -1 { - MapVirtual - } else { - MapFile(ptr::null()) - } - }) - } - } - - /// Granularity that the offset or address must be for `MapOffset` and - /// `MapAddr` respectively. - pub fn granularity() -> usize { - env::page_size() - } -} - -#[cfg(unix)] -impl Drop for MemoryMap { - /// Unmap the mapping. Panics the task if `munmap` panics. - fn drop(&mut self) { - if self.len == 0 { /* workaround for dummy_stack */ return; } - - unsafe { - // `munmap` only panics due to logic errors - libc::munmap(self.data as *mut c_void, self.len as libc::size_t); - } - } -} - -#[cfg(windows)] -impl MemoryMap { - /// Create a new mapping with the given `options`, at least `min_len` bytes long. - pub fn new(min_len: usize, options: &[MapOption]) -> Result { - use libc::types::os::arch::extra::{LPVOID, DWORD, SIZE_T, HANDLE}; - - let mut lpAddress: LPVOID = ptr::null_mut(); - let mut readable = false; - let mut writable = false; - let mut executable = false; - let mut handle: HANDLE = libc::INVALID_HANDLE_VALUE; - let mut offset: usize = 0; - let len = round_up(min_len, env::page_size()); - - for &o in options { - match o { - MapReadable => { readable = true; }, - MapWritable => { writable = true; }, - MapExecutable => { executable = true; } - MapAddr(addr_) => { lpAddress = addr_ as LPVOID; }, - MapFd(handle_) => { handle = handle_; }, - MapOffset(offset_) => { offset = offset_; }, - MapNonStandardFlags(..) => {} - } - } - - let flProtect = match (executable, readable, writable) { - (false, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_NOACCESS, - (false, true, false) => libc::PAGE_READONLY, - (false, true, true) => libc::PAGE_READWRITE, - (true, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_EXECUTE, - (true, true, false) => libc::PAGE_EXECUTE_READ, - (true, true, true) => libc::PAGE_EXECUTE_READWRITE, - _ => return Err(ErrUnsupProt) - }; - - if handle == libc::INVALID_HANDLE_VALUE { - if offset != 0 { - return Err(ErrUnsupOffset); - } - let r = unsafe { - libc::VirtualAlloc(lpAddress, - len as SIZE_T, - libc::MEM_COMMIT | libc::MEM_RESERVE, - flProtect) - }; - match r as usize { - 0 => Err(ErrVirtualAlloc(errno())), - _ => Ok(MemoryMap { - data: r as *mut u8, - len: len, - kind: MapVirtual - }) - } - } else { - let dwDesiredAccess = match (executable, readable, writable) { - (false, true, false) => libc::FILE_MAP_READ, - (false, true, true) => libc::FILE_MAP_WRITE, - (true, true, false) => libc::FILE_MAP_READ | libc::FILE_MAP_EXECUTE, - (true, true, true) => libc::FILE_MAP_WRITE | libc::FILE_MAP_EXECUTE, - _ => return Err(ErrUnsupProt) // Actually, because of the check above, - // we should never get here. - }; - unsafe { - let hFile = handle; - let mapping = libc::CreateFileMappingW(hFile, - ptr::null_mut(), - flProtect, - 0, - 0, - ptr::null()); - if mapping == ptr::null_mut() { - return Err(ErrCreateFileMappingW(errno())); - } - if errno() as c_int == libc::ERROR_ALREADY_EXISTS { - return Err(ErrAlreadyExists); - } - let r = libc::MapViewOfFile(mapping, - dwDesiredAccess, - ((len as u64) >> 32) as DWORD, - (offset & 0xffff_ffff) as DWORD, - 0); - match r as usize { - 0 => Err(ErrMapViewOfFile(errno())), - _ => Ok(MemoryMap { - data: r as *mut u8, - len: len, - kind: MapFile(mapping as *const u8) - }) - } - } - } - } - - /// Granularity of MapAddr() and MapOffset() parameter values. - /// This may be greater than the value returned by page_size(). - pub fn granularity() -> usize { - use mem; - unsafe { - let mut info = mem::zeroed(); - libc::GetSystemInfo(&mut info); - - return info.dwAllocationGranularity as usize; - } - } -} - -#[cfg(windows)] -impl Drop for MemoryMap { - /// Unmap the mapping. Panics the task if any of `VirtualFree`, - /// `UnmapViewOfFile`, or `CloseHandle` fail. - fn drop(&mut self) { - use libc::types::os::arch::extra::{LPCVOID, HANDLE}; - use libc::consts::os::extra::FALSE; - if self.len == 0 { return } - - unsafe { - match self.kind { - MapVirtual => { - if libc::VirtualFree(self.data as *mut c_void, 0, - libc::MEM_RELEASE) == 0 { - println!("VirtualFree failed: {}", errno()); - } - }, - MapFile(mapping) => { - if libc::UnmapViewOfFile(self.data as LPCVOID) == FALSE { - println!("UnmapViewOfFile failed: {}", errno()); - } - if libc::CloseHandle(mapping as HANDLE) == FALSE { - println!("CloseHandle failed: {}", errno()); - } - } - } - } - } -} - -impl MemoryMap { - /// Returns the pointer to the memory created or modified by this map. - pub fn data(&self) -> *mut u8 { self.data } - /// Returns the number of bytes this map applies to. - pub fn len(&self) -> usize { self.len } - /// Returns the type of mapping this represents. - pub fn kind(&self) -> MemoryMapKind { self.kind } -} - -#[cfg(target_os = "linux")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `linux`. - pub const SYSNAME: &'static str = "linux"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "macos")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `macos`. - pub const SYSNAME: &'static str = "macos"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.dylib`. - pub const DLL_SUFFIX: &'static str = ".dylib"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `dylib`. - pub const DLL_EXTENSION: &'static str = "dylib"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "ios")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `ios`. - pub const SYSNAME: &'static str = "ios"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "freebsd")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `freebsd`. - pub const SYSNAME: &'static str = "freebsd"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "dragonfly")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `dragonfly`. - pub const SYSNAME: &'static str = "dragonfly"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "bitrig")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `bitrig`. - pub const SYSNAME: &'static str = "bitrig"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "openbsd")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `openbsd`. - pub const SYSNAME: &'static str = "openbsd"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "android")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `android`. - pub const SYSNAME: &'static str = "android"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "windows")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "windows"; - - /// A string describing the specific operating system in use: in this - /// case, `windows`. - pub const SYSNAME: &'static str = "windows"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, the empty string. - pub const DLL_PREFIX: &'static str = ""; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.dll`. - pub const DLL_SUFFIX: &'static str = ".dll"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `dll`. - pub const DLL_EXTENSION: &'static str = "dll"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, `.exe`. - pub const EXE_SUFFIX: &'static str = ".exe"; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, `exe`. - pub const EXE_EXTENSION: &'static str = "exe"; -} - -#[cfg(target_arch = "x86")] -mod arch_consts { - pub const ARCH: &'static str = "x86"; -} - -#[cfg(target_arch = "x86_64")] -mod arch_consts { - pub const ARCH: &'static str = "x86_64"; -} - -#[cfg(target_arch = "arm")] -mod arch_consts { - pub const ARCH: &'static str = "arm"; -} - -#[cfg(target_arch = "aarch64")] -mod arch_consts { - pub const ARCH: &'static str = "aarch64"; -} - -#[cfg(target_arch = "mips")] -mod arch_consts { - pub const ARCH: &'static str = "mips"; -} - -#[cfg(target_arch = "mipsel")] -mod arch_consts { - pub const ARCH: &'static str = "mipsel"; -} - -#[cfg(target_arch = "powerpc")] -mod arch_consts { - pub const ARCH: &'static str = "powerpc"; -} - -#[cfg(test)] -mod tests { - #![allow(deprecated)] // rand - - use prelude::v1::*; - - use iter::repeat; - use os::{env, getcwd, getenv, make_absolute}; - use os::{split_paths, join_paths, setenv, unsetenv}; - use os; - use rand::Rng; - use rand; - use old_path::{Path, GenericPath}; - use old_io::{Reader, Writer, Seek}; - - #[test] - pub fn last_os_error() { - debug!("{}", os::last_os_error()); - } - - fn make_rand_name() -> String { - let mut rng = rand::thread_rng(); - let n = format!("TEST{}", rng.gen_ascii_chars().take(10) - .collect::()); - assert!(getenv(&n).is_none()); - n - } - - #[test] - fn test_num_cpus() { - assert!(os::num_cpus() > 0); - } - - #[test] - fn test_setenv() { - let n = make_rand_name(); - setenv(&n, "VALUE"); - assert_eq!(getenv(&n), Some("VALUE".to_string())); - } - - #[test] - fn test_unsetenv() { - let n = make_rand_name(); - setenv(&n, "VALUE"); - unsetenv(&n); - assert_eq!(getenv(&n), None); - } - - #[test] - #[ignore] - fn test_setenv_overwrite() { - let n = make_rand_name(); - setenv(&n, "1"); - setenv(&n, "2"); - assert_eq!(getenv(&n), Some("2".to_string())); - setenv(&n, ""); - assert_eq!(getenv(&n), Some("".to_string())); - } - - // Windows GetEnvironmentVariable requires some extra work to make sure - // the buffer the variable is copied into is the right size - #[test] - #[ignore] - fn test_getenv_big() { - let mut s = "".to_string(); - let mut i = 0; - while i < 100 { - s.push_str("aaaaaaaaaa"); - i += 1; - } - let n = make_rand_name(); - setenv(&n, &s); - debug!("{}", s.clone()); - assert_eq!(getenv(&n), Some(s)); - } - - #[test] - fn test_self_exe_name() { - let path = os::self_exe_name(); - assert!(path.is_some()); - let path = path.unwrap(); - debug!("{}", path.display()); - - // Hard to test this function - assert!(path.is_absolute()); - } - - #[test] - fn test_self_exe_path() { - let path = os::self_exe_path(); - assert!(path.is_some()); - let path = path.unwrap(); - debug!("{}", path.display()); - - // Hard to test this function - assert!(path.is_absolute()); - } - - #[test] - #[ignore] - fn test_env_getenv() { - let e = env(); - assert!(e.len() > 0); - for p in &e { - let (n, v) = (*p).clone(); - debug!("{}", n); - let v2 = getenv(&n); - // MingW seems to set some funky environment variables like - // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned - // from env() but not visible from getenv(). - assert!(v2.is_none() || v2 == Some(v)); - } - } - - #[test] - fn test_env_set_get_huge() { - let n = make_rand_name(); - let s = repeat("x").take(10000).collect::(); - setenv(&n, &s); - assert_eq!(getenv(&n), Some(s)); - unsetenv(&n); - assert_eq!(getenv(&n), None); - } - - #[test] - fn test_env_setenv() { - let n = make_rand_name(); - - let mut e = env(); - setenv(&n, "VALUE"); - assert!(!e.contains(&(n.clone(), "VALUE".to_string()))); - - e = env(); - assert!(e.contains(&(n, "VALUE".to_string()))); - } - - #[test] - fn test() { - assert!((!Path::new("test-path").is_absolute())); - - let cwd = getcwd().unwrap(); - debug!("Current working directory: {}", cwd.display()); - - debug!("{}", make_absolute(&Path::new("test-path")).unwrap().display()); - debug!("{}", make_absolute(&Path::new("/usr/bin")).unwrap().display()); - } - - #[test] - #[cfg(unix)] - fn homedir() { - let oldhome = getenv("HOME"); - - setenv("HOME", "/home/MountainView"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - setenv("HOME", ""); - assert!(os::homedir().is_none()); - - if let Some(s) = oldhome { - setenv("HOME", s); - } - } - - #[test] - #[cfg(windows)] - fn homedir() { - - let oldhome = getenv("HOME"); - let olduserprofile = getenv("USERPROFILE"); - - setenv("HOME", ""); - setenv("USERPROFILE", ""); - - assert!(os::homedir().is_none()); - - setenv("HOME", "/home/MountainView"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - setenv("HOME", ""); - - setenv("USERPROFILE", "/home/MountainView"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - setenv("HOME", "/home/MountainView"); - setenv("USERPROFILE", "/home/PaloAlto"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - if let Some(s) = oldhome { - setenv("HOME", &s); - } - if let Some(s) = olduserprofile { - setenv("USERPROFILE", &s); - } - } - - #[test] - fn memory_map_rw() { - use result::Result::{Ok, Err}; - - let chunk = match os::MemoryMap::new(16, &[ - os::MapOption::MapReadable, - os::MapOption::MapWritable - ]) { - Ok(chunk) => chunk, - Err(msg) => panic!("{:?}", msg) - }; - assert!(chunk.len >= 16); - - unsafe { - *chunk.data = 0xBE; - assert!(*chunk.data == 0xBE); - } - } - - #[test] - fn memory_map_file() { - use libc; - use os::*; - use old_io::fs::{File, unlink}; - use old_io::SeekStyle::SeekSet; - use old_io::FileMode::Open; - use old_io::FileAccess::ReadWrite; - - #[cfg(not(windows))] - fn get_fd(file: &File) -> libc::c_int { - use os::unix::prelude::*; - file.as_raw_fd() - } - - #[cfg(windows)] - fn get_fd(file: &File) -> libc::HANDLE { - use os::windows::prelude::*; - file.as_raw_handle() - } - - let mut path = tmpdir(); - path.push("mmap_file.tmp"); - let size = MemoryMap::granularity() * 2; - let mut file = File::open_mode(&path, Open, ReadWrite).unwrap(); - file.seek(size as i64, SeekSet).unwrap(); - file.write_u8(0).unwrap(); - - let chunk = MemoryMap::new(size / 2, &[ - MapOption::MapReadable, - MapOption::MapWritable, - MapOption::MapFd(get_fd(&file)), - MapOption::MapOffset(size / 2) - ]).unwrap(); - assert!(chunk.len > 0); - - unsafe { - *chunk.data = 0xbe; - assert!(*chunk.data == 0xbe); - } - drop(chunk); - - unlink(&path).unwrap(); - } - - #[test] - #[cfg(windows)] - fn split_paths_windows() { - fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { - split_paths(unparsed) == - parsed.iter().map(|s| Path::new(*s)).collect::>() - } - - assert!(check_parse("", &mut [""])); - assert!(check_parse(r#""""#, &mut [""])); - assert!(check_parse(";;", &mut ["", "", ""])); - assert!(check_parse(r"c:\", &mut [r"c:\"])); - assert!(check_parse(r"c:\;", &mut [r"c:\", ""])); - assert!(check_parse(r"c:\;c:\Program Files\", - &mut [r"c:\", r"c:\Program Files\"])); - assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"])); - assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#, - &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"])); - } - - #[test] - #[cfg(unix)] - fn split_paths_unix() { - fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { - split_paths(unparsed) == - parsed.iter().map(|s| Path::new(*s)).collect::>() - } - - assert!(check_parse("", &mut [""])); - assert!(check_parse("::", &mut ["", "", ""])); - assert!(check_parse("/", &mut ["/"])); - assert!(check_parse("/:", &mut ["/", ""])); - assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"])); - } - - #[test] - #[cfg(unix)] - fn join_paths_unix() { - fn test_eq(input: &[&str], output: &str) -> bool { - join_paths(input).unwrap() == output.as_bytes() - } - - assert!(test_eq(&[], "")); - assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"], - "/bin:/usr/bin:/usr/local/bin")); - assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""], - ":/bin:::/usr/bin:")); - assert!(join_paths(&["/te:st"]).is_err()); - } - - #[test] - #[cfg(windows)] - fn join_paths_windows() { - fn test_eq(input: &[&str], output: &str) -> bool { - join_paths(input).unwrap() == output.as_bytes() - } - - assert!(test_eq(&[], "")); - assert!(test_eq(&[r"c:\windows", r"c:\"], - r"c:\windows;c:\")); - assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""], - r";c:\windows;;;c:\;")); - assert!(test_eq(&[r"c:\te;st", r"c:\"], - r#""c:\te;st";c:\"#)); - assert!(join_paths(&[r#"c:\te"st"#]).is_err()); - } - - // More recursive_mkdir tests are in extra::tempfile -} diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 58d3ae9f7cf..44421c40901 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1318,7 +1318,7 @@ impl Path { #[stable(feature = "rust1", since = "1.0.0")] pub fn file_name(&self) -> Option<&OsStr> { self.components().next_back().and_then(|p| match p { - Component::Normal(p) => Some(p.as_os_str()), + Component::Normal(p) => Some(p.as_ref()), _ => None }) } diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 297eccb9f76..84a45086767 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -42,12 +42,11 @@ #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use result::Result::{self, Ok, Err}; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -#[doc(no_inline)] pub use slice::{SliceConcatExt, AsSlice}; -#[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -#[doc(no_inline)] pub use str::Str; +#[doc(no_inline)] pub use slice::SliceConcatExt; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use string::{String, ToString}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use vec::Vec; + +#[allow(deprecated)] pub use slice::AsSlice; +#[allow(deprecated)] pub use str::Str; diff --git a/src/libstd/process.rs b/src/libstd/process.rs index b4bd513e8f0..ece0aa8f064 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -16,15 +16,15 @@ use prelude::v1::*; use io::prelude::*; -use ffi::AsOsStr; +use ffi::OsStr; use fmt; use io::{self, Error, ErrorKind}; use libc; use path; use sync::mpsc::{channel, Receiver}; use sys::pipe2::{self, AnonPipe}; -use sys::process2::Process as ProcessImp; use sys::process2::Command as CommandImp; +use sys::process2::Process as ProcessImp; use sys::process2::ExitStatus as ExitStatusImp; use sys_common::{AsInner, AsInnerMut}; use thread; @@ -147,9 +147,9 @@ impl Command { /// Builder methods are provided to change these defaults and /// otherwise configure the process. #[stable(feature = "process", since = "1.0.0")] - pub fn new(program: S) -> Command { + pub fn new>(program: S) -> Command { Command { - inner: CommandImp::new(program.as_os_str()), + inner: CommandImp::new(program.as_ref()), stdin: None, stdout: None, stderr: None, @@ -158,15 +158,15 @@ impl Command { /// Add an argument to pass to the program. #[stable(feature = "process", since = "1.0.0")] - pub fn arg(&mut self, arg: S) -> &mut Command { - self.inner.arg(arg.as_os_str()); + pub fn arg>(&mut self, arg: S) -> &mut Command { + self.inner.arg(arg.as_ref()); self } /// Add multiple arguments to pass to the program. #[stable(feature = "process", since = "1.0.0")] - pub fn args(&mut self, args: &[S]) -> &mut Command { - self.inner.args(args.iter().map(AsOsStr::as_os_str)); + pub fn args>(&mut self, args: &[S]) -> &mut Command { + self.inner.args(args.iter().map(AsRef::as_ref)); self } @@ -176,16 +176,16 @@ impl Command { /// and case-sensitive on all other platforms. #[stable(feature = "process", since = "1.0.0")] pub fn env(&mut self, key: K, val: V) -> &mut Command - where K: AsOsStr, V: AsOsStr + where K: AsRef, V: AsRef { - self.inner.env(key.as_os_str(), val.as_os_str()); + self.inner.env(key.as_ref(), val.as_ref()); self } /// Removes an environment variable mapping. #[stable(feature = "process", since = "1.0.0")] - pub fn env_remove(&mut self, key: K) -> &mut Command { - self.inner.env_remove(key.as_os_str()); + pub fn env_remove>(&mut self, key: K) -> &mut Command { + self.inner.env_remove(key.as_ref()); self } @@ -199,7 +199,7 @@ impl Command { /// Set the working directory for the child process. #[stable(feature = "process", since = "1.0.0")] pub fn current_dir>(&mut self, dir: P) -> &mut Command { - self.inner.cwd(dir.as_ref().as_os_str()); + self.inner.cwd(dir.as_ref().as_ref()); self } @@ -378,11 +378,6 @@ enum StdioImp { } impl Stdio { - /// A new pipe should be arranged to connect the parent and child processes. - #[unstable(feature = "process_capture")] - #[deprecated(since = "1.0.0", reason = "renamed to `Stdio::piped`")] - pub fn capture() -> Stdio { Stdio::piped() } - /// A new pipe should be arranged to connect the parent and child processes. #[stable(feature = "process", since = "1.0.0")] pub fn piped() -> Stdio { Stdio(StdioImp::Piped) } @@ -529,11 +524,10 @@ impl Child { #[cfg(test)] mod tests { - use io::ErrorKind; + use prelude::v1::*; use io::prelude::*; - use prelude::v1::{Ok, Err, drop, Some, Vec}; - use prelude::v1::{String, Clone}; - use prelude::v1::{Str, AsSlice, ToString}; + + use io::ErrorKind; use old_path::{self, GenericPath}; use old_io::fs::PathExtensions; use rt::running_on_valgrind; @@ -678,7 +672,7 @@ mod tests { fn test_process_output_output() { let Output {status, stdout, stderr} = Command::new("echo").arg("hello").output().unwrap(); - let output_str = str::from_utf8(stdout.as_slice()).unwrap(); + let output_str = str::from_utf8(&stdout).unwrap(); assert!(status.success()); assert_eq!(output_str.trim().to_string(), "hello"); @@ -720,7 +714,7 @@ mod tests { let prog = Command::new("echo").arg("hello").stdout(Stdio::piped()) .spawn().unwrap(); let Output {status, stdout, stderr} = prog.wait_with_output().unwrap(); - let output_str = str::from_utf8(stdout.as_slice()).unwrap(); + let output_str = str::from_utf8(&stdout).unwrap(); assert!(status.success()); assert_eq!(output_str.trim().to_string(), "hello"); @@ -755,7 +749,8 @@ mod tests { let prog = pwd_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().stdout).unwrap(); - let parent_dir = os::getcwd().unwrap(); + let parent_dir = ::env::current_dir().unwrap().to_str().unwrap().to_string(); + let parent_dir = old_path::Path::new(parent_dir); let child_dir = old_path::Path::new(output.trim()); let parent_stat = parent_dir.stat().unwrap(); @@ -770,7 +765,8 @@ mod tests { use os; // test changing to the parent of os::getcwd() because we know // the path exists (and os::getcwd() is not expected to be root) - let parent_dir = os::getcwd().unwrap().dir_path(); + let parent_dir = ::env::current_dir().unwrap().to_str().unwrap().to_string(); + let parent_dir = old_path::Path::new(parent_dir).dir_path(); let result = pwd_cmd().current_dir(parent_dir.as_str().unwrap()).output().unwrap(); let output = String::from_utf8(result.stdout).unwrap(); @@ -855,7 +851,7 @@ mod tests { cmd.env("PATH", &p); } let result = cmd.output().unwrap(); - let output = String::from_utf8_lossy(result.stdout.as_slice()).to_string(); + let output = String::from_utf8_lossy(&result.stdout).to_string(); assert!(output.contains("RUN_TEST_NEW_ENV=123"), "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); @@ -864,7 +860,7 @@ mod tests { #[test] fn test_add_to_env() { let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap(); - let output = String::from_utf8_lossy(result.stdout.as_slice()).to_string(); + let output = String::from_utf8_lossy(&result.stdout).to_string(); assert!(output.contains("RUN_TEST_NEW_ENV=123"), "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 51b6045cf16..0a619ff8cd0 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -15,17 +15,16 @@ pub use self::imp::OsRng; #[cfg(all(unix, not(target_os = "ios")))] mod imp { - extern crate libc; - + use prelude::v1::*; use self::OsRngInner::*; + use libc; + use mem; use old_io::{IoResult, File}; use old_path::Path; use rand::Rng; use rand::reader::ReaderRng; - use result::Result::Ok; - use mem; - use os::errno; + use sys::os::errno; #[cfg(all(target_os = "linux", any(target_arch = "x86_64", @@ -184,14 +183,13 @@ mod imp { #[cfg(target_os = "ios")] mod imp { - extern crate libc; + use prelude::v1::*; - use old_io::{IoResult}; + use old_io::IoResult; use mem; use os; use rand::Rng; - use result::Result::{Ok}; - use self::libc::{c_int, size_t}; + use libc::{c_int, size_t}; /// A random number generator that retrieves randomness straight from /// the operating system. Platform sources: @@ -251,16 +249,15 @@ mod imp { #[cfg(windows)] mod imp { - extern crate libc; + use prelude::v1::*; - use old_io::{IoResult, IoError}; + use io; use mem; - use ops::Drop; + use old_io::{IoResult, IoError}; use os; use rand::Rng; - use result::Result::{Ok, Err}; - use self::libc::{DWORD, BYTE, LPCSTR, BOOL}; - use self::libc::types::os::arch::extra::{LONG_PTR}; + use libc::types::os::arch::extra::{LONG_PTR}; + use libc::{DWORD, BYTE, LPCSTR, BOOL}; type HCRYPTPROV = LONG_PTR; @@ -330,7 +327,8 @@ mod imp { v.as_mut_ptr()) }; if ret == 0 { - panic!("couldn't generate random bytes: {}", os::last_os_error()); + panic!("couldn't generate random bytes: {}", + io::Error::last_os_error()); } } } @@ -341,7 +339,8 @@ mod imp { CryptReleaseContext(self.hcryptprov, 0) }; if ret == 0 { - panic!("couldn't release context: {}", os::last_os_error()); + panic!("couldn't release context: {}", + io::Error::last_os_error()); } } } diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index 428bcaa49f7..2329861f29b 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -108,7 +108,6 @@ mod imp { #[cfg(test)] mod tests { use prelude::v1::*; - use finally::Finally; use super::*; @@ -127,14 +126,11 @@ mod imp { assert!(take() == Some(expected.clone())); assert!(take() == None); - (|| { - }).finally(|| { - // Restore the actual global state. - match saved_value { - Some(ref args) => put(args.clone()), - None => () - } - }) + // Restore the actual global state. + match saved_value { + Some(ref args) => put(args.clone()), + None => () + } } } } diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 68137601c40..a5259a00390 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -31,8 +31,6 @@ pub use self::barrier::{Barrier, BarrierWaitResult}; pub use self::poison::{PoisonError, TryLockError, TryLockResult, LockResult}; pub use self::future::Future; -#[allow(deprecated)] -pub use self::task_pool::TaskPool; pub mod mpsc; @@ -44,4 +42,3 @@ mod once; mod poison; mod rwlock; mod semaphore; -mod task_pool; diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs index c07c83d37f4..6ae8e043e05 100644 --- a/src/libstd/sync/poison.rs +++ b/src/libstd/sync/poison.rs @@ -122,12 +122,6 @@ impl PoisonError { PoisonError { guard: guard } } - /// Consumes this error indicating that a lock is poisoned, returning the - /// underlying guard to allow access regardless. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", reason = "renamed to into_inner")] - pub fn into_guard(self) -> T { self.guard } - /// Consumes this error indicating that a lock is poisoned, returning the /// underlying guard to allow access regardless. #[unstable(feature = "std_misc")] diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs deleted file mode 100644 index 51cf70e615b..00000000000 --- a/src/libstd/sync/task_pool.rs +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 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. - -//! Abstraction of a thread pool for basic parallelism. - -#![deprecated(since = "1.0.0", - reason = "This kind of API needs some time to bake in \ - crates.io. This functionality is available through \ - https://crates.io/crates/threadpool")] -#![unstable(feature = "std_misc")] - -#![allow(deprecated)] - -use core::prelude::*; - -use sync::{Arc, Mutex}; -use sync::mpsc::{channel, Sender, Receiver}; -use thread; -use thunk::Thunk; - -struct Sentinel<'a> { - jobs: &'a Arc>>>, - active: bool -} - -impl<'a> Sentinel<'a> { - fn new(jobs: &'a Arc>>>) -> Sentinel<'a> { - Sentinel { - jobs: jobs, - active: true - } - } - - // Cancel and destroy this sentinel. - fn cancel(mut self) { - self.active = false; - } -} - -#[unsafe_destructor] -impl<'a> Drop for Sentinel<'a> { - fn drop(&mut self) { - if self.active { - spawn_in_pool(self.jobs.clone()) - } - } -} - -/// A thread pool used to execute functions in parallel. -/// -/// Spawns `n` worker threads and replenishes the pool if any worker threads -/// panic. -/// -/// # Examples -/// -/// ``` -/// # #![feature(std_misc, core)] -/// use std::sync::TaskPool; -/// use std::iter::AdditiveIterator; -/// use std::sync::mpsc::channel; -/// -/// let pool = TaskPool::new(4); -/// -/// let (tx, rx) = channel(); -/// for _ in 0..8 { -/// let tx = tx.clone(); -/// pool.execute(move|| { -/// tx.send(1_u32).unwrap(); -/// }); -/// } -/// -/// assert_eq!(rx.iter().take(8).sum(), 8); -/// ``` -pub struct TaskPool { - // How the threadpool communicates with subthreads. - // - // This is the only such Sender, so when it is dropped all subthreads will - // quit. - jobs: Sender> -} - -impl TaskPool { - /// Spawns a new thread pool with `threads` threads. - /// - /// # Panics - /// - /// This function will panic if `threads` is 0. - pub fn new(threads: usize) -> TaskPool { - assert!(threads >= 1); - - let (tx, rx) = channel::(); - let rx = Arc::new(Mutex::new(rx)); - - // Threadpool threads - for _ in 0..threads { - spawn_in_pool(rx.clone()); - } - - TaskPool { jobs: tx } - } - - /// Executes the function `job` on a thread in the pool. - pub fn execute(&self, job: F) - where F : FnOnce(), F : Send + 'static - { - self.jobs.send(Thunk::new(job)).unwrap(); - } -} - -fn spawn_in_pool(jobs: Arc>>>) { - thread::spawn(move || { - // Will spawn a new thread on panic unless it is cancelled. - let sentinel = Sentinel::new(&jobs); - - loop { - let message = { - // Only lock jobs for the time it takes - // to get a job, not run it. - let lock = jobs.lock().unwrap(); - lock.recv() - }; - - match message { - Ok(job) => job.invoke(()), - - // The Taskpool was dropped. - Err(..) => break - } - } - - sentinel.cancel(); - }); -} - -#[cfg(test)] -mod test { - use prelude::v1::*; - use super::*; - use sync::mpsc::channel; - - const TEST_TASKS: usize = 4; - - #[test] - fn test_works() { - use iter::AdditiveIterator; - - let pool = TaskPool::new(TEST_TASKS); - - let (tx, rx) = channel(); - for _ in 0..TEST_TASKS { - let tx = tx.clone(); - pool.execute(move|| { - tx.send(1).unwrap(); - }); - } - - assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS); - } - - #[test] - #[should_panic] - fn test_zero_tasks_panic() { - TaskPool::new(0); - } - - #[test] - fn test_recovery_from_subtask_panic() { - use iter::AdditiveIterator; - - let pool = TaskPool::new(TEST_TASKS); - - // Panic all the existing threads. - for _ in 0..TEST_TASKS { - pool.execute(move|| -> () { panic!() }); - } - - // Ensure new threads were spawned to compensate. - let (tx, rx) = channel(); - for _ in 0..TEST_TASKS { - let tx = tx.clone(); - pool.execute(move|| { - tx.send(1).unwrap(); - }); - } - - assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS); - } - - #[test] - fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() { - use sync::{Arc, Barrier}; - - let pool = TaskPool::new(TEST_TASKS); - let waiter = Arc::new(Barrier::new(TEST_TASKS + 1)); - - // Panic all the existing threads in a bit. - for _ in 0..TEST_TASKS { - let waiter = waiter.clone(); - pool.execute(move|| { - waiter.wait(); - panic!(); - }); - } - - drop(pool); - - // Kick off the failure. - waiter.wait(); - } -} diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index 99a554a835f..ca805ad0242 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -251,7 +251,6 @@ fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void, fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void, symaddr: *mut libc::c_void) -> io::Result<()> { use env; - use ffi::AsOsStr; use os::unix::prelude::*; use ptr; diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 2569653811f..6b085c8eb7a 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -388,9 +388,7 @@ mod tests { fn test_file_desc() { // Run this test with some pipes so we don't have to mess around with // opening or closing files. - let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() }; - let mut reader = FileDesc::new(reader, true); - let mut writer = FileDesc::new(writer, true); + let (mut reader, mut writer) = unsafe { ::sys::os::pipe().unwrap() }; writer.write(b"test").unwrap(); let mut buf = [0; 4]; diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs index 202e5ddaec4..f425c39667a 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs2.rs @@ -12,7 +12,7 @@ use core::prelude::*; use io::prelude::*; use os::unix::prelude::*; -use ffi::{CString, CStr, OsString, AsOsStr, OsStr}; +use ffi::{CString, CStr, OsString, OsStr}; use io::{self, Error, SeekFrom}; use libc::{self, c_int, size_t, off_t, c_char, mode_t}; use mem; diff --git a/src/libstd/sys/unix/helper_signal.rs b/src/libstd/sys/unix/helper_signal.rs index 17c8b21f8b3..fe0ede80fc6 100644 --- a/src/libstd/sys/unix/helper_signal.rs +++ b/src/libstd/sys/unix/helper_signal.rs @@ -11,15 +11,15 @@ #![allow(deprecated)] use libc; -use os; +use sys::os; use sys::fs::FileDesc; pub type signal = libc::c_int; pub fn new() -> (signal, signal) { - let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() }; - (reader, writer) + let (a, b) = unsafe { os::pipe().unwrap() }; + (a.unwrap(), b.unwrap()) } pub fn signal(fd: libc::c_int) { diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index fab443feebd..af5b40af938 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use os::unix::prelude::*; use error::Error as StdError; -use ffi::{CString, CStr, OsString, OsStr, AsOsStr}; +use ffi::{CString, CStr, OsString, OsStr}; use fmt; use io; use iter; @@ -125,7 +125,8 @@ pub fn getcwd() -> io::Result { } pub fn chdir(p: &path::Path) -> io::Result<()> { - let p = try!(CString::new(p.as_os_str().as_bytes())); + let p: &OsStr = p.as_ref(); + let p = try!(CString::new(p.as_bytes())); unsafe { match libc::chdir(p.as_ptr()) == (0 as c_int) { true => Ok(()), @@ -158,13 +159,13 @@ impl<'a> Iterator for SplitPaths<'a> { pub struct JoinPathsError; pub fn join_paths(paths: I) -> Result - where I: Iterator, T: AsOsStr + where I: Iterator, T: AsRef { let mut joined = Vec::new(); let sep = b':'; for (i, path) in paths.enumerate() { - let path = path.as_os_str().as_bytes(); + let path = path.as_ref().as_bytes(); if i > 0 { joined.push(sep) } if path.contains(&sep) { return Err(JoinPathsError) @@ -464,7 +465,7 @@ pub fn page_size() -> usize { } pub fn temp_dir() -> PathBuf { - getenv("TMPDIR".as_os_str()).map(os2path).unwrap_or_else(|| { + getenv("TMPDIR".as_ref()).map(os2path).unwrap_or_else(|| { if cfg!(target_os = "android") { PathBuf::from("/data/local/tmp") } else { @@ -474,7 +475,7 @@ pub fn temp_dir() -> PathBuf { } pub fn home_dir() -> Option { - return getenv("HOME".as_os_str()).or_else(|| unsafe { + return getenv("HOME".as_ref()).or_else(|| unsafe { fallback() }).map(os2path); diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 0d35ace185d..8095325f83d 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -19,8 +19,9 @@ use hash::Hash; use old_io::process::{ProcessExit, ExitStatus, ExitSignal}; use old_io::{IoResult, EndOfFile}; use libc::{self, pid_t, c_void, c_int}; +use io; use mem; -use os; +use sys::os; use old_path::BytesContainer; use ptr; use sync::mpsc::{channel, Sender, Receiver}; @@ -496,7 +497,8 @@ impl Process { n if n > 0 => { ret = true; } 0 => return true, -1 if wouldblock() => return ret, - n => panic!("bad read {:?} ({:?})", os::last_os_error(), n), + n => panic!("bad read {} ({})", + io::Error::last_os_error(), n), } } } diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs index d9a162302fc..9309147b15c 100644 --- a/src/libstd/sys/unix/timer.rs +++ b/src/libstd/sys/unix/timer.rs @@ -54,7 +54,8 @@ use self::Req::*; use old_io::IoResult; use libc; use mem; -use os; +use sys::os; +use io; use ptr; use sync::atomic::{self, Ordering}; use sync::mpsc::{channel, Sender, Receiver, TryRecvError}; @@ -209,7 +210,7 @@ fn helper(input: libc::c_int, messages: Receiver, _: ()) { -1 if os::errno() == libc::EINTR as i32 => {} n => panic!("helper thread failed in select() with error: {} ({})", - n, os::last_os_error()) + n, io::Error::last_os_error()) } } } diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 167db1e8ac2..1ebd4c571ac 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use os::windows::prelude::*; use error::Error as StdError; -use ffi::{OsString, OsStr, AsOsStr}; +use ffi::{OsString, OsStr}; use fmt; use io; use libc::types::os::arch::extra::LPWCH; @@ -199,13 +199,13 @@ impl<'a> Iterator for SplitPaths<'a> { pub struct JoinPathsError; pub fn join_paths(paths: I) -> Result - where I: Iterator, T: AsOsStr + where I: Iterator, T: AsRef { let mut joined = Vec::new(); let sep = b';' as u16; for (i, path) in paths.enumerate() { - let path = path.as_os_str(); + let path = path.as_ref(); if i > 0 { joined.push(sep) } let v = path.encode_wide().collect::>(); if v.contains(&(b'"' as u16)) { @@ -245,7 +245,8 @@ pub fn getcwd() -> io::Result { } pub fn chdir(p: &path::Path) -> io::Result<()> { - let mut p = p.as_os_str().encode_wide().collect::>(); + let p: &OsStr = p.as_ref(); + let mut p = p.encode_wide().collect::>(); p.push(0); unsafe { @@ -361,8 +362,8 @@ pub fn temp_dir() -> PathBuf { } pub fn home_dir() -> Option { - getenv("HOME".as_os_str()).or_else(|| { - getenv("USERPROFILE".as_os_str()) + getenv("HOME".as_ref()).or_else(|| { + getenv("USERPROFILE".as_ref()) }).map(PathBuf::from).or_else(|| unsafe { let me = c::GetCurrentProcess(); let mut token = ptr::null_mut(); diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 297f6e173ab..2065df4fbe3 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -23,6 +23,7 @@ use mem; use old_io::process::{ProcessExit, ExitStatus}; use old_io::{IoResult, IoError}; use old_io; +use fs::PathExt; use os; use old_path::{BytesContainer, GenericPath}; use ptr; @@ -142,14 +143,19 @@ impl Process { let program = cfg.env().and_then(|env| { for (key, v) in env { if b"PATH" != key.container_as_bytes() { continue } + let v = match ::str::from_utf8(v.container_as_bytes()) { + Ok(s) => s, + Err(..) => continue, + }; // Split the value and test each path to see if the // program exists. - for path in os::split_paths(v.container_as_bytes()) { - let path = path.join(cfg.program().as_bytes()) + for path in ::env::split_paths(v) { + let program = str::from_utf8(cfg.program().as_bytes()).unwrap(); + let path = path.join(program) .with_extension(env::consts::EXE_EXTENSION); if path.exists() { - return Some(CString::from_slice(path.as_vec())) + return Some(CString::new(path.to_str().unwrap()).unwrap()) } } break @@ -482,9 +488,9 @@ mod tests { #[test] fn test_make_command_line() { fn test_wrapper(prog: &str, args: &[&str]) -> String { - make_command_line(&CString::from_slice(prog.as_bytes()), + make_command_line(&CString::new(prog), &args.iter() - .map(|a| CString::from_slice(a.as_bytes())) + .map(|a| CString::new(a)) .collect::>()) } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index a2b824bb016..b9cbd01bed1 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -294,12 +294,6 @@ impl LocalKey { } } } - - /// Deprecated - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", - reason = "function renamed to state() and returns more info")] - pub fn destroyed(&'static self) -> bool { self.state() == LocalKeyState::Destroyed } } #[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))] diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 074030bd07b..b9515c9a8a1 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -189,8 +189,6 @@ use sys_common::{stack, thread_info}; use thunk::Thunk; use time::Duration; -#[allow(deprecated)] use old_io::Writer; - //////////////////////////////////////////////////////////////////////////////// // Thread-local storage //////////////////////////////////////////////////////////////////////////////// @@ -243,28 +241,6 @@ impl Builder { self } - /// Redirect thread-local stdout. - #[unstable(feature = "std_misc", - reason = "Will likely go away after proc removal")] - #[deprecated(since = "1.0.0", - reason = "the old I/O module is deprecated and this function \ - will be removed with no replacement")] - #[allow(deprecated)] - pub fn stdout(self, _stdout: Box) -> Builder { - self - } - - /// Redirect thread-local stderr. - #[unstable(feature = "std_misc", - reason = "Will likely go away after proc removal")] - #[deprecated(since = "1.0.0", - reason = "the old I/O module is deprecated and this function \ - will be removed with no replacement")] - #[allow(deprecated)] - pub fn stderr(self, _stderr: Box) -> Builder { - self - } - /// Spawn a new thread, and return a join handle for it. /// /// The child thread may outlive the parent (unless the parent thread @@ -568,71 +544,6 @@ impl Thread { } } - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[unstable(feature = "std_misc", - reason = "may change with specifics of new Send semantics")] - pub fn spawn(f: F) -> Thread where F: FnOnce(), F: Send + 'static { - Builder::new().spawn(f).unwrap().thread().clone() - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[unstable(feature = "std_misc", - reason = "may change with specifics of new Send semantics")] - pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where - T: Send + 'a, F: FnOnce() -> T, F: Send + 'a - { - Builder::new().scoped(f).unwrap() - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn current() -> Thread { - thread_info::current_thread() - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[unstable(feature = "std_misc", reason = "name may change")] - pub fn yield_now() { - unsafe { imp::yield_now() } - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn panicking() -> bool { - unwind::panicking() - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[unstable(feature = "std_misc", reason = "recently introduced")] - pub fn park() { - let thread = current(); - let mut guard = thread.inner.lock.lock().unwrap(); - while !*guard { - guard = thread.inner.cvar.wait(guard).unwrap(); - } - *guard = false; - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[unstable(feature = "std_misc", reason = "recently introduced")] - pub fn park_timeout(duration: Duration) { - let thread = current(); - let mut guard = thread.inner.lock.lock().unwrap(); - if !*guard { - let (g, _) = thread.inner.cvar.wait_timeout(guard, duration).unwrap(); - guard = g; - } - *guard = false; - } - /// Atomically makes the handle's token available if it is not already. /// /// See the module doc for more detail. @@ -762,8 +673,8 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> { &self.inner.thread } - /// Wait for the associated thread to finish, returning the result of the thread's - /// calculation. + /// Wait for the associated thread to finish, returning the result of the + /// thread's calculation. /// /// # Panics /// @@ -777,17 +688,6 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl JoinGuard<'static, T> { - /// Detaches the child thread, allowing it to outlive its parent. - #[deprecated(since = "1.0.0", reason = "use spawn instead")] - #[unstable(feature = "std_misc")] - pub fn detach(mut self) { - unsafe { imp::detach(self.inner.native) }; - self.inner.joined = true; // avoid joining in the destructor - } -} - #[unsafe_destructor] #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index ee0d190d729..2d56d7ddf1b 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -43,7 +43,6 @@ #![feature(std_misc)] #![feature(libc)] #![feature(set_stdio)] -#![feature(os)] #![feature(convert)] #![cfg_attr(test, feature(old_io))] @@ -857,7 +856,8 @@ fn get_concurrency() -> usize { if std::rt::util::limit_thread_creation_due_to_osx_and_valgrind() { 1 } else { - std::os::num_cpus() + extern { fn rust_get_num_cpus() -> libc::uintptr_t; } + unsafe { rust_get_num_cpus() as usize } } } } diff --git a/src/test/bench/shootout-binarytrees.rs b/src/test/bench/shootout-binarytrees.rs index 64c38722137..ce050cc7323 100644 --- a/src/test/bench/shootout-binarytrees.rs +++ b/src/test/bench/shootout-binarytrees.rs @@ -38,11 +38,10 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -#![feature(rustc_private, core)] +#![feature(rustc_private, core, step_by)] extern crate arena; -use std::iter::range_step; use std::thread; use arena::TypedArena; @@ -109,7 +108,7 @@ fn main() { let long_lived_arena = TypedArena::new(); let long_lived_tree = bottom_up_tree(&long_lived_arena, 0, max_depth); - let messages = range_step(min_depth, max_depth + 1, 2).map(|depth| { + let messages = (min_depth..max_depth + 1).step_by(2).map(|depth| { use std::num::Int; let iterations = 2.pow((max_depth - depth + min_depth) as u32); thread::scoped(move || inner(depth, iterations)) diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs index 3a1da4c32af..af9ef80e609 100644 --- a/src/test/bench/shootout-fannkuch-redux.rs +++ b/src/test/bench/shootout-fannkuch-redux.rs @@ -38,9 +38,9 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -#![feature(core)] +#![feature(step_by)] -use std::{cmp, iter, mem}; +use std::{cmp, mem}; use std::thread; fn rotate(x: &mut [i32]) { @@ -163,7 +163,7 @@ fn fannkuch(n: i32) -> (i32, i32) { let mut futures = vec![]; let k = perm.max() / N; - for (_, j) in (0..N).zip(iter::count(0, k)) { + for (_, j) in (0..N).zip((0..).step_by(k)) { let max = cmp::min(j+k, perm.max()); futures.push(thread::scoped(move|| { diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index de1d0103657..c190641bfbf 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -193,7 +193,7 @@ fn main() { // start processing if this is the one ('>', false) => { - match line[1..].find_str("THREE") { + match line[1..].find("THREE") { Some(_) => { proc_mode = true; } None => { } } diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index cd89b822035..c0268e816cf 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -118,7 +118,9 @@ fn dot(v: &[f64], u: &[f64]) -> f64 { fn parallel<'a,T, F>(v: &mut [T], ref f: F) where T: Send + Sync + 'a, F: Fn(usize, &mut [T]) + Sync + 'a { - let size = v.len() / os::num_cpus() + 1; + // FIXME: pick a more appropriate parallel factor + let parallelism = 4; + let size = v.len() / parallelism + 1; v.chunks_mut(size).enumerate().map(|(i, chunk)| { thread::scoped(move|| { f(i * size, chunk) diff --git a/src/test/compile-fail/dropck_arr_cycle_checked.rs b/src/test/compile-fail/dropck_arr_cycle_checked.rs index 3aa2fae2826..40d992fe21f 100644 --- a/src/test/compile-fail/dropck_arr_cycle_checked.rs +++ b/src/test/compile-fail/dropck_arr_cycle_checked.rs @@ -20,9 +20,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; pub fn next_count() -> usize { S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 diff --git a/src/test/compile-fail/dropck_tarena_cycle_checked.rs b/src/test/compile-fail/dropck_tarena_cycle_checked.rs index 74e3c724b67..9488882ca94 100644 --- a/src/test/compile-fail/dropck_tarena_cycle_checked.rs +++ b/src/test/compile-fail/dropck_tarena_cycle_checked.rs @@ -27,9 +27,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; pub fn next_count() -> usize { S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 diff --git a/src/test/compile-fail/dropck_vec_cycle_checked.rs b/src/test/compile-fail/dropck_vec_cycle_checked.rs index 3f69c7d1a9c..9d92552244f 100644 --- a/src/test/compile-fail/dropck_vec_cycle_checked.rs +++ b/src/test/compile-fail/dropck_vec_cycle_checked.rs @@ -19,9 +19,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; pub fn next_count() -> usize { S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 diff --git a/src/test/compile-fail/estr-subtyping.rs b/src/test/compile-fail/estr-subtyping.rs index 6e64e01d741..b5c6db0cea9 100644 --- a/src/test/compile-fail/estr-subtyping.rs +++ b/src/test/compile-fail/estr-subtyping.rs @@ -18,7 +18,7 @@ fn has_uniq(x: String) { fn has_slice(x: &str) { wants_uniq(x); //~ ERROR mismatched types - wants_slice(x.as_slice()); + wants_slice(x); } fn main() { diff --git a/src/test/compile-fail/issue-13058.rs b/src/test/compile-fail/issue-13058.rs index 50c4ac94d90..8886dd80be5 100644 --- a/src/test/compile-fail/issue-13058.rs +++ b/src/test/compile-fail/issue-13058.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::iter::{Range,range}; +use std::ops::Range; trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } impl<'r> Itble<'r, usize, Range> for (usize, usize) { fn iter(&'r self) -> Range { let &(min, max) = self; - range(min, max) + min..max } } diff --git a/src/test/compile-fail/issue-17651.rs b/src/test/compile-fail/issue-17651.rs index 8ebf80a8db0..9e49abc463f 100644 --- a/src/test/compile-fail/issue-17651.rs +++ b/src/test/compile-fail/issue-17651.rs @@ -13,6 +13,6 @@ fn main() { // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - (|| Box::new(*[0].as_slice()))(); + (|| Box::new(*(&[0][..])))(); //~^ ERROR the trait `core::marker::Sized` is not implemented for the type `[_]` } diff --git a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs index 0a8e4514b43..d2d0dbf3e98 100644 --- a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs +++ b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs @@ -10,14 +10,14 @@ // ignore-tidy-linelength -use std::iter::{Range,range}; +use std::ops::Range; trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } impl<'r> Itble<'r, usize, Range> for (usize, usize) { fn iter(&'r self) -> Range { let &(min, max) = self; - range(min, max) + min..max } } diff --git a/src/test/compile-fail/variance-deprecated-markers.rs b/src/test/compile-fail/variance-deprecated-markers.rs deleted file mode 100644 index 8f9d24cb132..00000000000 --- a/src/test/compile-fail/variance-deprecated-markers.rs +++ /dev/null @@ -1,35 +0,0 @@ -// 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 that the deprecated markers still have their old effect. - -#![feature(rustc_attrs)] - -use std::marker; - -#[rustc_variance] -struct A(marker::CovariantType); //~ ERROR types=[[+];[];[]] - -#[rustc_variance] -struct B(marker::ContravariantType); //~ ERROR types=[[-];[];[]] - -#[rustc_variance] -struct C(marker::InvariantType); //~ ERROR types=[[o];[];[]] - -#[rustc_variance] -struct D<'a>(marker::CovariantLifetime<'a>); //~ ERROR regions=[[+];[];[]] - -#[rustc_variance] -struct E<'a>(marker::ContravariantLifetime<'a>); //~ ERROR regions=[[-];[];[]] - -#[rustc_variance] -struct F<'a>(marker::InvariantLifetime<'a>); //~ ERROR regions=[[o];[];[]] - -fn main() { } diff --git a/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs b/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs index 6aaf51278af..44a3f716e3e 100644 --- a/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs +++ b/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs @@ -30,9 +30,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; /// generates globally unique count (global across the current /// process, that is) diff --git a/src/test/compile-fail/vec_refs_data_with_early_death.rs b/src/test/compile-fail/vec_refs_data_with_early_death.rs index a191b3e56c4..0025449a3db 100644 --- a/src/test/compile-fail/vec_refs_data_with_early_death.rs +++ b/src/test/compile-fail/vec_refs_data_with_early_death.rs @@ -27,5 +27,5 @@ fn main() { v.push(&x); //~ ERROR `x` does not live long enough v.push(&y); //~ ERROR `y` does not live long enough - assert_eq!(v.as_slice(), [&3, &4]); + assert_eq!(v, [&3, &4]); } diff --git a/src/test/run-fail/rt-set-exit-status-panic.rs b/src/test/run-fail/rt-set-exit-status-panic.rs index 0e72ab22dc8..249e2e1ac2d 100644 --- a/src/test/run-fail/rt-set-exit-status-panic.rs +++ b/src/test/run-fail/rt-set-exit-status-panic.rs @@ -10,16 +10,16 @@ // error-pattern:whatever -#![feature(os, rustc_private)] +#![feature(exit_status, rustc_private)] #[macro_use] extern crate log; -use std::os; +use std::env; fn main() { error!("whatever"); // Setting the exit status only works when the scheduler terminates // normally. In this case we're going to panic, so instead of // returning 50 the process will return the typical rt failure code. - os::set_exit_status(50); + env::set_exit_status(50); panic!(); } diff --git a/src/test/run-fail/rt-set-exit-status-panic2.rs b/src/test/run-fail/rt-set-exit-status-panic2.rs index a71ce9ebab5..fddff3c5a9f 100644 --- a/src/test/run-fail/rt-set-exit-status-panic2.rs +++ b/src/test/run-fail/rt-set-exit-status-panic2.rs @@ -10,10 +10,10 @@ // error-pattern:whatever -#![feature(os, rustc_private)] +#![feature(exit_status, rustc_private)] #[macro_use] extern crate log; -use std::os; +use std::env; use std::thread; struct r { @@ -25,7 +25,7 @@ struct r { // runtime's exit code impl Drop for r { fn drop(&mut self) { - os::set_exit_status(50); + env::set_exit_status(50); } } diff --git a/src/test/run-fail/rt-set-exit-status.rs b/src/test/run-fail/rt-set-exit-status.rs index 9425a1b1902..c33a8d2d032 100644 --- a/src/test/run-fail/rt-set-exit-status.rs +++ b/src/test/run-fail/rt-set-exit-status.rs @@ -10,14 +10,14 @@ // error-pattern:whatever -#![feature(rustc_private, os)] +#![feature(rustc_private, exit_status)] #[macro_use] extern crate log; -use std::os; +use std::env; fn main() { error!("whatever"); // 101 is the code the runtime uses on task panic and the value // compiletest expects run-fail tests to return. - os::set_exit_status(101); + env::set_exit_status(101); } diff --git a/src/test/run-make/link-path-order/main.rs b/src/test/run-make/link-path-order/main.rs index b1576ccd48e..c1787eb03f5 100644 --- a/src/test/run-make/link-path-order/main.rs +++ b/src/test/run-make/link-path-order/main.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(libc, os)] +#![feature(libc, exit_status)] extern crate libc; @@ -23,6 +23,6 @@ fn main() { }; if result != 1 { - std::os::set_exit_status(255); + std::env::set_exit_status(255); } } diff --git a/src/test/run-make/unicode-input/span_length.rs b/src/test/run-make/unicode-input/span_length.rs index ebf3226334c..a70a1600765 100644 --- a/src/test/run-make/unicode-input/span_length.rs +++ b/src/test/run-make/unicode-input/span_length.rs @@ -95,10 +95,10 @@ fn main() { let expected_span = format!("\n{}^{}\n", repeat(" ").take(offset + 7).collect::(), repeat("~").take(8).collect::()); - assert!(err.contains(expected_span.as_slice())); + assert!(err.contains(&expected_span)); // Second snake is 8 ~s long, with 36 preceding spaces let expected_span = format!("\n{}^{}\n", repeat(" ").take(offset + 36).collect::(), repeat("~").take(8).collect::()); - assert!(err.contains(expected_span.as_slice())); + assert!(err.contains(&expected_span)); } diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs index 7a3c32a45f9..4bacde0aadf 100644 --- a/src/test/run-pass-fulldeps/compiler-calls.rs +++ b/src/test/run-pass-fulldeps/compiler-calls.rs @@ -77,6 +77,6 @@ fn main() { let mut tc = TestCalls { count: 1 }; // we should never get use this filename, but lets make sure they are valid args. let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; - rustc_driver::run_compiler(args.as_slice(), &mut tc); + rustc_driver::run_compiler(&args, &mut tc); assert!(tc.count == 30); } diff --git a/src/test/run-pass/create-dir-all-bare.rs b/src/test/run-pass-fulldeps/create-dir-all-bare.rs similarity index 86% rename from src/test/run-pass/create-dir-all-bare.rs rename to src/test/run-pass-fulldeps/create-dir-all-bare.rs index 475df629f63..d09d7c55722 100644 --- a/src/test/run-pass/create-dir-all-bare.rs +++ b/src/test/run-pass-fulldeps/create-dir-all-bare.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(tempdir)] +#![feature(rustc_private)] + +extern crate rustc_back; use std::env; -use std::fs::{self, TempDir}; +use std::fs; +use rustc_back::tempdir::TempDir; fn main() { let td = TempDir::new("create-dir-all-bare").unwrap(); diff --git a/src/test/run-pass/rename-directory.rs b/src/test/run-pass-fulldeps/rename-directory.rs similarity index 90% rename from src/test/run-pass/rename-directory.rs rename to src/test/run-pass-fulldeps/rename-directory.rs index f149a70817a..fa810f72fcb 100644 --- a/src/test/run-pass/rename-directory.rs +++ b/src/test/run-pass-fulldeps/rename-directory.rs @@ -13,10 +13,13 @@ // pretty-expanded FIXME #23616 -#![feature(tempdir, path_ext)] +#![feature(rustc_private, path_ext)] + +extern crate rustc_back; use std::ffi::CString; -use std::fs::{self, TempDir, File, PathExt}; +use std::fs::{self, File, PathExt}; +use rustc_back::tempdir::TempDir; fn rename_directory() { let tmpdir = TempDir::new("rename_directory").ok().expect("rename_directory failed"); diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index 226a7c12df9..14d8bce061f 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -80,9 +80,9 @@ fn runtest(me: &str) { let s = str::from_utf8(&out.error).unwrap(); let mut i = 0; for _ in 0..2 { - i += s[i + 10..].find_str("stack backtrace").unwrap() + 10; + i += s[i + 10..].find("stack backtrace").unwrap() + 10; } - assert!(s[i + 10..].find_str("stack backtrace").is_none(), + assert!(s[i + 10..].find("stack backtrace").is_none(), "bad output4: {}", s); } diff --git a/src/test/run-pass/capturing-logging.rs b/src/test/run-pass/capturing-logging.rs index b20de7113ec..f9b429a935a 100644 --- a/src/test/run-pass/capturing-logging.rs +++ b/src/test/run-pass/capturing-logging.rs @@ -22,7 +22,7 @@ use log::{set_logger, Logger, LogRecord}; use std::sync::mpsc::channel; use std::fmt; use std::old_io::{ChanReader, ChanWriter, Reader, Writer}; -use std::thread::Thread; +use std::thread; struct MyWriter(ChanWriter); @@ -36,7 +36,7 @@ impl Logger for MyWriter { fn main() { let (tx, rx) = channel(); let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx)); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { set_logger(box MyWriter(w) as Box); debug!("debug"); info!("info"); diff --git a/src/test/run-pass/child-outlives-parent.rs b/src/test/run-pass/child-outlives-parent.rs index 64642e51c09..7da1416602f 100644 --- a/src/test/run-pass/child-outlives-parent.rs +++ b/src/test/run-pass/child-outlives-parent.rs @@ -14,10 +14,10 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; fn child2(_s: String) { } pub fn main() { - let _x = Thread::spawn(move|| child2("hi".to_string())); + let _x = thread::spawn(move|| child2("hi".to_string())); } diff --git a/src/test/run-pass/clone-with-exterior.rs b/src/test/run-pass/clone-with-exterior.rs index fa663105ccd..16efceb9d7e 100644 --- a/src/test/run-pass/clone-with-exterior.rs +++ b/src/test/run-pass/clone-with-exterior.rs @@ -13,7 +13,7 @@ #![allow(unknown_features)] #![feature(box_syntax, std_misc)] -use std::thread::Thread; +use std::thread; struct Pair { a: isize, @@ -23,7 +23,7 @@ struct Pair { pub fn main() { let z: Box<_> = box Pair { a : 10, b : 12}; - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { assert_eq!(z.a, 10); assert_eq!(z.b, 12); }); diff --git a/src/test/run-pass/comm.rs b/src/test/run-pass/comm.rs index 43f10cfd060..859599596ae 100644 --- a/src/test/run-pass/comm.rs +++ b/src/test/run-pass/comm.rs @@ -10,12 +10,12 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { child(&tx) }); + let _t = thread::scoped(move|| { child(&tx) }); let y = rx.recv().unwrap(); println!("received"); println!("{}", y); diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index a969f691154..03bf3851257 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -24,7 +24,7 @@ use std::old_io::{Process, Command, timer}; use std::time::Duration; use std::str; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; macro_rules! succeed { ($e:expr) => ( match $e { Ok(..) => {}, Err(e) => panic!("panic: {}", e) } @@ -86,7 +86,7 @@ pub fn test_destroy_actually_kills(force: bool) { let (tx, rx1) = channel(); let mut t = timer::Timer::new().unwrap(); let rx2 = t.oneshot(Duration::milliseconds(1000)); - Thread::spawn(move|| { + thread::spawn(move|| { select! { _ = rx2.recv() => unsafe { libc::exit(1) }, _ = rx1.recv() => {} diff --git a/src/test/run-pass/drop-with-type-ascription-2.rs b/src/test/run-pass/drop-with-type-ascription-2.rs index ddfaf54493f..3d4af80e30b 100644 --- a/src/test/run-pass/drop-with-type-ascription-2.rs +++ b/src/test/run-pass/drop-with-type-ascription-2.rs @@ -14,7 +14,7 @@ fn main() { let args = vec!("foobie", "asdf::asdf"); - let arr: Vec<&str> = args[1].split_str("::").collect(); + let arr: Vec<&str> = args[1].split("::").collect(); assert_eq!(arr[0], "asdf"); assert_eq!(arr[0], "asdf"); } diff --git a/src/test/run-pass/extern-call-scrub.rs b/src/test/run-pass/extern-call-scrub.rs index 069ecd92a56..e8c9bc76335 100644 --- a/src/test/run-pass/extern-call-scrub.rs +++ b/src/test/run-pass/extern-call-scrub.rs @@ -15,7 +15,7 @@ #![feature(libc, std_misc)] extern crate libc; -use std::thread::Thread; +use std::thread; mod rustrt { extern crate libc; @@ -46,7 +46,7 @@ fn count(n: libc::uintptr_t) -> libc::uintptr_t { pub fn main() { // Make sure we're on a task with small Rust stacks (main currently // has a large stack) - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let result = count(12); println!("result = {}", result); assert_eq!(result, 2048); diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index 3d1b74438a8..5c96aaf4bd8 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -25,7 +25,7 @@ mod map_reduce { use std::collections::HashMap; use std::sync::mpsc::{channel, Sender}; use std::str; - use std::thread::Thread; + use std::thread; pub type putter<'a> = Box; @@ -37,7 +37,7 @@ mod map_reduce { for i in &inputs { let ctrl = ctrl.clone(); let i = i.clone(); - Thread::spawn(move|| map_task(ctrl.clone(), i.clone()) ); + thread::spawn(move|| map_task(ctrl.clone(), i.clone()) ); } } diff --git a/src/test/run-pass/init-large-type.rs b/src/test/run-pass/init-large-type.rs index ca4dba4198c..26d58d34b9d 100644 --- a/src/test/run-pass/init-large-type.rs +++ b/src/test/run-pass/init-large-type.rs @@ -16,7 +16,7 @@ #![feature(intrinsics, std_misc)] -use std::thread::Thread; +use std::thread; extern "rust-intrinsic" { pub fn init() -> T; @@ -26,7 +26,7 @@ const SIZE: usize = 1024 * 1024; fn main() { // do the test in a new thread to avoid (spurious?) stack overflows - let _ = Thread::scoped(|| { + let _ = thread::scoped(|| { let _memory: [u8; SIZE] = unsafe { init() }; }).join(); } diff --git a/src/test/run-pass/issue-13304.rs b/src/test/run-pass/issue-13304.rs index 876b329998e..c260aa95b57 100644 --- a/src/test/run-pass/issue-13304.rs +++ b/src/test/run-pass/issue-13304.rs @@ -29,8 +29,8 @@ fn main() { fn parent() { let args: Vec = env::args().collect(); let mut p = Command::new(&args[0]).arg("child") - .stdout(Stdio::capture()) - .stdin(Stdio::capture()) + .stdout(Stdio::piped()) + .stdin(Stdio::piped()) .spawn().unwrap(); p.stdin.as_mut().unwrap().write_all(b"test1\ntest2\ntest3").unwrap(); let out = p.wait_with_output().unwrap(); diff --git a/src/test/run-pass/issue-13494.rs b/src/test/run-pass/issue-13494.rs index 6159edbfe1e..d1b1647de78 100644 --- a/src/test/run-pass/issue-13494.rs +++ b/src/test/run-pass/issue-13494.rs @@ -16,7 +16,7 @@ #![feature(std_misc)] use std::sync::mpsc::{channel, Sender, Receiver}; -use std::thread::Thread; +use std::thread; fn helper(rx: Receiver>) { for tx in rx.iter() { @@ -26,7 +26,7 @@ fn helper(rx: Receiver>) { fn main() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { helper(rx) }); + let _t = thread::scoped(move|| { helper(rx) }); let (snd, rcv) = channel::(); for _ in 1..100000 { snd.send(1).unwrap(); @@ -37,4 +37,5 @@ fn main() { _ = rcv.recv() => () } } + drop(tx); } diff --git a/src/test/run-pass/issue-14456.rs b/src/test/run-pass/issue-14456.rs index f897b00ceff..ab9633ca1fe 100644 --- a/src/test/run-pass/issue-14456.rs +++ b/src/test/run-pass/issue-14456.rs @@ -38,9 +38,9 @@ fn child() { fn test() { let args: Vec = env::args().collect(); let mut p = Command::new(&args[0]).arg("child") - .stdin(Stdio::capture()) - .stdout(Stdio::capture()) - .stderr(Stdio::capture()) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) .spawn().unwrap(); assert!(p.wait().unwrap().success()); } diff --git a/src/test/run-pass/issue-17351.rs b/src/test/run-pass/issue-17351.rs index 0dac3295c1b..6e93194647a 100644 --- a/src/test/run-pass/issue-17351.rs +++ b/src/test/run-pass/issue-17351.rs @@ -12,6 +12,10 @@ #![feature(core)] +trait Str { fn foo(&self) {} } +impl Str for str {} +impl<'a, S: ?Sized> Str for &'a S where S: Str {} + fn main() { let _: &Str = &"x"; } diff --git a/src/test/run-pass/issue-20454.rs b/src/test/run-pass/issue-20454.rs index 0e3d4e0e40d..d527d9519cf 100644 --- a/src/test/run-pass/issue-20454.rs +++ b/src/test/run-pass/issue-20454.rs @@ -12,10 +12,12 @@ use std::thread; -fn main() { - thread::Thread::spawn(move || { // no need for -> () +fn _foo() { + let _t = thread::scoped(move || { // no need for -> () loop { println!("hello"); } }); } + +fn main() {} diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index 7842bcb7dd1..71d1439dd2b 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -21,7 +21,7 @@ pub mod pipes { use std::mem::{forget, transmute}; use std::mem::{replace, swap}; use std::mem; - use std::thread::Thread; + use std::thread; use std::marker::Send; pub struct Stuff { @@ -115,7 +115,7 @@ pub mod pipes { let old_state = swap_state_acq(&mut (*p).state, blocked); match old_state { - empty | blocked => { Thread::yield_now(); } + empty | blocked => { thread::yield_now(); } full => { let payload = replace(&mut p.payload, None); return Some(payload.unwrap()) diff --git a/src/test/run-pass/issue-3609.rs b/src/test/run-pass/issue-3609.rs index 2bd56e81687..45eb21374e2 100644 --- a/src/test/run-pass/issue-3609.rs +++ b/src/test/run-pass/issue-3609.rs @@ -11,7 +11,7 @@ #![allow(unknown_features)] #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::Sender; use std::thunk::Invoke; @@ -24,7 +24,7 @@ enum Msg } fn foo(name: String, samples_chan: Sender) { - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let mut samples_chan = samples_chan; // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. diff --git a/src/test/run-pass/issue-8827.rs b/src/test/run-pass/issue-8827.rs index 4e1ff84291e..280311af6fb 100644 --- a/src/test/run-pass/issue-8827.rs +++ b/src/test/run-pass/issue-8827.rs @@ -10,12 +10,12 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Receiver}; fn periodical(n: isize) -> Receiver { let (chan, port) = channel(); - Thread::spawn(move|| { + thread::spawn(move|| { loop { for _ in 1..n { match chan.send(false) { @@ -34,7 +34,7 @@ fn periodical(n: isize) -> Receiver { fn integers() -> Receiver { let (chan, port) = channel(); - Thread::spawn(move|| { + thread::spawn(move|| { let mut i = 1; loop { match chan.send(i) { diff --git a/src/test/run-pass/issue-9396.rs b/src/test/run-pass/issue-9396.rs index aeba6889f49..bfaf060e43c 100644 --- a/src/test/run-pass/issue-9396.rs +++ b/src/test/run-pass/issue-9396.rs @@ -14,12 +14,12 @@ use std::sync::mpsc::{TryRecvError, channel}; use std::old_io::timer::Timer; -use std::thread::Thread; +use std::thread; use std::time::Duration; pub fn main() { let (tx, rx) = channel(); - let _t = Thread::scoped(move||{ + let _t = thread::scoped(move||{ let mut timer = Timer::new().unwrap(); timer.sleep(Duration::milliseconds(10)); tx.send(()).unwrap(); diff --git a/src/test/run-pass/ivec-tag.rs b/src/test/run-pass/ivec-tag.rs index d5138f6fdbc..8ae084dce8c 100644 --- a/src/test/run-pass/ivec-tag.rs +++ b/src/test/run-pass/ivec-tag.rs @@ -12,7 +12,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; fn producer(tx: &Sender>) { @@ -23,7 +23,7 @@ fn producer(tx: &Sender>) { pub fn main() { let (tx, rx) = channel::>(); - let _prod = Thread::spawn(move|| { + let _prod = thread::scoped(move|| { producer(&tx) }); diff --git a/src/test/run-pass/kindck-implicit-close-over-mut-var.rs b/src/test/run-pass/kindck-implicit-close-over-mut-var.rs index 4645e8ff392..11b1d70137d 100644 --- a/src/test/run-pass/kindck-implicit-close-over-mut-var.rs +++ b/src/test/run-pass/kindck-implicit-close-over-mut-var.rs @@ -10,7 +10,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; fn user(_i: isize) {} @@ -18,7 +18,7 @@ fn foo() { // Here, i is *copied* into the proc (heap closure). // Requires allocation. The proc's copy is not mutable. let mut i = 0; - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { user(i); println!("spawned {}", i) }); @@ -31,7 +31,7 @@ fn bar() { // mutable outside of the proc. let mut i = 0; while i < 10 { - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { user(i); }); i += 1; @@ -42,7 +42,7 @@ fn car() { // Here, i must be shadowed in the proc to be mutable. let mut i = 0; while i < 10 { - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let mut i = i; i += 1; user(i); diff --git a/src/test/run-pass/macro-with-braces-in-expr-position.rs b/src/test/run-pass/macro-with-braces-in-expr-position.rs index 80a3b8c9edd..4881a5ab647 100644 --- a/src/test/run-pass/macro-with-braces-in-expr-position.rs +++ b/src/test/run-pass/macro-with-braces-in-expr-position.rs @@ -10,13 +10,13 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; macro_rules! expr { ($e: expr) => { $e } } macro_rules! spawn { ($($code: tt)*) => { - expr!(Thread::spawn(move|| {$($code)*})) + expr!(thread::spawn(move|| {$($code)*})) } } diff --git a/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs b/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs index 329b77776b6..77072bdec90 100644 --- a/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs +++ b/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs @@ -33,6 +33,6 @@ impl B for *const [T] { fn main() { let x: [isize; 4] = [1,2,3,4]; - let xptr = x.as_slice() as *const [isize]; + let xptr = &x[..] as *const [isize]; xptr.foo(); } diff --git a/src/test/run-pass/moves-based-on-type-capture-clause.rs b/src/test/run-pass/moves-based-on-type-capture-clause.rs index f0eba366e71..b6509d28036 100644 --- a/src/test/run-pass/moves-based-on-type-capture-clause.rs +++ b/src/test/run-pass/moves-based-on-type-capture-clause.rs @@ -10,11 +10,11 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; pub fn main() { let x = "Hello world!".to_string(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { println!("{}", x); }); } diff --git a/src/test/run-pass/option-ext.rs b/src/test/run-pass/option-ext.rs index 8f5a5e8ece7..03ba6097cd9 100644 --- a/src/test/run-pass/option-ext.rs +++ b/src/test/run-pass/option-ext.rs @@ -12,7 +12,7 @@ pub fn main() { let thing = "{{ f }}"; - let f = thing.find_str("{{"); + let f = thing.find("{{"); if f.is_none() { println!("None!"); diff --git a/src/test/run-pass/out-of-stack-new-thread-no-split.rs b/src/test/run-pass/out-of-stack-new-thread-no-split.rs index 3c322f72b75..f08ed6e7f9c 100644 --- a/src/test/run-pass/out-of-stack-new-thread-no-split.rs +++ b/src/test/run-pass/out-of-stack-new-thread-no-split.rs @@ -18,7 +18,7 @@ use std::old_io::process::Command; use std::env; -use std::thread::Thread; +use std::thread; // lifted from the test module // Inlining to avoid llvm turning the recursive functions into tail calls, @@ -37,7 +37,7 @@ fn recurse() { fn main() { let args: Vec = env::args().collect(); if args.len() > 1 && args[1] == "recurse" { - let _t = Thread::scoped(recurse); + let _t = thread::scoped(recurse); } else { let recurse = Command::new(&args[0]).arg("recurse").output().unwrap(); assert!(!recurse.status.success()); diff --git a/src/test/run-pass/running-with-no-runtime.rs b/src/test/run-pass/running-with-no-runtime.rs index c5b59e6c6e0..abad08c7ac6 100644 --- a/src/test/run-pass/running-with-no-runtime.rs +++ b/src/test/run-pass/running-with-no-runtime.rs @@ -10,7 +10,7 @@ #![feature(start, os, std_misc, old_io)] -use std::ffi; +use std::ffi::CStr; use std::old_io::process::{Command, ProcessOutput}; use std::os; use std::rt::unwind::try; @@ -38,7 +38,7 @@ fn start(argc: isize, argv: *const *const u8) -> isize { let args = unsafe { (0..argc as usize).map(|i| { let ptr = *argv.offset(i as isize) as *const _; - ffi::c_str_to_bytes(&ptr).to_vec() + CStr::from_ptr(ptr).to_bytes().to_vec() }).collect::>() }; let me = &*args[0]; diff --git a/src/test/run-pass/rust-log-filter.rs b/src/test/run-pass/rust-log-filter.rs index bc379f1a76f..660b1e2036d 100644 --- a/src/test/run-pass/rust-log-filter.rs +++ b/src/test/run-pass/rust-log-filter.rs @@ -19,7 +19,7 @@ extern crate log; use std::sync::mpsc::{channel, Sender, Receiver}; -use std::thread::Thread; +use std::thread; pub struct ChannelLogger { tx: Sender @@ -41,7 +41,7 @@ impl log::Logger for ChannelLogger { pub fn main() { let (logger, rx) = ChannelLogger::new(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { log::set_logger(logger); info!("foo"); 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 index 5815eaa01ea..99ae3b7c7d8 100644 --- a/src/test/run-pass/send-is-not-static-par-for.rs +++ b/src/test/run-pass/send-is-not-static-par-for.rs @@ -11,7 +11,7 @@ // pretty-expanded FIXME #23616 #![feature(core, std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::Mutex; fn par_for(iter: I, f: F) @@ -21,7 +21,7 @@ fn par_for(iter: I, f: F) { let f = &f; let _guards: Vec<_> = iter.map(|elem| { - Thread::scoped(move || { + thread::scoped(move || { f(elem) }) }).collect(); diff --git a/src/test/run-pass/send-resource.rs b/src/test/run-pass/send-resource.rs index 2c897c48a33..3f64b2adb63 100644 --- a/src/test/run-pass/send-resource.rs +++ b/src/test/run-pass/send-resource.rs @@ -12,7 +12,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::channel; struct test { @@ -32,7 +32,7 @@ fn test(f: isize) -> test { pub fn main() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let (tx2, rx2) = channel(); tx.send(tx2).unwrap(); diff --git a/src/test/run-pass/stat.rs b/src/test/run-pass/stat.rs deleted file mode 100644 index c453f9252ef..00000000000 --- a/src/test/run-pass/stat.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012-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. - -// pretty-expanded FIXME #23616 - -#![feature(tempdir, path_ext)] - -use std::fs::{File, TempDir}; -use std::io::prelude::*; - -pub fn main() { - let dir = TempDir::new_in(".", "").unwrap(); - let path = dir.path().join("file"); - - { - match File::create(&path) { - Err(..) => unreachable!(), - Ok(f) => { - let mut f = f; - for _ in 0..1000 { - f.write(&[0]); - } - } - } - } - - assert!(path.exists()); - assert_eq!(path.metadata().unwrap().len(), 1000); -} diff --git a/src/test/run-pass/syntax-extension-source-utils.rs b/src/test/run-pass/syntax-extension-source-utils.rs index b3f503aad34..8834fd39d1d 100644 --- a/src/test/run-pass/syntax-extension-source-utils.rs +++ b/src/test/run-pass/syntax-extension-source-utils.rs @@ -36,7 +36,6 @@ pub fn main() { assert!( include_str!("syntax-extension-source-utils-files/includeme.\ fragment").to_string() - .as_slice() .starts_with("/* this is for ")); assert!( include_bytes!("syntax-extension-source-utils-files/includeme.fragment") @@ -44,8 +43,5 @@ pub fn main() { // The Windows tests are wrapped in an extra module for some reason assert!((m1::m2::where_am_i().ends_with("m1::m2"))); - assert!(match (47, "( 2 * 3 ) + 5") { - (line!(), stringify!((2*3) + 5)) => true, - _ => false - }) + assert_eq!((46, "( 2 * 3 ) + 5"), (line!(), stringify!((2*3) + 5))); } diff --git a/src/test/run-pass/task-comm-0.rs b/src/test/run-pass/task-comm-0.rs index 05197cd6a3d..786dd2c7612 100644 --- a/src/test/run-pass/task-comm-0.rs +++ b/src/test/run-pass/task-comm-0.rs @@ -10,7 +10,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { test05(); } @@ -26,7 +26,7 @@ fn test05_start(tx : &Sender) { fn test05() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { test05_start(&tx) }); + let _t = thread::scoped(move|| { test05_start(&tx) }); let mut value: isize = rx.recv().unwrap(); println!("{}", value); value = rx.recv().unwrap(); diff --git a/src/test/run-pass/task-comm-1.rs b/src/test/run-pass/task-comm-1.rs index e882d8506fc..9c3466f162b 100644 --- a/src/test/run-pass/task-comm-1.rs +++ b/src/test/run-pass/task-comm-1.rs @@ -10,13 +10,13 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; pub fn main() { test00(); } fn start() { println!("Started / Finished task."); } fn test00() { - let _ = Thread::scoped(move|| start() ).join(); + let _ = thread::scoped(move|| start() ).join(); println!("Completing."); } diff --git a/src/test/run-pass/task-comm-10.rs b/src/test/run-pass/task-comm-10.rs index 99eebdb601a..f25bb3ff71a 100644 --- a/src/test/run-pass/task-comm-10.rs +++ b/src/test/run-pass/task-comm-10.rs @@ -10,7 +10,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; fn start(tx: &Sender>) { @@ -29,10 +29,10 @@ fn start(tx: &Sender>) { pub fn main() { let (tx, rx) = channel(); - let _child = Thread::spawn(move|| { start(&tx) }); + let _child = thread::scoped(move|| { start(&tx) }); let mut c = rx.recv().unwrap(); c.send("A".to_string()).unwrap(); c.send("B".to_string()).unwrap(); - Thread::yield_now(); + thread::yield_now(); } diff --git a/src/test/run-pass/task-comm-11.rs b/src/test/run-pass/task-comm-11.rs index 9ef5afab2e0..ec9ed53c1dc 100644 --- a/src/test/run-pass/task-comm-11.rs +++ b/src/test/run-pass/task-comm-11.rs @@ -13,7 +13,7 @@ #![feature(std_misc)] use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; fn start(tx: &Sender>) { let (tx2, _rx) = channel(); @@ -22,7 +22,7 @@ fn start(tx: &Sender>) { pub fn main() { let (tx, rx) = channel(); - let _child = Thread::spawn(move|| { + let _child = thread::scoped(move|| { start(&tx) }); let _tx = rx.recv().unwrap(); diff --git a/src/test/run-pass/task-comm-12.rs b/src/test/run-pass/task-comm-12.rs index 8921529c6be..03305091a2d 100644 --- a/src/test/run-pass/task-comm-12.rs +++ b/src/test/run-pass/task-comm-12.rs @@ -10,7 +10,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; pub fn main() { test00(); } @@ -18,14 +18,14 @@ fn start(_task_number: isize) { println!("Started / Finished task."); } fn test00() { let i: isize = 0; - let mut result = Thread::scoped(move|| { + let mut result = thread::scoped(move|| { start(i) }); // Sleep long enough for the task to finish. let mut i = 0_usize; while i < 10000 { - Thread::yield_now(); + thread::yield_now(); i += 1; } diff --git a/src/test/run-pass/task-comm-13.rs b/src/test/run-pass/task-comm-13.rs index 3a0757548e8..15ceacd672f 100644 --- a/src/test/run-pass/task-comm-13.rs +++ b/src/test/run-pass/task-comm-13.rs @@ -11,7 +11,7 @@ #![feature(std_misc)] use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; fn start(tx: &Sender, start: isize, number_of_messages: isize) { let mut i: isize = 0; @@ -21,6 +21,6 @@ fn start(tx: &Sender, start: isize, number_of_messages: isize) { pub fn main() { println!("Check that we don't deadlock."); let (tx, rx) = channel(); - let _ = Thread::scoped(move|| { start(&tx, 0, 10) }).join(); + let _t = thread::scoped(move|| { start(&tx, 0, 10) }).join(); println!("Joined task"); } diff --git a/src/test/run-pass/task-comm-14.rs b/src/test/run-pass/task-comm-14.rs index 2ef09cdcf87..1e2d9fe52df 100644 --- a/src/test/run-pass/task-comm-14.rs +++ b/src/test/run-pass/task-comm-14.rs @@ -11,7 +11,7 @@ #![feature(std_misc)] use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; pub fn main() { let (tx, rx) = channel(); @@ -21,7 +21,7 @@ pub fn main() { while (i > 0) { println!("{}", i); let tx = tx.clone(); - Thread::spawn({let i = i; move|| { child(i, &tx) }}); + thread::scoped({let i = i; move|| { child(i, &tx) }}); i = i - 1; } diff --git a/src/test/run-pass/task-comm-15.rs b/src/test/run-pass/task-comm-15.rs index 605900495b5..2663595aecf 100644 --- a/src/test/run-pass/task-comm-15.rs +++ b/src/test/run-pass/task-comm-15.rs @@ -13,7 +13,7 @@ #![feature(std_misc)] use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; fn start(tx: &Sender, i0: isize) { let mut i = i0; @@ -29,7 +29,7 @@ pub fn main() { // the child's point of view the receiver may die. We should // drop messages on the floor in this case, and not crash! let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { start(&tx, 10) }); rx.recv(); diff --git a/src/test/run-pass/task-comm-17.rs b/src/test/run-pass/task-comm-17.rs index 6c27292d19d..de334c77aa3 100644 --- a/src/test/run-pass/task-comm-17.rs +++ b/src/test/run-pass/task-comm-17.rs @@ -16,11 +16,11 @@ // This test is specifically about spawning temporary closures. -use std::thread::Thread; +use std::thread; fn f() { } pub fn main() { - let _t = Thread::scoped(move|| f() ).join(); + let _t = thread::scoped(move|| f() ).join(); } diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs index d742b7bb11a..254ad653c48 100644 --- a/src/test/run-pass/task-comm-3.rs +++ b/src/test/run-pass/task-comm-3.rs @@ -12,7 +12,7 @@ // no-pretty-expanded FIXME #15189 -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); } @@ -42,7 +42,7 @@ fn test00() { let mut results = Vec::new(); while i < number_of_tasks { let tx = tx.clone(); - results.push(Thread::scoped({ + results.push(thread::scoped({ let i = i; move|| { test00_start(&tx, i, number_of_messages) diff --git a/src/test/run-pass/task-comm-7.rs b/src/test/run-pass/task-comm-7.rs index 82e8fe0af41..b05e36552a2 100644 --- a/src/test/run-pass/task-comm-7.rs +++ b/src/test/run-pass/task-comm-7.rs @@ -14,7 +14,7 @@ #![allow(dead_assignment)] use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; pub fn main() { test00(); } @@ -31,19 +31,19 @@ fn test00() { let number_of_messages: isize = 10; let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 0, number_of_messages); }); let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 1, number_of_messages); }); let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 2, number_of_messages); }); let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 3, number_of_messages); }); diff --git a/src/test/run-pass/task-comm-9.rs b/src/test/run-pass/task-comm-9.rs index 3e4a75b8e22..758764aa9fd 100644 --- a/src/test/run-pass/task-comm-9.rs +++ b/src/test/run-pass/task-comm-9.rs @@ -10,7 +10,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { test00(); } @@ -26,7 +26,7 @@ fn test00() { let (tx, rx) = channel(); let number_of_messages: isize = 10; - let result = Thread::scoped(move|| { + let result = thread::scoped(move|| { test00_start(&tx, number_of_messages); }); diff --git a/src/test/run-pass/task-life-0.rs b/src/test/run-pass/task-life-0.rs index 7da7a1afb9a..b97f4355b3e 100644 --- a/src/test/run-pass/task-life-0.rs +++ b/src/test/run-pass/task-life-0.rs @@ -12,10 +12,10 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; pub fn main() { - let _t = Thread::spawn(move|| child("Hello".to_string()) ); + let _t = thread::scoped(move|| child("Hello".to_string()) ); } fn child(_s: String) { diff --git a/src/test/run-pass/task-spawn-move-and-copy.rs b/src/test/run-pass/task-spawn-move-and-copy.rs index 637f564f726..aa7b61bf112 100644 --- a/src/test/run-pass/task-spawn-move-and-copy.rs +++ b/src/test/run-pass/task-spawn-move-and-copy.rs @@ -13,7 +13,7 @@ #![allow(unknown_features)] #![feature(box_syntax, std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::channel; pub fn main() { @@ -22,7 +22,7 @@ pub fn main() { let x: Box = box 1; let x_in_parent = &(*x) as *const isize as usize; - let _t = Thread::spawn(move || { + let _t = thread::scoped(move || { let x_in_child = &(*x) as *const isize as usize; tx.send(x_in_child).unwrap(); }); diff --git a/src/test/run-pass/tcp-accept-stress.rs b/src/test/run-pass/tcp-accept-stress.rs index 99d36a179aa..00467e56334 100644 --- a/src/test/run-pass/tcp-accept-stress.rs +++ b/src/test/run-pass/tcp-accept-stress.rs @@ -19,7 +19,7 @@ use std::old_io::{TcpListener, Listener, Acceptor, EndOfFile, TcpStream}; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; static N: usize = 8; static M: usize = 20; @@ -40,7 +40,7 @@ fn test() { let a = a.clone(); let cnt = cnt.clone(); let srv_tx = srv_tx.clone(); - Thread::scoped(move|| { + thread::scoped(move|| { let mut a = a; loop { match a.accept() { @@ -59,7 +59,7 @@ fn test() { let _t = (0..N).map(|_| { let cli_tx = cli_tx.clone(); - Thread::scoped(move|| { + thread::scoped(move|| { for _ in 0..M { let _s = TcpStream::connect(addr).unwrap(); } diff --git a/src/test/run-pass/tcp-connect-timeouts.rs b/src/test/run-pass/tcp-connect-timeouts.rs index a9a16cd72df..64f07a60b35 100644 --- a/src/test/run-pass/tcp-connect-timeouts.rs +++ b/src/test/run-pass/tcp-connect-timeouts.rs @@ -26,7 +26,7 @@ use std::old_io::test::*; use std::old_io; use std::time::Duration; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; #[cfg_attr(target_os = "freebsd", ignore)] fn eventual_timeout() { @@ -34,7 +34,7 @@ fn eventual_timeout() { let (tx1, rx1) = channel(); let (_tx2, rx2) = channel::<()>(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let _l = TcpListener::bind(addr).unwrap().listen(); tx1.send(()).unwrap(); let _ = rx2.recv(); diff --git a/src/test/run-pass/tempfile.rs b/src/test/run-pass/tempfile.rs index 74290518364..49fac24d0b3 100644 --- a/src/test/run-pass/tempfile.rs +++ b/src/test/run-pass/tempfile.rs @@ -24,7 +24,7 @@ use std::old_path::{Path, GenericPath}; use std::old_io::fs::PathExtensions; use std::old_io::{fs, TempDir}; use std::old_io; -use std::os; +use std::env; use std::sync::mpsc::channel; use std::thread; @@ -129,7 +129,7 @@ fn test_rm_tempdir_close() { // to depend on std fn recursive_mkdir_rel() { let path = Path::new("frob"); - let cwd = os::getcwd().unwrap(); + let cwd = Path::new(env::current_dir().unwrap().to_str().unwrap()); println!("recursive_mkdir_rel: Making: {} in cwd {} [{}]", path.display(), cwd.display(), path.exists()); fs::mkdir_recursive(&path, old_io::USER_RWX); @@ -147,7 +147,7 @@ fn recursive_mkdir_dot() { fn recursive_mkdir_rel_2() { let path = Path::new("./frob/baz"); - let cwd = os::getcwd().unwrap(); + let cwd = Path::new(env::current_dir().unwrap().to_str().unwrap()); println!("recursive_mkdir_rel_2: Making: {} in cwd {} [{}]", path.display(), cwd.display(), path.exists()); fs::mkdir_recursive(&path, old_io::USER_RWX); @@ -196,7 +196,7 @@ pub fn dont_double_panic() { fn in_tmpdir(f: F) where F: FnOnce() { let tmpdir = TempDir::new("test").ok().expect("can't make tmpdir"); - assert!(os::change_dir(tmpdir.path()).is_ok()); + assert!(env::set_current_dir(tmpdir.path().as_str().unwrap()).is_ok()); f(); } diff --git a/src/test/run-pass/threads.rs b/src/test/run-pass/threads.rs index 4fc09952904..969a42a6f87 100644 --- a/src/test/run-pass/threads.rs +++ b/src/test/run-pass/threads.rs @@ -10,12 +10,12 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; pub fn main() { let mut i = 10; while i > 0 { - Thread::scoped({let i = i; move|| child(i)}); + thread::scoped({let i = i; move|| child(i)}); i = i - 1; } println!("main thread exiting"); diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs index 2d97633771e..02ea7037056 100644 --- a/src/test/run-pass/trait-bounds-in-arc.rs +++ b/src/test/run-pass/trait-bounds-in-arc.rs @@ -19,7 +19,7 @@ use std::sync::Arc; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; trait Pet { fn name(&self, blk: Box); @@ -83,13 +83,13 @@ pub fn main() { box dogge2 as Box)); let (tx1, rx1) = channel(); let arc1 = arc.clone(); - let _t1 = Thread::spawn(move|| { check_legs(arc1); tx1.send(()); }); + let _t1 = thread::scoped(move|| { check_legs(arc1); tx1.send(()); }); let (tx2, rx2) = channel(); let arc2 = arc.clone(); - let _t2 = Thread::spawn(move|| { check_names(arc2); tx2.send(()); }); + let _t2 = thread::scoped(move|| { check_names(arc2); tx2.send(()); }); let (tx3, rx3) = channel(); let arc3 = arc.clone(); - let _t3 = Thread::spawn(move|| { check_pedigree(arc3); tx3.send(()); }); + let _t3 = thread::scoped(move|| { check_pedigree(arc3); tx3.send(()); }); rx1.recv(); rx2.recv(); rx3.recv(); diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs index 1688482ca37..d81dc3afcd7 100644 --- a/src/test/run-pass/variadic-ffi.rs +++ b/src/test/run-pass/variadic-ffi.rs @@ -14,7 +14,7 @@ extern crate libc; -use std::ffi::{self, CString}; +use std::ffi::{CStr, CString}; use libc::{c_char, c_int}; @@ -25,7 +25,7 @@ extern { unsafe fn check(expected: &str, f: F) where F: FnOnce(*mut c_char) -> T { let mut x = [0 as c_char; 50]; f(&mut x[0] as *mut c_char); - assert_eq!(expected.as_bytes(), ffi::c_str_to_bytes(&x.as_ptr())); + assert_eq!(expected.as_bytes(), CStr::from_ptr(x.as_ptr()).to_bytes()); } pub fn main() { From 94137a37e90f2fc5faf725965b419944e14ad271 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 31 Mar 2015 10:26:25 -0700 Subject: [PATCH 22/46] Test fixes and rebase conflicts, round 1 --- src/libcollections/slice.rs | 2 -- src/libcollections/vec_deque.rs | 2 -- src/libcollectionstest/lib.rs | 1 + src/libcore/intrinsics.rs | 1 - src/libcore/marker.rs | 4 ---- src/libcore/mem.rs | 41 ++++++++++++--------------------- src/librand/lib.rs | 2 +- src/librustc/middle/ty.rs | 1 + src/libstd/old_io/mem.rs | 2 +- src/libstd/old_io/net/ip.rs | 2 +- src/libstd/old_io/process.rs | 2 +- src/libsyntax/feature_gate.rs | 2 +- src/snapshots.txt | 10 ++++++++ 13 files changed, 32 insertions(+), 40 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 929c97dceb2..84613c28d72 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -89,8 +89,6 @@ use core::iter::MultiplicativeIterator; use core::marker::Sized; use core::mem::size_of; use core::mem; -#[cfg(stage0)] -use core::num::wrapping::WrappingOps; use core::ops::FnMut; use core::option::Option::{self, Some, None}; use core::ptr; diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 6083f03477c..09735e585dd 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -25,8 +25,6 @@ use core::default::Default; use core::fmt; use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator}; use core::mem; -#[cfg(stage0)] -use core::num::wrapping::WrappingOps; use core::ops::{Index, IndexMut}; use core::ptr::{self, Unique}; use core::slice; diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index f03a073e274..a6340a3d7f9 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -21,6 +21,7 @@ #![feature(unicode)] #![feature(unsafe_destructor)] #![feature(into_cow)] +#![feature(convert)] #![cfg_attr(test, feature(str_char))] #[macro_use] extern crate log; diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 43cf64bf3ad..0e91eafce18 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -197,7 +197,6 @@ extern "rust-intrinsic" { /// Rust moves to non-zeroing dynamic drop (and thus removes the /// embedded drop flags that are being established by this /// intrinsic). - #[cfg(not(stage0))] pub fn init_dropped() -> T; /// Create a value initialized to zero. diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 3f4b39da4b3..277b98f0523 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -487,9 +487,5 @@ pub struct InvariantType; pub trait Reflect : MarkerTrait { } -#[cfg(stage0)] -impl Reflect for T { } - -#[cfg(not(stage0))] impl Reflect for .. { } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 98e8668239b..249beb6295c 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -173,11 +173,6 @@ pub unsafe fn zeroed() -> T { #[inline] #[unstable(feature = "filling_drop")] pub unsafe fn dropped() -> T { - #[cfg(stage0)] - #[inline(always)] - unsafe fn dropped_impl() -> T { zeroed() } - - #[cfg(not(stage0))] #[inline(always)] unsafe fn dropped_impl() -> T { intrinsics::init_dropped() } @@ -337,38 +332,32 @@ macro_rules! repeat_u8_as_u64 { // But having the sign bit set is a pain, so 0x1d is probably better. // // And of course, 0x00 brings back the old world of zero'ing on drop. -#[cfg(not(stage0))] #[unstable(feature = "filling_drop")] +#[unstable(feature = "filling_drop")] pub const POST_DROP_U8: u8 = 0x1d; -#[cfg(not(stage0))] #[unstable(feature = "filling_drop")] +#[unstable(feature = "filling_drop")] pub const POST_DROP_U32: u32 = repeat_u8_as_u32!(POST_DROP_U8); -#[cfg(not(stage0))] #[unstable(feature = "filling_drop")] +#[unstable(feature = "filling_drop")] pub const POST_DROP_U64: u64 = repeat_u8_as_u64!(POST_DROP_U8); #[cfg(target_pointer_width = "32")] -#[cfg(not(stage0))] #[unstable(feature = "filling_drop")] +#[unstable(feature = "filling_drop")] pub const POST_DROP_USIZE: usize = POST_DROP_U32 as usize; #[cfg(target_pointer_width = "64")] -#[cfg(not(stage0))] #[unstable(feature = "filling_drop")] +#[unstable(feature = "filling_drop")] pub const POST_DROP_USIZE: usize = POST_DROP_U64 as usize; -#[cfg(stage0)] #[unstable(feature = "filling_drop")] -pub const POST_DROP_U8: u8 = 0; -#[cfg(stage0)] #[unstable(feature = "filling_drop")] -pub const POST_DROP_U32: u32 = 0; -#[cfg(stage0)] #[unstable(feature = "filling_drop")] -pub const POST_DROP_U64: u64 = 0; -#[cfg(stage0)] #[unstable(feature = "filling_drop")] -pub const POST_DROP_USIZE: usize = 0; - -/// Interprets `src` as `&U`, and then reads `src` without moving the contained value. +/// Interprets `src` as `&U`, and then reads `src` without moving the contained +/// value. /// -/// This function will unsafely assume the pointer `src` is valid for `sizeof(U)` bytes by -/// transmuting `&T` to `&U` and then reading the `&U`. It will also unsafely create a copy of the -/// contained value instead of moving out of `src`. +/// This function will unsafely assume the pointer `src` is valid for +/// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It +/// will also unsafely create a copy of the contained value instead of moving +/// out of `src`. /// -/// It is not a compile-time error if `T` and `U` have different sizes, but it is highly encouraged -/// to only invoke this function where `T` and `U` have the same size. This function triggers -/// undefined behavior if `U` is larger than `T`. +/// It is not a compile-time error if `T` and `U` have different sizes, but it +/// is highly encouraged to only invoke this function where `T` and `U` have the +/// same size. This function triggers undefined behavior if `U` is larger than +/// `T`. /// /// # Examples /// diff --git a/src/librand/lib.rs b/src/librand/lib.rs index d859f1c109e..15d3d981eb5 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -154,7 +154,7 @@ pub trait Rng : Sized { /// /// let mut v = [0; 13579]; /// thread_rng().fill_bytes(&mut v); - /// println!("{:?}", v); + /// println!("{:?}", &v[..]); /// ``` fn fill_bytes(&mut self, dest: &mut [u8]) { // this could, in theory, be done by transmuting dest to a diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 161fae11ea6..1090ba984ee 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -73,6 +73,7 @@ use std::cmp; use std::fmt; use std::hash::{Hash, SipHasher, Hasher}; use std::mem; +use std::num::ToPrimitive; use std::ops; use std::rc::Rc; use std::vec::IntoIter; diff --git a/src/libstd/old_io/mem.rs b/src/libstd/old_io/mem.rs index 7d491c8e8fe..c28ad651f80 100644 --- a/src/libstd/old_io/mem.rs +++ b/src/libstd/old_io/mem.rs @@ -744,7 +744,7 @@ mod test { wr.write(&[5; 10]).unwrap(); } } - assert_eq!(buf.as_ref(), [5; 100].as_ref()); + assert_eq!(&buf[..], &[5; 100][..]); }); } diff --git a/src/libstd/old_io/net/ip.rs b/src/libstd/old_io/net/ip.rs index d405bde19cb..099fe657f26 100644 --- a/src/libstd/old_io/net/ip.rs +++ b/src/libstd/old_io/net/ip.rs @@ -414,7 +414,7 @@ pub struct ParseError; /// Some examples: /// /// ```rust,no_run -/// # #![feature(old_io, core)] +/// # #![feature(old_io, core, convert)] /// # #![allow(unused_must_use)] /// /// use std::old_io::{TcpStream, TcpListener}; diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index a2129fcde58..84d8fa31ba8 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -367,7 +367,7 @@ impl Command { /// # Examples /// /// ``` - /// # #![feature(old_io, core)] + /// # #![feature(old_io, core, convert)] /// use std::old_io::Command; /// /// let output = match Command::new("cat").arg("foot.txt").output() { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 1b03a180720..98ffc054394 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -92,7 +92,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ ("main", "1.0.0", Active), // Deprecate after snapshot - // SNAP a923278 + // SNAP 5520801 ("unsafe_destructor", "1.0.0", Active), // A temporary feature gate used to enable parser extensions needed diff --git a/src/snapshots.txt b/src/snapshots.txt index 8b05f7c8955..74d8b222c54 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,13 @@ +S 2015-03-27 5520801 + bitrig-x86_64 41de2c7a69a1ac648d3fa3b65e96a29bdc122163 + freebsd-x86_64 0910bbad35e213f679d0433884fd51398eb3bc8d + linux-i386 1ef82402ed16f5a6d2f87a9a62eaa83170e249ec + linux-x86_64 ef2154372e97a3cb687897d027fd51c8f2c5f349 + macos-i386 0310b1a970f2da7e61770fd14dbbbdca3b518234 + macos-x86_64 5f35d9c920b8083a7420ef8cf5b00d5ef3085dfa + winnt-i386 808b7961f85872f04ec15ad0d3e9e23ae9bc0c3b + winnt-x86_64 903a99a58f57a9bd9848cc68a2445dda881f1ee8 + S 2015-03-25 a923278 bitrig-x86_64 41de2c7a69a1ac648d3fa3b65e96a29bdc122163 freebsd-x86_64 cd02c86a9218da73b2a45aff293787010d33bf3e From 30532884f83c4346f736dee5df03e812bde94ddc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 31 Mar 2015 11:41:18 -0700 Subject: [PATCH 23/46] Test fixes and rebase conflicts, round 2 --- src/libcollections/borrow.rs | 2 +- src/libcore/convert.rs | 7 -- src/libcore/iter.rs | 122 +++++++++++++++++------------- src/libcore/num/mod.rs | 2 +- src/librustc/lib.rs | 1 - src/librustc_driver/lib.rs | 1 - src/librustc_llvm/lib.rs | 1 - src/librustdoc/flock.rs | 4 +- src/librustdoc/lib.rs | 1 - src/libstd/ffi/c_str.rs | 2 +- src/libstd/old_io/test.rs | 8 +- src/libstd/rand/os.rs | 1 - src/libstd/sys/windows/fs.rs | 7 -- src/libstd/sys/windows/process.rs | 1 - src/libsyntax/feature_gate.rs | 11 --- 15 files changed, 80 insertions(+), 91 deletions(-) diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index ab69e1c86ca..2fe769b73f5 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -213,7 +213,7 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { /// /// let hello = cow.to_mut(); /// - /// assert_eq!(&[1, 2, 3], hello); + /// assert_eq!(hello, &[1, 2, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_mut(&mut self) -> &mut ::Owned { diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 62ca8c47ab6..4a99f1a756a 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -95,13 +95,6 @@ impl<'a, T: ?Sized, U: ?Sized> AsMut for &'a mut T where T: AsMut { // } // } -// From itself is always itself -impl From for T { - fn from(t: T) -> T { - t - } -} - // From implies Into #[stable(feature = "rust1", since = "1.0.0")] impl Into for T where U: From { diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 6440c654be7..1328b1a3ba9 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -12,25 +12,26 @@ //! //! # The `Iterator` trait //! -//! This module defines Rust's core iteration trait. The `Iterator` trait has one -//! unimplemented method, `next`. All other methods are derived through default -//! methods to perform operations such as `zip`, `chain`, `enumerate`, and `fold`. +//! This module defines Rust's core iteration trait. The `Iterator` trait has +//! one unimplemented method, `next`. All other methods are derived through +//! default methods to perform operations such as `zip`, `chain`, `enumerate`, +//! and `fold`. //! //! The goal of this module is to unify iteration across all containers in Rust. -//! An iterator can be considered as a state machine which is used to track which -//! element will be yielded next. +//! An iterator can be considered as a state machine which is used to track +//! which element will be yielded next. //! -//! There are various extensions also defined in this module to assist with various -//! types of iteration, such as the `DoubleEndedIterator` for iterating in reverse, -//! the `FromIterator` trait for creating a container from an iterator, and much -//! more. +//! There are various extensions also defined in this module to assist with +//! various types of iteration, such as the `DoubleEndedIterator` for iterating +//! in reverse, the `FromIterator` trait for creating a container from an +//! iterator, and much more. //! //! ## Rust's `for` loop //! //! The special syntax used by rust's `for` loop is based around the `Iterator` -//! trait defined in this module. For loops can be viewed as a syntactical expansion -//! into a `loop`, for example, the `for` loop in this example is essentially -//! translated to the `loop` below. +//! trait defined in this module. For loops can be viewed as a syntactical +//! expansion into a `loop`, for example, the `for` loop in this example is +//! essentially translated to the `loop` below. //! //! ``` //! let values = vec![1, 2, 3]; @@ -64,8 +65,8 @@ use cmp::Ord; use default::Default; use marker; use mem; -use num::{Int, Zero, One, ToPrimitive}; -use ops::{Add, Sub, FnMut, RangeFrom}; +use num::{Int, Zero, One}; +use ops::{self, Add, Sub, FnMut, RangeFrom}; use option::Option::{self, Some, None}; use marker::Sized; use usize; @@ -84,21 +85,22 @@ fn _assert_is_object_safe(_: &Iterator) {} /// else. #[lang="iterator"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling `.iter()` or a similar \ - method"] +#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \ + `.iter()` or a similar method"] pub trait Iterator { /// The type of the elements being iterated #[stable(feature = "rust1", since = "1.0.0")] type Item; - /// Advance the iterator and return the next value. Return `None` when the end is reached. + /// Advance the iterator and return the next value. Return `None` when the + /// end is reached. #[stable(feature = "rust1", since = "1.0.0")] fn next(&mut self) -> Option; /// Returns a lower and upper bound on the remaining length of the iterator. /// - /// An upper bound of `None` means either there is no known upper bound, or the upper bound - /// does not fit within a `usize`. + /// An upper bound of `None` means either there is no known upper bound, or + /// the upper bound does not fit within a `usize`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn size_hint(&self) -> (usize, Option) { (0, None) } @@ -274,7 +276,8 @@ pub trait Iterator { /// iterator plus the current index of iteration. /// /// `enumerate` keeps its count as a `usize`. If you want to count by a - /// different sized integer, the `zip` function provides similar functionality. + /// different sized integer, the `zip` function provides similar + /// functionality. /// /// # Examples /// @@ -612,7 +615,8 @@ pub trait Iterator { true } - /// Tests whether any element of an iterator satisfies the specified predicate. + /// Tests whether any element of an iterator satisfies the specified + /// predicate. /// /// Does not consume the iterator past the first found element. /// @@ -776,7 +780,8 @@ pub trait Iterator { /// element in the iterator and all elements are equal. /// /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons, - /// and so is faster than calling `min` and `max` separately which does `2 * n` comparisons. + /// and so is faster than calling `min` and `max` separately which does `2 * + /// n` comparisons. /// /// # Examples /// @@ -810,10 +815,11 @@ pub trait Iterator { }; loop { - // `first` and `second` are the two next elements we want to look at. - // We first compare `first` and `second` (#1). The smaller one is then compared to - // current minimum (#2). The larger one is compared to current maximum (#3). This - // way we do 3 comparisons for 2 elements. + // `first` and `second` are the two next elements we want to look + // at. We first compare `first` and `second` (#1). The smaller one + // is then compared to current minimum (#2). The larger one is + // compared to current maximum (#3). This way we do 3 comparisons + // for 2 elements. let first = match self.next() { None => break, Some(x) => x @@ -1038,7 +1044,8 @@ pub trait FromIterator { /// assert_eq!(colors_set.len(), 3); /// ``` /// - /// `FromIterator` is more commonly used implicitly via the `Iterator::collect` method: + /// `FromIterator` is more commonly used implicitly via the + /// `Iterator::collect` method: /// /// ``` /// use std::collections::HashSet; @@ -1105,12 +1112,13 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { /// An object implementing random access indexing by `usize` /// -/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`. -/// Calling `next()` or `next_back()` on a `RandomAccessIterator` -/// reduces the indexable range accordingly. That is, `it.idx(1)` will become `it.idx(0)` -/// after `it.next()` is called. +/// A `RandomAccessIterator` should be either infinite or a +/// `DoubleEndedIterator`. Calling `next()` or `next_back()` on a +/// `RandomAccessIterator` reduces the indexable range accordingly. That is, +/// `it.idx(1)` will become `it.idx(0)` after `it.next()` is called. #[unstable(feature = "core", - reason = "not widely used, may be better decomposed into Index and ExactSizeIterator")] + reason = "not widely used, may be better decomposed into Index \ + and ExactSizeIterator")] pub trait RandomAccessIterator: Iterator { /// Return the number of indexable elements. At most `std::usize::MAX` /// elements are indexable, even if the iterator represents a longer range. @@ -1155,13 +1163,15 @@ impl ExactSizeIterator for Inspect where F: FnMut(&I::Item), {} #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Rev where I: ExactSizeIterator + DoubleEndedIterator {} +impl ExactSizeIterator for Rev + where I: ExactSizeIterator + DoubleEndedIterator {} #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Map where F: FnMut(I::Item) -> B, {} #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Zip where A: ExactSizeIterator, B: ExactSizeIterator {} +impl ExactSizeIterator for Zip + where A: ExactSizeIterator, B: ExactSizeIterator {} /// An double-ended iterator with the direction inverted #[derive(Clone)] @@ -1188,7 +1198,9 @@ impl DoubleEndedIterator for Rev where I: DoubleEndedIterator { } #[unstable(feature = "core", reason = "trait is experimental")] -impl RandomAccessIterator for Rev where I: DoubleEndedIterator + RandomAccessIterator { +impl RandomAccessIterator for Rev + where I: DoubleEndedIterator + RandomAccessIterator +{ #[inline] fn indexable(&self) -> usize { self.iter.indexable() } #[inline] @@ -1291,7 +1303,8 @@ impl_multiplicative! { usize, 1 } impl_multiplicative! { f32, 1.0 } impl_multiplicative! { f64, 1.0 } -/// `MinMaxResult` is an enum returned by `min_max`. See `Iterator::min_max` for more detail. +/// `MinMaxResult` is an enum returned by `min_max`. See `Iterator::min_max` for +/// more detail. #[derive(Clone, PartialEq, Debug)] #[unstable(feature = "core", reason = "unclear whether such a fine-grained result is widely useful")] @@ -1302,15 +1315,17 @@ pub enum MinMaxResult { /// Iterator with one element, so the minimum and maximum are the same OneElement(T), - /// More than one element in the iterator, the first element is not larger than the second + /// More than one element in the iterator, the first element is not larger + /// than the second MinMax(T, T) } impl MinMaxResult { - /// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` has variant - /// `None` if and only if the `MinMaxResult` has variant `NoElements`. Otherwise variant - /// `Some(x,y)` is returned where `x <= y`. If `MinMaxResult` has variant `OneElement(x)`, - /// performing this operation will make one clone of `x`. + /// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` + /// has variant `None` if and only if the `MinMaxResult` has variant + /// `NoElements`. Otherwise variant `Some(x,y)` is returned where `x <= y`. + /// If `MinMaxResult` has variant `OneElement(x)`, performing this operation + /// will make one clone of `x`. /// /// # Examples /// @@ -2522,7 +2537,7 @@ impl RangeFrom { } #[allow(deprecated)] -impl ::ops::Range { +impl ops::Range { /// Creates an iterator with the same range, but stepping by the /// given amount at each iteration. /// @@ -2588,7 +2603,9 @@ pub struct RangeInclusive { #[inline] #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -pub fn range_inclusive(start: A, stop: A) -> RangeInclusive { +pub fn range_inclusive(start: A, stop: A) -> RangeInclusive + where A: Step + One + Clone +{ RangeInclusive { range: start..stop, done: false, @@ -2597,7 +2614,7 @@ pub fn range_inclusive(start: A, stop: A) -> RangeInclusive { #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -impl Iterator for RangeInclusive { +impl Iterator for RangeInclusive { type Item = A; #[inline] @@ -2633,12 +2650,15 @@ impl Iterator for RangeInclusive { #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -impl DoubleEndedIterator for RangeInclusive { +impl DoubleEndedIterator for RangeInclusive + where A: Step + One + Clone, + for<'a> &'a A: Sub +{ #[inline] fn next_back(&mut self) -> Option { if self.range.end > self.range.start { let result = self.range.end.clone(); - self.range.end = self.range.end - A::one(); + self.range.end = &self.range.end - &A::one(); Some(result) } else if !self.done && self.range.start == self.range.end { self.done = true; @@ -2651,7 +2671,7 @@ impl DoubleEndedIterator for RangeInclusive { #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] -impl Iterator for StepBy> { +impl Iterator for StepBy> { type Item = A; #[inline] @@ -2754,13 +2774,13 @@ impl Iterator for RangeStepInclusive { macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl ExactSizeIterator for ::ops::Range<$t> { } + impl ExactSizeIterator for ops::Range<$t> { } )*) } #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] -impl Iterator for ::ops::Range { +impl Iterator for ops::Range { type Item = A; #[inline] @@ -2799,7 +2819,7 @@ range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32); #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] -impl DoubleEndedIterator for ::ops::Range where +impl DoubleEndedIterator for ops::Range where for<'a> &'a A: Sub<&'a A, Output = A> { #[inline] @@ -2815,7 +2835,7 @@ impl DoubleEndedIterator for ::ops::Range where #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] -impl Iterator for ::ops::RangeFrom { +impl Iterator for ops::RangeFrom { type Item = A; #[inline] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 64f8e7055a5..a4829ed96b3 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -46,7 +46,7 @@ use str::{FromStr, StrExt}; /// intended to have wrapping semantics. #[stable(feature = "rust1", since = "1.0.0")] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] -pub struct Wrapping(pub T); +pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] pub T); #[unstable(feature = "core", reason = "may be removed or relocated")] pub mod wrapping; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 6215f823142..b3ad96c4b5f 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -37,7 +37,6 @@ #![feature(unsafe_destructor)] #![feature(staged_api)] #![feature(std_misc)] -#![feature(io)] #![feature(path_ext)] #![feature(str_words)] #![feature(str_char)] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 112f1502643..450c8eb66c8 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -27,7 +27,6 @@ #![feature(box_syntax)] #![feature(collections)] -#![feature(core)] #![feature(libc)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index cba2188ef79..550959fb2b3 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -30,7 +30,6 @@ #![feature(libc)] #![feature(link_args)] #![feature(staged_api)] -#![cfg_attr(unix, feature(convert))] extern crate libc; #[macro_use] #[no_link] extern crate rustc_bitflags; diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index f8c56b68577..760fa329fd9 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -195,8 +195,8 @@ mod imp { impl Lock { pub fn new(p: &Path) -> Lock { - let p: &OsStr = p.as_ref(); - let mut p_16: Vec<_> = p.encode_wide().collect(); + let os: &OsStr = p.as_ref(); + let mut p_16: Vec<_> = os.encode_wide().collect(); p_16.push(0); let handle = unsafe { libc::CreateFileW(p_16.as_ptr(), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 98598509cbc..1ff3411f8fc 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -23,7 +23,6 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(collections)] -#![feature(core)] #![feature(exit_status)] #![feature(set_stdio)] #![feature(libc)] diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 3322b2c52bf..42ea50bff77 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -10,7 +10,7 @@ #![unstable(feature = "std_misc")] -use convert::Into; +use convert::{Into, From}; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; use error::Error; use fmt; diff --git a/src/libstd/old_io/test.rs b/src/libstd/old_io/test.rs index 8c46e2c06b8..312e1c814dc 100644 --- a/src/libstd/old_io/test.rs +++ b/src/libstd/old_io/test.rs @@ -141,7 +141,7 @@ mod darwin_fd_limit { // sysctl value, and bump the soft resource limit for maxfiles up to the sysctl value. use ptr::null_mut; use mem::size_of_val; - use os::last_os_error; + use io; // Fetch the kern.maxfilesperproc value let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC]; @@ -149,14 +149,14 @@ mod darwin_fd_limit { let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t; if sysctl(&mut mib[0], 2, &mut maxfiles as *mut libc::c_int as *mut libc::c_void, &mut size, null_mut(), 0) != 0 { - let err = last_os_error(); + let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling sysctl: {}", err); } // Fetch the current resource limits let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0}; if getrlimit(RLIMIT_NOFILE, &mut rlim) != 0 { - let err = last_os_error(); + let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling getrlimit: {}", err); } @@ -165,7 +165,7 @@ mod darwin_fd_limit { // Set our newly-increased resource limit if setrlimit(RLIMIT_NOFILE, &rlim) != 0 { - let err = last_os_error(); + let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling setrlimit: {}", err); } } diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 0a619ff8cd0..7aba40dc6be 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -254,7 +254,6 @@ mod imp { use io; use mem; use old_io::{IoResult, IoError}; - use os; use rand::Rng; use libc::types::os::arch::extra::{LONG_PTR}; use libc::{DWORD, BYTE, LPCSTR, BOOL}; diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 3330130c770..f534a33d8cc 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -135,13 +135,6 @@ impl FileDesc { _ => Err(super::last_error()), } } - - /// Extract the actual filedescriptor without closing it. - pub fn unwrap(self) -> fd_t { - let fd = self.fd; - unsafe { mem::forget(self) }; - fd - } } impl Drop for FileDesc { diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 2065df4fbe3..414083bc41f 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -24,7 +24,6 @@ use old_io::process::{ProcessExit, ExitStatus}; use old_io::{IoResult, IoError}; use old_io; use fs::PathExt; -use os; use old_path::{BytesContainer, GenericPath}; use ptr; use str; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 98ffc054394..4a977fe02c4 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -161,10 +161,6 @@ enum Status { /// currently being considered for addition/removal. Active, - /// Represents a feature gate that is temporarily enabling deprecated behavior. - /// This gate will never be accepted. - Deprecated, - /// Represents a feature which has since been removed (it was once Active) Removed, @@ -699,13 +695,6 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, Some(&(name, _, Active)) => { cx.features.push(name); } - Some(&(name, _, Deprecated)) => { - cx.features.push(name); - span_handler.span_warn( - mi.span, - "feature is deprecated and will only be available \ - for a limited time, please rewrite code that relies on it"); - } Some(&(_, _, Removed)) => { span_handler.span_err(mi.span, "feature has been removed"); } From 8da08317a6e5bce60b833c279564728c68938973 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 31 Mar 2015 19:02:32 -0400 Subject: [PATCH 24/46] Move benchmark tests to unstable section Fixes #23881 --- src/doc/trpl/SUMMARY.md | 1 + src/doc/trpl/benchmark-tests.md | 152 ++++++++++++++++++++++++++++++++ src/doc/trpl/testing.md | 146 ------------------------------ 3 files changed, 153 insertions(+), 146 deletions(-) create mode 100644 src/doc/trpl/benchmark-tests.md diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index d31348d667b..136e155b1af 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -42,5 +42,6 @@ * [Intrinsics](intrinsics.md) * [Lang items](lang-items.md) * [Link args](link-args.md) + * [Benchmark Tests](benchmark-tests.md) * [Conclusion](conclusion.md) * [Glossary](glossary.md) diff --git a/src/doc/trpl/benchmark-tests.md b/src/doc/trpl/benchmark-tests.md new file mode 100644 index 00000000000..88796537593 --- /dev/null +++ b/src/doc/trpl/benchmark-tests.md @@ -0,0 +1,152 @@ +% Benchmark tests + +Rust supports benchmark tests, which can test the performance of your +code. Let's make our `src/lib.rs` look like this (comments elided): + +```{rust,ignore} +#![feature(test)] + +extern crate test; + +pub fn add_two(a: i32) -> i32 { + a + 2 +} + +#[cfg(test)] +mod tests { + use super::*; + use test::Bencher; + + #[test] + fn it_works() { + assert_eq!(4, add_two(2)); + } + + #[bench] + fn bench_add_two(b: &mut Bencher) { + b.iter(|| add_two(2)); + } +} +``` + +Note the `test` feature gate, which enables this unstable feature. + +We've imported the `test` crate, which contains our benchmarking support. +We have a new function as well, with the `bench` attribute. Unlike regular +tests, which take no arguments, benchmark tests take a `&mut Bencher`. This +`Bencher` provides an `iter` method, which takes a closure. This closure +contains the code we'd like to benchmark. + +We can run benchmark tests with `cargo bench`: + +```bash +$ cargo bench + Compiling adder v0.0.1 (file:///home/steve/tmp/adder) + Running target/release/adder-91b3e234d4ed382a + +running 2 tests +test tests::it_works ... ignored +test tests::bench_add_two ... bench: 1 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured +``` + +Our non-benchmark test was ignored. You may have noticed that `cargo bench` +takes a bit longer than `cargo test`. This is because Rust runs our benchmark +a number of times, and then takes the average. Because we're doing so little +work in this example, we have a `1 ns/iter (+/- 0)`, but this would show +the variance if there was one. + +Advice on writing benchmarks: + + +* Move setup code outside the `iter` loop; only put the part you want to measure inside +* Make the code do "the same thing" on each iteration; do not accumulate or change state +* Make the outer function idempotent too; the benchmark runner is likely to run + it many times +* Make the inner `iter` loop short and fast so benchmark runs are fast and the + calibrator can adjust the run-length at fine resolution +* Make the code in the `iter` loop do something simple, to assist in pinpointing + performance improvements (or regressions) + +## Gotcha: optimizations + +There's another tricky part to writing benchmarks: benchmarks compiled with +optimizations activated can be dramatically changed by the optimizer so that +the benchmark is no longer benchmarking what one expects. For example, the +compiler might recognize that some calculation has no external effects and +remove it entirely. + +```{rust,ignore} +#![feature(test)] + +extern crate test; +use test::Bencher; + +#[bench] +fn bench_xor_1000_ints(b: &mut Bencher) { + b.iter(|| { + (0..1000).fold(0, |old, new| old ^ new); + }); +} +``` + +gives the following results + +```text +running 1 test +test bench_xor_1000_ints ... bench: 0 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured +``` + +The benchmarking runner offers two ways to avoid this. Either, the closure that +the `iter` method receives can return an arbitrary value which forces the +optimizer to consider the result used and ensures it cannot remove the +computation entirely. This could be done for the example above by adjusting the +`b.iter` call to + +```rust +# struct X; +# impl X { fn iter(&self, _: F) where F: FnMut() -> T {} } let b = X; +b.iter(|| { + // note lack of `;` (could also use an explicit `return`). + (0..1000).fold(0, |old, new| old ^ new) +}); +``` + +Or, the other option is to call the generic `test::black_box` function, which +is an opaque "black box" to the optimizer and so forces it to consider any +argument as used. + +```rust +#![feature(test)] + +extern crate test; + +# fn main() { +# struct X; +# impl X { fn iter(&self, _: F) where F: FnMut() -> T {} } let b = X; +b.iter(|| { + let n = test::black_box(1000); + + (0..n).fold(0, |a, b| a ^ b) +}) +# } +``` + +Neither of these read or modify the value, and are very cheap for small values. +Larger values can be passed indirectly to reduce overhead (e.g. +`black_box(&huge_struct)`). + +Performing either of the above changes gives the following benchmarking results + +```text +running 1 test +test bench_xor_1000_ints ... bench: 131 ns/iter (+/- 3) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured +``` + +However, the optimizer can still modify a testcase in an undesirable manner +even when using either of the above. diff --git a/src/doc/trpl/testing.md b/src/doc/trpl/testing.md index 8b2c14526cb..fddb4c19031 100644 --- a/src/doc/trpl/testing.md +++ b/src/doc/trpl/testing.md @@ -430,149 +430,3 @@ documentation tests: the `_0` is generated for the module test, and `add_two_0` for the function test. These will auto increment with names like `add_two_1` as you add more examples. -# Benchmark tests - -Rust also supports benchmark tests, which can test the performance of your -code. Let's make our `src/lib.rs` look like this (comments elided): - -```{rust,ignore} -extern crate test; - -pub fn add_two(a: i32) -> i32 { - a + 2 -} - -#[cfg(test)] -mod tests { - use super::*; - use test::Bencher; - - #[test] - fn it_works() { - assert_eq!(4, add_two(2)); - } - - #[bench] - fn bench_add_two(b: &mut Bencher) { - b.iter(|| add_two(2)); - } -} -``` - -We've imported the `test` crate, which contains our benchmarking support. -We have a new function as well, with the `bench` attribute. Unlike regular -tests, which take no arguments, benchmark tests take a `&mut Bencher`. This -`Bencher` provides an `iter` method, which takes a closure. This closure -contains the code we'd like to benchmark. - -We can run benchmark tests with `cargo bench`: - -```bash -$ cargo bench - Compiling adder v0.0.1 (file:///home/steve/tmp/adder) - Running target/release/adder-91b3e234d4ed382a - -running 2 tests -test tests::it_works ... ignored -test tests::bench_add_two ... bench: 1 ns/iter (+/- 0) - -test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured -``` - -Our non-benchmark test was ignored. You may have noticed that `cargo bench` -takes a bit longer than `cargo test`. This is because Rust runs our benchmark -a number of times, and then takes the average. Because we're doing so little -work in this example, we have a `1 ns/iter (+/- 0)`, but this would show -the variance if there was one. - -Advice on writing benchmarks: - - -* Move setup code outside the `iter` loop; only put the part you want to measure inside -* Make the code do "the same thing" on each iteration; do not accumulate or change state -* Make the outer function idempotent too; the benchmark runner is likely to run - it many times -* Make the inner `iter` loop short and fast so benchmark runs are fast and the - calibrator can adjust the run-length at fine resolution -* Make the code in the `iter` loop do something simple, to assist in pinpointing - performance improvements (or regressions) - -## Gotcha: optimizations - -There's another tricky part to writing benchmarks: benchmarks compiled with -optimizations activated can be dramatically changed by the optimizer so that -the benchmark is no longer benchmarking what one expects. For example, the -compiler might recognize that some calculation has no external effects and -remove it entirely. - -```{rust,ignore} -extern crate test; -use test::Bencher; - -#[bench] -fn bench_xor_1000_ints(b: &mut Bencher) { - b.iter(|| { - (0..1000).fold(0, |old, new| old ^ new); - }); -} -``` - -gives the following results - -```text -running 1 test -test bench_xor_1000_ints ... bench: 0 ns/iter (+/- 0) - -test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured -``` - -The benchmarking runner offers two ways to avoid this. Either, the closure that -the `iter` method receives can return an arbitrary value which forces the -optimizer to consider the result used and ensures it cannot remove the -computation entirely. This could be done for the example above by adjusting the -`b.iter` call to - -```rust -# struct X; -# impl X { fn iter(&self, _: F) where F: FnMut() -> T {} } let b = X; -b.iter(|| { - // note lack of `;` (could also use an explicit `return`). - (0..1000).fold(0, |old, new| old ^ new) -}); -``` - -Or, the other option is to call the generic `test::black_box` function, which -is an opaque "black box" to the optimizer and so forces it to consider any -argument as used. - -```rust -# #![feature(test)] - -extern crate test; - -# fn main() { -# struct X; -# impl X { fn iter(&self, _: F) where F: FnMut() -> T {} } let b = X; -b.iter(|| { - let n = test::black_box(1000); - - (0..n).fold(0, |a, b| a ^ b) -}) -# } -``` - -Neither of these read or modify the value, and are very cheap for small values. -Larger values can be passed indirectly to reduce overhead (e.g. -`black_box(&huge_struct)`). - -Performing either of the above changes gives the following benchmarking results - -```text -running 1 test -test bench_xor_1000_ints ... bench: 131 ns/iter (+/- 3) - -test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured -``` - -However, the optimizer can still modify a testcase in an undesirable manner -even when using either of the above. From ac77392f8ab1c201b0c927f6a2d30b632b95acda Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 31 Mar 2015 16:01:03 -0700 Subject: [PATCH 25/46] std: Stabilize last bits of io::Error This commit stabilizes a few remaining bits of the `io::Error` type: * The `Error::new` method is now stable. The last `detail` parameter was removed and the second `desc` parameter was generalized to `E: Into>` to allow creating an I/O error from any form of error. Currently there is no form of downcasting, but this will be added in time. * An implementation of `From<&str> for Box` was added to liballoc to allow construction of errors from raw strings. * The `Error::raw_os_error` method was stabilized as-is. * Trait impls for `Clone`, `Eq`, and `PartialEq` were removed from `Error` as it is not possible to use them with trait objects. This is a breaking change due to the modification of the `new` method as well as the removal of the trait implementations for the `Error` type. [breaking-change] --- src/liballoc/boxed.rs | 46 ++++++++++- src/liballoc/lib.rs | 1 + src/librbml/lib.rs | 14 ++-- src/librustc_back/fs.rs | 4 +- src/librustc_back/lib.rs | 1 - src/librustc_back/target/apple_ios_base.rs | 5 +- src/librustc_back/tempdir.rs | 3 +- src/librustc_driver/lib.rs | 1 - src/librustc_driver/pretty.rs | 4 +- src/libstd/ffi/c_str.rs | 2 +- src/libstd/fs/mod.rs | 3 +- src/libstd/fs/tempdir.rs | 3 +- src/libstd/io/buffered.rs | 2 +- src/libstd/io/cursor.rs | 3 +- src/libstd/io/error.rs | 89 +++++++++------------- src/libstd/io/impls.rs | 2 +- src/libstd/io/mod.rs | 7 +- src/libstd/net/addr.rs | 2 +- src/libstd/net/mod.rs | 2 +- src/libstd/net/udp.rs | 2 +- src/libstd/process.rs | 1 - src/libstd/sys/common/net2.rs | 5 +- src/libstd/sys/unix/net.rs | 3 +- 23 files changed, 109 insertions(+), 96 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index f9bd0ab2f1e..37315b2e72f 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -56,8 +56,10 @@ use core::fmt; use core::hash::{self, Hash}; use core::mem; use core::ops::{Deref, DerefMut}; -use core::ptr::Unique; -use core::raw::TraitObject; +use core::ptr::{self, Unique}; +use core::raw::{TraitObject, Slice}; + +use heap; /// A value that represents the heap. This is the default place that the `box` /// keyword allocates into when no place is supplied. @@ -327,3 +329,43 @@ impl<'a, E: Error + 'a> FromError for Box { Box::new(err) } } + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + Send + 'a> From for Box { + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b> From<&'b str> for Box { + fn from(err: &'b str) -> Box { + #[derive(Debug)] + struct StringError(Box); + impl Error for StringError { + fn description(&self) -> &str { &self.0 } + } + impl fmt::Display for StringError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } + } + + // Unfortunately `String` is located in libcollections, so we construct + // a `Box` manually here. + unsafe { + let alloc = if err.len() == 0 { + 0 as *mut u8 + } else { + let ptr = heap::allocate(err.len(), 1); + if ptr.is_null() { ::oom(); } + ptr as *mut u8 + }; + ptr::copy(err.as_bytes().as_ptr(), alloc, err.len()); + Box::new(StringError(mem::transmute(Slice { + data: alloc, + len: err.len(), + }))) + } + } +} diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index b92dfa9117e..a880ba5cfe4 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -78,6 +78,7 @@ #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(core)] #![feature(unique)] +#![feature(convert)] #![cfg_attr(test, feature(test, alloc, rustc_private))] #![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")), feature(libc))] diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 092cd780ec7..878ef04942a 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -862,8 +862,8 @@ pub mod writer { } else if 0x100 <= n && n < NUM_TAGS { w.write_all(&[0xf0 | (n >> 8) as u8, n as u8]) } else { - Err(io::Error::new(io::ErrorKind::Other, "invalid tag", - Some(n.to_string()))) + Err(io::Error::new(io::ErrorKind::Other, + &format!("invalid tag: {}", n)[..])) } } @@ -876,7 +876,7 @@ pub mod writer { 4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8, (n >> 8) as u8, n as u8]), _ => Err(io::Error::new(io::ErrorKind::Other, - "isize too big", Some(n.to_string()))) + &format!("isize too big: {}", n)[..])) } } @@ -885,8 +885,8 @@ pub mod writer { if n < 0x4000 { return write_sized_vuint(w, n, 2); } if n < 0x200000 { return write_sized_vuint(w, n, 3); } if n < 0x10000000 { return write_sized_vuint(w, n, 4); } - Err(io::Error::new(io::ErrorKind::Other, "isize too big", - Some(n.to_string()))) + Err(io::Error::new(io::ErrorKind::Other, + &format!("isize too big: {}", n)[..])) } impl<'a> Encoder<'a> { @@ -1077,8 +1077,8 @@ pub mod writer { self.wr_tagged_raw_u32(EsSub32 as usize, v) } else { Err(io::Error::new(io::ErrorKind::Other, - "length or variant id too big", - Some(v.to_string()))) + &format!("length or variant id too big: {}", + v)[..])) } } diff --git a/src/librustc_back/fs.rs b/src/librustc_back/fs.rs index 6d8891dd4fe..214cec4e292 100644 --- a/src/librustc_back/fs.rs +++ b/src/librustc_back/fs.rs @@ -20,9 +20,7 @@ pub fn realpath(original: &Path) -> io::Result { let old = old_path::Path::new(original.to_str().unwrap()); match old_realpath(&old) { Ok(p) => Ok(PathBuf::from(p.as_str().unwrap())), - Err(e) => Err(io::Error::new(io::ErrorKind::Other, - "realpath error", - Some(e.to_string()))) + Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)) } } diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index fe457841e91..6a5a5201c10 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -36,7 +36,6 @@ #![feature(collections)] #![feature(core)] #![feature(old_fs)] -#![feature(io)] #![feature(old_io)] #![feature(old_path)] #![feature(os)] diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs index 2fbbe7d1f7c..42cbdd7577d 100644 --- a/src/librustc_back/target/apple_ios_base.rs +++ b/src/librustc_back/target/apple_ios_base.rs @@ -47,9 +47,10 @@ pub fn get_sdk_root(sdk_name: &str) -> String { Ok(String::from_utf8(output.stdout).unwrap()) } else { let error = String::from_utf8(output.stderr); + let error = format!("process exit with error: {}", + error.unwrap()); Err(io::Error::new(io::ErrorKind::Other, - "process exit with error", - error.ok())) + &error[..])) } }); diff --git a/src/librustc_back/tempdir.rs b/src/librustc_back/tempdir.rs index d4503ae7fc9..3bf9827411a 100644 --- a/src/librustc_back/tempdir.rs +++ b/src/librustc_back/tempdir.rs @@ -67,8 +67,7 @@ impl TempDir { } Err(Error::new(ErrorKind::AlreadyExists, - "too many temporary directories already exist", - None)) + "too many temporary directories already exist")) } /// Attempts to make a temporary directory inside of `env::temp_dir()` whose diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 456d5f7a60a..f087a2c742b 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -35,7 +35,6 @@ #![feature(unsafe_destructor)] #![feature(staged_api)] #![feature(exit_status)] -#![feature(io)] #![feature(set_stdio)] #![feature(unicode)] #![feature(convert)] diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 9e693a64ef0..fe55ca3b73b 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -699,8 +699,8 @@ fn print_flowgraph(variants: Vec, fn expand_err_details(r: io::Result<()>) -> io::Result<()> { r.map_err(|ioerr| { - io::Error::new(io::ErrorKind::Other, "graphviz::render failed", - Some(ioerr.to_string())) + io::Error::new(io::ErrorKind::Other, + &format!("graphviz::render failed: {}", ioerr)[..]) }) } } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index a00f7708025..622e6b54f5e 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -301,7 +301,7 @@ impl fmt::Display for NulError { impl FromError for io::Error { fn from_error(_: NulError) -> io::Error { io::Error::new(io::ErrorKind::InvalidInput, - "data provided contains a nul byte", None) + "data provided contains a nul byte") } } diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs index a3128ef0f8d..a5186ad9a98 100644 --- a/src/libstd/fs/mod.rs +++ b/src/libstd/fs/mod.rs @@ -575,8 +575,7 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { let to = to.as_ref(); if !from.is_file() { return Err(Error::new(ErrorKind::InvalidInput, - "the source path is not an existing file", - None)) + "the source path is not an existing file")) } let mut reader = try!(File::open(from)); diff --git a/src/libstd/fs/tempdir.rs b/src/libstd/fs/tempdir.rs index 8cc1dde98a0..24f285e424e 100644 --- a/src/libstd/fs/tempdir.rs +++ b/src/libstd/fs/tempdir.rs @@ -73,8 +73,7 @@ impl TempDir { } Err(Error::new(ErrorKind::AlreadyExists, - "too many temporary directories already exist", - None)) + "too many temporary directories already exist")) } /// Attempts to make a temporary directory inside of `env::temp_dir()` whose diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 8eea06bf6b0..9abc30b7da8 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -165,7 +165,7 @@ impl BufWriter { match self.inner.as_mut().unwrap().write(&self.buf[written..]) { Ok(0) => { ret = Err(Error::new(ErrorKind::WriteZero, - "failed to write the buffered data", None)); + "failed to write the buffered data")); break; } Ok(n) => written += n, diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index d8e403376bd..87bd8540931 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -75,8 +75,7 @@ macro_rules! seek { if pos < 0 { Err(Error::new(ErrorKind::InvalidInput, - "invalid seek to a negative position", - None)) + "invalid seek to a negative position")) } else { self.pos = pos as u64; Ok(self.pos) diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index f445ace081e..b84dcb8fb62 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -9,12 +9,12 @@ // except according to those terms. use boxed::Box; -use clone::Clone; +use convert::Into; use error; use fmt; +use marker::Send; use option::Option::{self, Some, None}; use result; -use string::String; use sys; /// A type for results generated by I/O related functions where the `Err` type @@ -31,23 +31,22 @@ pub type Result = result::Result; /// Errors mostly originate from the underlying OS, but custom instances of /// `Error` can be created with crafted error messages and a particular value of /// `ErrorKind`. -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Error { repr: Repr, } -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] enum Repr { Os(i32), Custom(Box), } -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] struct Custom { kind: ErrorKind, - desc: &'static str, - detail: Option + error: Box, } /// A list specifying general categories of I/O error. @@ -125,18 +124,34 @@ pub enum ErrorKind { } impl Error { - /// Creates a new custom error from a specified kind/description/detail. - #[unstable(feature = "io", reason = "the exact makeup of an Error may - change to include `Box` for \ - example")] - pub fn new(kind: ErrorKind, - description: &'static str, - detail: Option) -> Error { + /// Creates a new I/O error from a known kind of error as well as an + /// arbitrary error payload. + /// + /// This function is used to generically create I/O errors which do not + /// originate from the OS itself. The `error` argument is an arbitrary + /// payload which will be contained in this `Error`. Accessors as well as + /// downcasting will soon be added to this type as well to access the custom + /// information. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// // errors can be created from strings + /// let custom_error = Error::new(ErrorKind::Other, "oh no!"); + /// + /// // errors can also be created from other errors + /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(kind: ErrorKind, error: E) -> Error + where E: Into> + { Error { repr: Repr::Custom(Box::new(Custom { kind: kind, - desc: description, - detail: detail, + error: error.into(), })) } } @@ -162,8 +177,7 @@ impl Error { /// /// If this `Error` was constructed via `last_os_error` then this function /// will return `Some`, otherwise it will return `None`. - #[unstable(feature = "io", reason = "function was just added and the return \ - type may become an abstract OS error")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn raw_os_error(&self) -> Option { match self.repr { Repr::Os(i) => Some(i), @@ -179,27 +193,6 @@ impl Error { Repr::Custom(ref c) => c.kind, } } - - /// Returns a short description for this error message - #[unstable(feature = "io")] - #[deprecated(since = "1.0.0", reason = "use the Error trait's description \ - method instead")] - pub fn description(&self) -> &str { - match self.repr { - Repr::Os(..) => "os error", - Repr::Custom(ref c) => c.desc, - } - } - - /// Returns a detailed error message for this error (if one is available) - #[unstable(feature = "io")] - #[deprecated(since = "1.0.0", reason = "use the to_string() method instead")] - pub fn detail(&self) -> Option { - match self.repr { - Repr::Os(code) => Some(sys::os::error_string(code)), - Repr::Custom(ref s) => s.detail.clone(), - } - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -210,21 +203,7 @@ impl fmt::Display for Error { let detail = sys::os::error_string(code); write!(fmt, "{} (os error {})", detail, code) } - Repr::Custom(ref c) => { - match **c { - Custom { - kind: ErrorKind::Other, - desc: "unknown error", - detail: Some(ref detail) - } => { - write!(fmt, "{}", detail) - } - Custom { detail: None, desc, .. } => - write!(fmt, "{}", desc), - Custom { detail: Some(ref detail), desc, .. } => - write!(fmt, "{} ({})", desc, detail) - } - } + Repr::Custom(ref c) => c.error.fmt(fmt), } } } @@ -234,7 +213,7 @@ impl error::Error for Error { fn description(&self) -> &str { match self.repr { Repr::Os(..) => "os error", - Repr::Custom(ref c) => c.desc, + Repr::Custom(ref c) => c.error.description(), } } } diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index 52daba36213..67bc45d3b62 100644 --- a/src/libstd/io/impls.rs +++ b/src/libstd/io/impls.rs @@ -180,7 +180,7 @@ impl<'a> Write for &'a mut [u8] { if try!(self.write(data)) == data.len() { Ok(()) } else { - Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer", None)) + Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")) } } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 830a88bb6c9..91ea7ab4df6 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -83,7 +83,7 @@ fn append_to_string(buf: &mut String, f: F) -> Result if str::from_utf8(&g.s[g.len..]).is_err() { ret.and_then(|_| { Err(Error::new(ErrorKind::InvalidInput, - "stream did not contain valid UTF-8", None)) + "stream did not contain valid UTF-8")) }) } else { g.len = g.s.len(); @@ -359,8 +359,7 @@ pub trait Write { while buf.len() > 0 { match self.write(buf) { Ok(0) => return Err(Error::new(ErrorKind::WriteZero, - "failed to write whole buffer", - None)), + "failed to write whole buffer")), Ok(n) => buf = &buf[n..], Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), @@ -780,7 +779,7 @@ pub struct Chars { /// An enumeration of possible errors that can be generated from the `Chars` /// adapter. -#[derive(PartialEq, Clone, Debug)] +#[derive(Debug)] #[unstable(feature = "io", reason = "awaiting stability of Read::chars")] pub enum CharsError { /// Variant representing that the underlying stream was read successfully diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index a08b33b342b..eb6cb441606 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -435,7 +435,7 @@ impl ToSocketAddrs for str { match $e { Some(r) => r, None => return Err(io::Error::new(io::ErrorKind::InvalidInput, - $msg, None)), + $msg)), } ) } diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index ee57300765e..a152b98822a 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -72,7 +72,7 @@ fn each_addr(addr: A, mut f: F) -> io::Result } Err(last_err.unwrap_or_else(|| { Error::new(ErrorKind::InvalidInput, - "could not resolve to any addresses", None) + "could not resolve to any addresses") })) } diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 81151114962..511c2e3f8b2 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -76,7 +76,7 @@ impl UdpSocket { match try!(addr.to_socket_addrs()).next() { Some(addr) => self.0.send_to(buf, &addr), None => Err(Error::new(ErrorKind::InvalidInput, - "no addresses to send data to", None)), + "no addresses to send data to")), } } diff --git a/src/libstd/process.rs b/src/libstd/process.rs index b4bd513e8f0..7921296dabf 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -461,7 +461,6 @@ impl Child { return Err(Error::new( ErrorKind::InvalidInput, "invalid argument: can't kill an exited process", - None )) } diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index a8ee40639e3..b4903096cce 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -75,7 +75,7 @@ fn sockaddr_to_addr(storage: &libc::sockaddr_storage, }))) } _ => { - Err(Error::new(ErrorKind::InvalidInput, "invalid argument", None)) + Err(Error::new(ErrorKind::InvalidInput, "invalid argument")) } } } @@ -158,8 +158,7 @@ pub fn lookup_addr(addr: &IpAddr) -> io::Result { match from_utf8(data.to_bytes()) { Ok(name) => Ok(name.to_string()), Err(_) => Err(io::Error::new(io::ErrorKind::Other, - "failed to lookup address information", - Some("invalid host name".to_string()))) + "failed to lookup address information")) } } diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index b22fa33e562..205f30810b5 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -35,7 +35,8 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { .to_string() }; Err(io::Error::new(io::ErrorKind::Other, - "failed to lookup address information", Some(detail))) + &format!("failed to lookup address information: {}", + detail)[..])) } impl Socket { From 55e531dc26b2cb20316fecb7a6126f6975ea9a47 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Tue, 31 Mar 2015 16:22:23 -0700 Subject: [PATCH 26/46] Add test for #17746 Closes #17746 --- src/test/run-pass/issue-17746.rs | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/test/run-pass/issue-17746.rs diff --git a/src/test/run-pass/issue-17746.rs b/src/test/run-pass/issue-17746.rs new file mode 100644 index 00000000000..a66d5e10288 --- /dev/null +++ b/src/test/run-pass/issue-17746.rs @@ -0,0 +1,33 @@ +// 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. + +// Regression test for #17746 + +fn main() {} + +struct A; + +impl A { + fn b(&mut self) { + self.a() + } +} + +trait Foo { + fn dummy(&self) {} +} +trait Bar { + fn a(&self); +} + +impl Foo for A {} +impl Bar for T where T: Foo { + fn a(&self) {} +} From 371ba00da2183a9763f1145c5e711e3278a785dd Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 31 Mar 2015 19:45:09 -0400 Subject: [PATCH 27/46] Add description of + for multiple trait bounds Fixes #23688 --- src/doc/trpl/traits.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/doc/trpl/traits.md b/src/doc/trpl/traits.md index 1e44076a430..341c90a7087 100644 --- a/src/doc/trpl/traits.md +++ b/src/doc/trpl/traits.md @@ -277,6 +277,29 @@ One last thing about traits: generic functions with a trait bound use dispatched. What's that mean? Check out the chapter on [static and dynamic dispatch](static-and-dynamic-dispatch.html) for more. +## Multiple trait bounds + +You’ve seen that you can bound a generic type parameter with a trait: + +```rust +fn foo(x: T) { + x.clone(); +} +``` + +If you need more than one bound, you can use `+`: + +```rust +use std::fmt::Debug; + +fn foo(x: T) { + x.clone(); + println!("{:?}", x); +} +``` + +`T` now needs to be both `Clone` as well as `Debug`. + ## Where clause Writing functions with only a few generic types and a small number of trait From 72f59732d7974767650abfc58f8287212e5a1fba Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 31 Mar 2015 16:20:09 -0700 Subject: [PATCH 28/46] Test fixes and rebase conflicts, round 3 --- src/liballoc/lib.rs | 1 - src/libcollections/str.rs | 24 +++--- src/libcore/iter.rs | 3 +- src/librbml/lib.rs | 1 - src/librustc/middle/ty.rs | 1 - src/libstd/io/buffered.rs | 44 +++++------ src/libstd/io/cursor.rs | 122 +++++++++++++++---------------- src/libstd/io/mod.rs | 48 ++++++------ src/libstd/io/util.rs | 24 +++--- src/libstd/net/addr.rs | 7 +- src/libstd/net/tcp.rs | 14 ++-- src/libstd/net/udp.rs | 4 +- src/libstd/process.rs | 2 +- src/libstd/sys/unix/fs2.rs | 2 +- src/libstd/sys/windows/c.rs | 2 +- src/libstd/sys/windows/os.rs | 2 +- src/libstd/sys/windows/stdio.rs | 5 +- src/test/run-pass/issue-22577.rs | 3 +- 18 files changed, 156 insertions(+), 153 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index a880ba5cfe4..b92dfa9117e 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -78,7 +78,6 @@ #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(core)] #![feature(unique)] -#![feature(convert)] #![cfg_attr(test, feature(test, alloc, rustc_private))] #![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")), feature(libc))] diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 62a6df71e35..f8f2909291f 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -12,10 +12,10 @@ //! Unicode string manipulation (the `str` type). //! -//! Rust's `str` type is one of the core primitive types of the language. `&str` is the borrowed -//! string type. This type of string can only be created from other strings, unless it is a -//! `&'static str` (see below). It is not possible to move out of borrowed strings because they are -//! owned elsewhere. +//! Rust's `str` type is one of the core primitive types of the language. `&str` +//! is the borrowed string type. This type of string can only be created from +//! other strings, unless it is a `&'static str` (see below). It is not possible +//! to move out of borrowed strings because they are owned elsewhere. //! //! # Examples //! @@ -25,8 +25,9 @@ //! let s = "Hello, world."; //! ``` //! -//! This `&str` is a `&'static str`, which is the type of string literals. They're `'static` -//! because literals are available for the entire lifetime of the program. +//! This `&str` is a `&'static str`, which is the type of string literals. +//! They're `'static` because literals are available for the entire lifetime of +//! the program. //! //! You can get a non-`'static` `&str` by taking a slice of a `String`: //! @@ -37,12 +38,13 @@ //! //! # Representation //! -//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as a stream of UTF-8 -//! bytes. All [strings](../../reference.html#literals) are guaranteed to be validly encoded UTF-8 -//! sequences. Additionally, strings are not null-terminated and can thus contain null bytes. +//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as +//! a stream of UTF-8 bytes. All [strings](../../reference.html#literals) are +//! guaranteed to be validly encoded UTF-8 sequences. Additionally, strings are +//! not null-terminated and can thus contain null bytes. //! -//! The actual representation of `str`s have direct mappings to slices: `&str` is the same as -//! `&[u8]`. +//! The actual representation of `str`s have direct mappings to slices: `&str` +//! is the same as `&[u8]`. #![doc(primitive = "str")] #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index cf417d9d2d8..2d69eeb9fa9 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -41,10 +41,11 @@ //! } //! //! // Rough translation of the iteration without a `for` iterator. +//! # let values = vec![1, 2, 3]; //! let mut it = values.into_iter(); //! loop { //! match it.next() { -//! Some(&x) => { +//! Some(x) => { //! println!("{}", x); //! } //! None => { break } diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 878ef04942a..3e91b988770 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -123,7 +123,6 @@ html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(io)] #![feature(core)] #![feature(rustc_private)] #![feature(staged_api)] diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 1090ba984ee..161fae11ea6 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -73,7 +73,6 @@ use std::cmp; use std::fmt; use std::hash::{Hash, SipHasher, Hasher}; use std::mem; -use std::num::ToPrimitive; use std::ops; use std::rc::Rc; use std::vec::IntoIter; diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 479665c4728..6fe35614a85 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -503,34 +503,34 @@ mod tests { let mut buf = [0, 0, 0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(3), nread); + assert_eq!(nread.unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(buf, b); let mut buf = [0, 0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(2), nread); + assert_eq!(nread.unwrap(), 2); let b: &[_] = &[0, 1]; assert_eq!(buf, b); let mut buf = [0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(1), nread); + assert_eq!(nread.unwrap(), 1); let b: &[_] = &[2]; assert_eq!(buf, b); let mut buf = [0, 0, 0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(1), nread); + assert_eq!(nread.unwrap(), 1); let b: &[_] = &[3, 0, 0]; assert_eq!(buf, b); let nread = reader.read(&mut buf); - assert_eq!(Ok(1), nread); + assert_eq!(nread.unwrap(), 1); let b: &[_] = &[4, 0, 0]; assert_eq!(buf, b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] @@ -592,7 +592,7 @@ mod tests { } let mut stream = BufStream::new(S); - assert_eq!(stream.read(&mut [0; 10]), Ok(0)); + assert_eq!(stream.read(&mut [0; 10]).unwrap(), 0); stream.write(&[0; 10]).unwrap(); stream.flush().unwrap(); } @@ -658,10 +658,10 @@ mod tests { let in_buf: &[u8] = b"a\nb\nc"; let reader = BufReader::with_capacity(2, in_buf); let mut it = reader.lines(); - assert_eq!(it.next(), Some(Ok("a".to_string()))); - assert_eq!(it.next(), Some(Ok("b".to_string()))); - assert_eq!(it.next(), Some(Ok("c".to_string()))); - assert_eq!(it.next(), None); + assert_eq!(it.next().unwrap().unwrap(), "a".to_string()); + assert_eq!(it.next().unwrap().unwrap(), "b".to_string()); + assert_eq!(it.next().unwrap().unwrap(), "c".to_string()); + assert!(it.next().is_none()); } #[test] @@ -669,20 +669,20 @@ mod tests { let inner = ShortReader{lengths: vec![0, 1, 2, 0, 1, 0]}; let mut reader = BufReader::new(inner); let mut buf = [0, 0]; - assert_eq!(reader.read(&mut buf), Ok(0)); - assert_eq!(reader.read(&mut buf), Ok(1)); - assert_eq!(reader.read(&mut buf), Ok(2)); - assert_eq!(reader.read(&mut buf), Ok(0)); - assert_eq!(reader.read(&mut buf), Ok(1)); - assert_eq!(reader.read(&mut buf), Ok(0)); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.read(&mut buf).unwrap(), 2); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] fn read_char_buffered() { let buf = [195, 159]; let reader = BufReader::with_capacity(1, &buf[..]); - assert_eq!(reader.chars().next(), Some(Ok('ß'))); + assert_eq!(reader.chars().next().unwrap().unwrap(), 'ß'); } #[test] @@ -690,9 +690,9 @@ mod tests { let buf = [195, 159, b'a']; let reader = BufReader::with_capacity(1, &buf[..]); let mut it = reader.chars(); - assert_eq!(it.next(), Some(Ok('ß'))); - assert_eq!(it.next(), Some(Ok('a'))); - assert_eq!(it.next(), None); + assert_eq!(it.next().unwrap().unwrap(), 'ß'); + assert_eq!(it.next().unwrap().unwrap(), 'a'); + assert!(it.next().is_none()); } #[test] diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index a7b7f96c22b..6433c29bb9d 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -171,9 +171,9 @@ mod tests { #[test] fn test_vec_writer() { let mut writer = Vec::new(); - assert_eq!(writer.write(&[0]), Ok(1)); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; assert_eq!(writer, b); } @@ -181,9 +181,9 @@ mod tests { #[test] fn test_mem_writer() { let mut writer = Cursor::new(Vec::new()); - assert_eq!(writer.write(&[0]), Ok(1)); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; assert_eq!(&writer.get_ref()[..], b); } @@ -194,16 +194,16 @@ mod tests { { let mut writer = Cursor::new(&mut buf[..]); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[0]), Ok(1)); + assert_eq!(writer.write(&[0]).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); assert_eq!(writer.position(), 8); - assert_eq!(writer.write(&[]), Ok(0)); + assert_eq!(writer.write(&[]).unwrap(), 0); assert_eq!(writer.position(), 8); - assert_eq!(writer.write(&[8, 9]), Ok(1)); - assert_eq!(writer.write(&[10]), Ok(0)); + assert_eq!(writer.write(&[8, 9]).unwrap(), 1); + assert_eq!(writer.write(&[10]).unwrap(), 0); } let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; assert_eq!(buf, b); @@ -215,22 +215,22 @@ mod tests { { let mut writer = Cursor::new(&mut buf[..]); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[1]), Ok(1)); + assert_eq!(writer.write(&[1]).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.seek(SeekFrom::Start(2)), Ok(2)); + assert_eq!(writer.seek(SeekFrom::Start(2)).unwrap(), 2); assert_eq!(writer.position(), 2); - assert_eq!(writer.write(&[2]), Ok(1)); + assert_eq!(writer.write(&[2]).unwrap(), 1); assert_eq!(writer.position(), 3); - assert_eq!(writer.seek(SeekFrom::Current(-2)), Ok(1)); + assert_eq!(writer.seek(SeekFrom::Current(-2)).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.write(&[3]), Ok(1)); + assert_eq!(writer.write(&[3]).unwrap(), 1); assert_eq!(writer.position(), 2); - assert_eq!(writer.seek(SeekFrom::End(-1)), Ok(7)); + assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7); assert_eq!(writer.position(), 7); - assert_eq!(writer.write(&[4]), Ok(1)); + assert_eq!(writer.write(&[4]).unwrap(), 1); assert_eq!(writer.position(), 8); } @@ -242,31 +242,31 @@ mod tests { fn test_buf_writer_error() { let mut buf = [0 as u8; 2]; let mut writer = Cursor::new(&mut buf[..]); - assert_eq!(writer.write(&[0]), Ok(1)); - assert_eq!(writer.write(&[0, 0]), Ok(1)); - assert_eq!(writer.write(&[0, 0]), Ok(0)); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.write(&[0, 0]).unwrap(), 1); + assert_eq!(writer.write(&[0, 0]).unwrap(), 0); } #[test] fn test_mem_reader() { let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7)); let mut buf = []; - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); assert_eq!(reader.position(), 0); let mut buf = [0]; - assert_eq!(reader.read(&mut buf), Ok(1)); + assert_eq!(reader.read(&mut buf).unwrap(), 1); assert_eq!(reader.position(), 1); let b: &[_] = &[0]; assert_eq!(buf, b); let mut buf = [0; 4]; - assert_eq!(reader.read(&mut buf), Ok(4)); + assert_eq!(reader.read(&mut buf).unwrap(), 4); assert_eq!(reader.position(), 5); let b: &[_] = &[1, 2, 3, 4]; assert_eq!(buf, b); - assert_eq!(reader.read(&mut buf), Ok(3)); + assert_eq!(reader.read(&mut buf).unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(&buf[..3], b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] @@ -282,21 +282,21 @@ mod tests { let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; let mut reader = &mut &in_buf[..]; let mut buf = []; - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); let mut buf = [0]; - assert_eq!(reader.read(&mut buf), Ok(1)); + assert_eq!(reader.read(&mut buf).unwrap(), 1); assert_eq!(reader.len(), 7); let b: &[_] = &[0]; assert_eq!(&buf[..], b); let mut buf = [0; 4]; - assert_eq!(reader.read(&mut buf), Ok(4)); + assert_eq!(reader.read(&mut buf).unwrap(), 4); assert_eq!(reader.len(), 3); let b: &[_] = &[1, 2, 3, 4]; assert_eq!(&buf[..], b); - assert_eq!(reader.read(&mut buf), Ok(3)); + assert_eq!(reader.read(&mut buf).unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(&buf[..3], b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] @@ -304,33 +304,33 @@ mod tests { let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; let mut reader = Cursor::new(&in_buf[..]); let mut buf = []; - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); assert_eq!(reader.position(), 0); let mut buf = [0]; - assert_eq!(reader.read(&mut buf), Ok(1)); + assert_eq!(reader.read(&mut buf).unwrap(), 1); assert_eq!(reader.position(), 1); let b: &[_] = &[0]; assert_eq!(buf, b); let mut buf = [0; 4]; - assert_eq!(reader.read(&mut buf), Ok(4)); + assert_eq!(reader.read(&mut buf).unwrap(), 4); assert_eq!(reader.position(), 5); let b: &[_] = &[1, 2, 3, 4]; assert_eq!(buf, b); - assert_eq!(reader.read(&mut buf), Ok(3)); + assert_eq!(reader.read(&mut buf).unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(&buf[..3], b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] fn test_read_char() { let b = &b"Vi\xE1\xBB\x87t"[..]; let mut c = Cursor::new(b).chars(); - assert_eq!(c.next(), Some(Ok('V'))); - assert_eq!(c.next(), Some(Ok('i'))); - assert_eq!(c.next(), Some(Ok('ệ'))); - assert_eq!(c.next(), Some(Ok('t'))); - assert_eq!(c.next(), None); + assert_eq!(c.next().unwrap().unwrap(), 'V'); + assert_eq!(c.next().unwrap().unwrap(), 'i'); + assert_eq!(c.next().unwrap().unwrap(), 'ệ'); + assert_eq!(c.next().unwrap().unwrap(), 't'); + assert!(c.next().is_none()); } #[test] @@ -344,17 +344,17 @@ mod tests { fn seek_past_end() { let buf = [0xff]; let mut r = Cursor::new(&buf[..]); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.read(&mut [0]), Ok(0)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.read(&mut [0]).unwrap(), 0); let mut r = Cursor::new(vec!(10)); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.read(&mut [0]), Ok(0)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.read(&mut [0]).unwrap(), 0); let mut buf = [0]; let mut r = Cursor::new(&mut buf[..]); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.write(&[3]), Ok(0)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.write(&[3]).unwrap(), 0); } #[test] @@ -375,32 +375,32 @@ mod tests { fn test_seekable_mem_writer() { let mut writer = Cursor::new(Vec::::new()); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[0]), Ok(1)); + assert_eq!(writer.write(&[0]).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); assert_eq!(writer.position(), 8); let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::Start(0)), Ok(0)); + assert_eq!(writer.seek(SeekFrom::Start(0)).unwrap(), 0); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[3, 4]), Ok(2)); + assert_eq!(writer.write(&[3, 4]).unwrap(), 2); let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7]; assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::Current(1)), Ok(3)); - assert_eq!(writer.write(&[0, 1]), Ok(2)); + assert_eq!(writer.seek(SeekFrom::Current(1)).unwrap(), 3); + assert_eq!(writer.write(&[0, 1]).unwrap(), 2); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7]; assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::End(-1)), Ok(7)); - assert_eq!(writer.write(&[1, 2]), Ok(2)); + assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7); + assert_eq!(writer.write(&[1, 2]).unwrap(), 2); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2]; assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::End(1)), Ok(10)); - assert_eq!(writer.write(&[1]), Ok(1)); + assert_eq!(writer.seek(SeekFrom::End(1)).unwrap(), 10); + assert_eq!(writer.write(&[1]).unwrap(), 1); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]; assert_eq!(&writer.get_ref()[..], b); } @@ -408,8 +408,8 @@ mod tests { #[test] fn vec_seek_past_end() { let mut r = Cursor::new(Vec::new()); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.write(&[3]), Ok(1)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.write(&[3]).unwrap(), 1); } #[test] diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index d72abe8c69b..a014d6e68ff 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -920,18 +920,18 @@ mod tests { fn read_until() { let mut buf = Cursor::new(&b"12"[..]); let mut v = Vec::new(); - assert_eq!(buf.read_until(b'3', &mut v), Ok(2)); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 2); assert_eq!(v, b"12"); let mut buf = Cursor::new(&b"1233"[..]); let mut v = Vec::new(); - assert_eq!(buf.read_until(b'3', &mut v), Ok(3)); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 3); assert_eq!(v, b"123"); v.truncate(0); - assert_eq!(buf.read_until(b'3', &mut v), Ok(1)); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 1); assert_eq!(v, b"3"); v.truncate(0); - assert_eq!(buf.read_until(b'3', &mut v), Ok(0)); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 0); assert_eq!(v, []); } @@ -939,32 +939,32 @@ mod tests { fn split() { let buf = Cursor::new(&b"12"[..]); let mut s = buf.split(b'3'); - assert_eq!(s.next(), Some(Ok(vec![b'1', b'2']))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); + assert!(s.next().is_none()); let buf = Cursor::new(&b"1233"[..]); let mut s = buf.split(b'3'); - assert_eq!(s.next(), Some(Ok(vec![b'1', b'2']))); - assert_eq!(s.next(), Some(Ok(vec![]))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); + assert_eq!(s.next().unwrap().unwrap(), vec![]); + assert!(s.next().is_none()); } #[test] fn read_line() { let mut buf = Cursor::new(&b"12"[..]); let mut v = String::new(); - assert_eq!(buf.read_line(&mut v), Ok(2)); + assert_eq!(buf.read_line(&mut v).unwrap(), 2); assert_eq!(v, "12"); let mut buf = Cursor::new(&b"12\n\n"[..]); let mut v = String::new(); - assert_eq!(buf.read_line(&mut v), Ok(3)); + assert_eq!(buf.read_line(&mut v).unwrap(), 3); assert_eq!(v, "12\n"); v.truncate(0); - assert_eq!(buf.read_line(&mut v), Ok(1)); + assert_eq!(buf.read_line(&mut v).unwrap(), 1); assert_eq!(v, "\n"); v.truncate(0); - assert_eq!(buf.read_line(&mut v), Ok(0)); + assert_eq!(buf.read_line(&mut v).unwrap(), 0); assert_eq!(v, ""); } @@ -972,26 +972,26 @@ mod tests { fn lines() { let buf = Cursor::new(&b"12"[..]); let mut s = buf.lines(); - assert_eq!(s.next(), Some(Ok("12".to_string()))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), "12".to_string()); + assert!(s.next().is_none()); let buf = Cursor::new(&b"12\n\n"[..]); let mut s = buf.lines(); - assert_eq!(s.next(), Some(Ok("12".to_string()))); - assert_eq!(s.next(), Some(Ok(String::new()))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), "12".to_string()); + assert_eq!(s.next().unwrap().unwrap(), "".to_string()); + assert!(s.next().is_none()); } #[test] fn read_to_end() { let mut c = Cursor::new(&b""[..]); let mut v = Vec::new(); - assert_eq!(c.read_to_end(&mut v), Ok(0)); + assert_eq!(c.read_to_end(&mut v).unwrap(), 0); assert_eq!(v, []); let mut c = Cursor::new(&b"1"[..]); let mut v = Vec::new(); - assert_eq!(c.read_to_end(&mut v), Ok(1)); + assert_eq!(c.read_to_end(&mut v).unwrap(), 1); assert_eq!(v, b"1"); } @@ -999,12 +999,12 @@ mod tests { fn read_to_string() { let mut c = Cursor::new(&b""[..]); let mut v = String::new(); - assert_eq!(c.read_to_string(&mut v), Ok(0)); + assert_eq!(c.read_to_string(&mut v).unwrap(), 0); assert_eq!(v, ""); let mut c = Cursor::new(&b"1"[..]); let mut v = String::new(); - assert_eq!(c.read_to_string(&mut v), Ok(1)); + assert_eq!(c.read_to_string(&mut v).unwrap(), 1); assert_eq!(v, "1"); let mut c = Cursor::new(&b"\xff"[..]); @@ -1018,11 +1018,11 @@ mod tests { impl Read for R { fn read(&mut self, _: &mut [u8]) -> io::Result { - Err(io::Error::new(io::ErrorKind::Other, "", None)) + Err(io::Error::new(io::ErrorKind::Other, "")) } } let mut buf = [0; 1]; - assert_eq!(Ok(0), R.take(0).read(&mut buf)); + assert_eq!(0, R.take(0).read(&mut buf).unwrap()); } } diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 20426025257..c82f9515e8d 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -111,33 +111,33 @@ mod test { #[test] fn sink_sinks() { let mut s = sink(); - assert_eq!(s.write(&[]), Ok(0)); - assert_eq!(s.write(&[0]), Ok(1)); - assert_eq!(s.write(&[0; 1024]), Ok(1024)); - assert_eq!(s.by_ref().write(&[0; 1024]), Ok(1024)); + assert_eq!(s.write(&[]).unwrap(), 0); + assert_eq!(s.write(&[0]).unwrap(), 1); + assert_eq!(s.write(&[0; 1024]).unwrap(), 1024); + assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024); } #[test] fn empty_reads() { let mut e = empty(); - assert_eq!(e.read(&mut []), Ok(0)); - assert_eq!(e.read(&mut [0]), Ok(0)); - assert_eq!(e.read(&mut [0; 1024]), Ok(0)); - assert_eq!(e.by_ref().read(&mut [0; 1024]), Ok(0)); + assert_eq!(e.read(&mut []).unwrap(), 0); + assert_eq!(e.read(&mut [0]).unwrap(), 0); + assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); + assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); } #[test] fn repeat_repeats() { let mut r = repeat(4); let mut b = [0; 1024]; - assert_eq!(r.read(&mut b), Ok(1024)); + assert_eq!(r.read(&mut b).unwrap(), 1024); assert!(b.iter().all(|b| *b == 4)); } #[test] fn take_some_bytes() { assert_eq!(repeat(4).take(100).bytes().count(), 100); - assert_eq!(repeat(4).take(100).bytes().next(), Some(Ok(4))); + assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4); assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20); } @@ -146,7 +146,7 @@ mod test { let mut buf = [0; 10]; { let mut ptr: &mut [u8] = &mut buf; - assert_eq!(repeat(4).tee(&mut ptr).take(5).read(&mut [0; 10]), Ok(5)); + assert_eq!(repeat(4).tee(&mut ptr).take(5).read(&mut [0; 10]).unwrap(), 5); } assert_eq!(buf, [4, 4, 4, 4, 4, 0, 0, 0, 0, 0]); } @@ -160,7 +160,7 @@ mod test { let mut ptr2: &mut [u8] = &mut buf2; assert_eq!((&mut ptr1).broadcast(&mut ptr2) - .write(&[1, 2, 3]), Ok(3)); + .write(&[1, 2, 3]).unwrap(), 3); } assert_eq!(buf1, buf2); assert_eq!(buf1, [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]); diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index eb6cb441606..c45230e91ba 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -697,8 +697,11 @@ mod tests { false, false, false, true, false, false, false, Some(Global)); } - fn tsa(a: A) -> io::Result> { - Ok(try!(a.to_socket_addrs()).collect()) + fn tsa(a: A) -> Result, String> { + match a.to_socket_addrs() { + Ok(a) => Ok(a.collect()), + Err(e) => Err(e.to_string()), + } } #[test] diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index a1a27f28fd9..04d1013af1f 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -521,7 +521,7 @@ mod tests { let mut c = t!(TcpStream::connect(&addr)); let mut b = [0; 10]; - assert_eq!(c.read(&mut b), Ok(1)); + assert_eq!(c.read(&mut b).unwrap(), 1); t!(c.write(&[1])); rx.recv().unwrap(); }) @@ -566,7 +566,7 @@ mod tests { let _t = thread::spawn(move|| { let mut s = t!(TcpStream::connect(&addr)); let mut buf = [0, 0]; - assert_eq!(s.read(&mut buf), Ok(1)); + assert_eq!(s.read(&mut buf).unwrap(), 1); assert_eq!(buf[0], 1); t!(s.write(&[2])); }); @@ -584,7 +584,7 @@ mod tests { }); tx1.send(()).unwrap(); let mut buf = [0, 0]; - assert_eq!(s1.read(&mut buf), Ok(1)); + assert_eq!(s1.read(&mut buf).unwrap(), 1); rx2.recv().unwrap(); }) } @@ -657,7 +657,7 @@ mod tests { let _t = thread::spawn(move|| { let mut c = t!(a.accept()).0; let mut b = [0]; - assert_eq!(c.read(&mut b), Ok(0)); + assert_eq!(c.read(&mut b).unwrap(), 0); t!(c.write(&[1])); }); @@ -688,16 +688,16 @@ mod tests { t!(s.shutdown(Shutdown::Write)); assert!(s.write(&[0]).is_err()); t!(s.shutdown(Shutdown::Read)); - assert_eq!(s.read(&mut b), Ok(0)); + assert_eq!(s.read(&mut b).unwrap(), 0); // closing should affect previous handles assert!(s2.write(&[0]).is_err()); - assert_eq!(s2.read(&mut b), Ok(0)); + assert_eq!(s2.read(&mut b).unwrap(), 0); // closing should affect new handles let mut s3 = t!(s.try_clone()); assert!(s3.write(&[0]).is_err()); - assert_eq!(s3.read(&mut b), Ok(0)); + assert_eq!(s3.read(&mut b).unwrap(), 0); // make sure these don't die let _ = s2.shutdown(Shutdown::Read); diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 14b5c974b67..7b14e4dbea6 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -212,7 +212,7 @@ mod tests { let _t = thread::spawn(move|| { let mut buf = [0, 0]; - assert_eq!(sock2.recv_from(&mut buf), Ok((1, addr1))); + assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1)); assert_eq!(buf[0], 1); t!(sock2.send_to(&[2], &addr1)); }); @@ -228,7 +228,7 @@ mod tests { }); tx1.send(()).unwrap(); let mut buf = [0, 0]; - assert_eq!(sock1.recv_from(&mut buf), Ok((1, addr2))); + assert_eq!(sock1.recv_from(&mut buf).unwrap(), (1, addr2)); rx2.recv().unwrap(); }) } diff --git a/src/libstd/process.rs b/src/libstd/process.rs index ca25cadb9dc..c2d43ba2a05 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -576,7 +576,7 @@ mod tests { assert!(p.is_ok()); let mut p = p.unwrap(); assert!(p.wait().unwrap().code() == Some(1)); - drop(p.wait().clone()); + drop(p.wait()); } #[cfg(all(unix, not(target_os="android")))] diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs index 314d694f66a..c0426af051b 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs2.rs @@ -277,7 +277,7 @@ impl File { fn cstr(path: &Path) -> io::Result { path.as_os_str().to_cstring().ok_or( - io::Error::new(io::ErrorKind::InvalidInput, "path contained a null", None)) + io::Error::new(io::ErrorKind::InvalidInput, "path contained a null")) } impl FromInner for File { diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index b930e35c064..e74de595f97 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -433,7 +433,7 @@ extern "system" { TokenHandle: *mut libc::HANDLE) -> libc::BOOL; pub fn GetCurrentProcess() -> libc::HANDLE; pub fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; - pub fn ExitProcess(uExitCode: libc::UINT) -> !; + pub fn ExitProcess(uExitCode: libc::c_uint) -> !; } #[link(name = "userenv")] diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index f98c39cfad0..d5843a2f998 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -382,5 +382,5 @@ pub fn home_dir() -> Option { } pub fn exit(code: i32) -> ! { - unsafe { libc::ExitProcess(code as libc::UINT) } + unsafe { c::ExitProcess(code as libc::c_uint) } } diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index d1bff0e135d..91f6f328ff6 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -41,7 +41,7 @@ fn get(handle: libc::DWORD) -> io::Result { Err(io::Error::last_os_error()) } else if handle.is_null() { Err(io::Error::new(io::ErrorKind::Other, - "no stdio handle available for this process", None)) + "no stdio handle available for this process")) } else { let ret = NoClose::new(handle); let mut out = 0; @@ -160,6 +160,5 @@ impl Drop for NoClose { } fn invalid_encoding() -> io::Error { - io::Error::new(io::ErrorKind::InvalidInput, "text was not valid unicode", - None) + io::Error::new(io::ErrorKind::InvalidInput, "text was not valid unicode") } diff --git a/src/test/run-pass/issue-22577.rs b/src/test/run-pass/issue-22577.rs index a47c844e199..2c4141b0bd3 100644 --- a/src/test/run-pass/issue-22577.rs +++ b/src/test/run-pass/issue-22577.rs @@ -15,13 +15,14 @@ use std::{fs, net}; fn assert_both() {} +fn assert_send() {} fn main() { assert_both::(); assert_both::(); assert_both::(); assert_both::(); - assert_both::(); + assert_send::(); assert_both::(); assert_both::(); From 4e04d57efa665ae62a2af4c2d785809f15c17599 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 27 Mar 2015 01:43:14 +0100 Subject: [PATCH 29/46] Added type-specific overflow checks when computing enum discriminant values. Moved such overflow checking into one place (in `rustc::middle::ty`, since it needs to be run on-demand during `const_eval` in some scenarios), and revised `rustc_typeck` accordingly. (Note that we only check for overflow if program did not provide a discriminant value explicitly.) Fix #23030 Fix #23221 Fix #23235 --- src/librustc/diagnostics.rs | 5 +- src/librustc/middle/ty.rs | 305 ++++++++++++++++++++++++----- src/librustc_typeck/check/mod.rs | 85 ++------ src/librustc_typeck/diagnostics.rs | 2 - 4 files changed, 279 insertions(+), 118 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 70303bb3410..0a29ed90ad4 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -68,6 +68,8 @@ register_diagnostics! { E0019, E0020, E0022, + E0079, // enum variant: expected signed integer constant + E0080, // enum variant: constant evaluation error E0109, E0110, E0133, @@ -128,7 +130,8 @@ register_diagnostics! { E0313, // lifetime of borrowed pointer outlives lifetime of captured variable E0314, // closure outlives stack frame E0315, // cannot invoke closure outside of its lifetime - E0316 // nested quantification of lifetimes + E0316, // nested quantification of lifetimes + E0370 // discriminant overflow } __build_diagnostic_array! { DIAGNOSTICS } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 161fae11ea6..c40f31d837a 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -73,6 +73,8 @@ use std::cmp; use std::fmt; use std::hash::{Hash, SipHasher, Hasher}; use std::mem; +use std::num::ToPrimitive; +use std::num::wrapping::WrappingOps; use std::ops; use std::rc::Rc; use std::vec::IntoIter; @@ -83,9 +85,11 @@ use syntax::ast::{CrateNum, DefId, Ident, ItemTrait, LOCAL_CRATE}; use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId}; use syntax::ast::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility}; use syntax::ast_util::{self, is_local, lit_is_str, local_def}; -use syntax::attr::{self, AttrMetaMethods}; +use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt}; use syntax::codemap::Span; use syntax::parse::token::{self, InternedString, special_idents}; +use syntax::print::pprust; +use syntax::ptr::P; use syntax::{ast, ast_map}; pub type Disr = u64; @@ -5489,63 +5493,268 @@ pub fn type_is_empty(cx: &ctxt, ty: Ty) -> bool { } } +trait IntTypeExt { + fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx>; + fn i64_to_disr(&self, val: i64) -> Option; + fn u64_to_disr(&self, val: u64) -> Option; + fn disr_incr(&self, val: Disr) -> Option; + fn disr_string(&self, val: Disr) -> String; + fn disr_wrap_incr(&self, val: Option) -> Disr; +} + +impl IntTypeExt for attr::IntType { + fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> { + match *self { + SignedInt(ast::TyI8) => cx.types.i8, + SignedInt(ast::TyI16) => cx.types.i16, + SignedInt(ast::TyI32) => cx.types.i32, + SignedInt(ast::TyI64) => cx.types.i64, + SignedInt(ast::TyIs) => cx.types.int, + UnsignedInt(ast::TyU8) => cx.types.u8, + UnsignedInt(ast::TyU16) => cx.types.u16, + UnsignedInt(ast::TyU32) => cx.types.u32, + UnsignedInt(ast::TyU64) => cx.types.u64, + UnsignedInt(ast::TyUs) => cx.types.uint, + } + } + + fn i64_to_disr(&self, val: i64) -> Option { + match *self { + SignedInt(ast::TyI8) => val.to_i8() .map(|v| v as Disr), + SignedInt(ast::TyI16) => val.to_i16() .map(|v| v as Disr), + SignedInt(ast::TyI32) => val.to_i32() .map(|v| v as Disr), + SignedInt(ast::TyI64) => val.to_i64() .map(|v| v as Disr), + UnsignedInt(ast::TyU8) => val.to_u8() .map(|v| v as Disr), + UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr), + UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr), + UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr), + + UnsignedInt(ast::TyUs) | + SignedInt(ast::TyIs) => unreachable!(), + } + } + + fn u64_to_disr(&self, val: u64) -> Option { + match *self { + SignedInt(ast::TyI8) => val.to_i8() .map(|v| v as Disr), + SignedInt(ast::TyI16) => val.to_i16() .map(|v| v as Disr), + SignedInt(ast::TyI32) => val.to_i32() .map(|v| v as Disr), + SignedInt(ast::TyI64) => val.to_i64() .map(|v| v as Disr), + UnsignedInt(ast::TyU8) => val.to_u8() .map(|v| v as Disr), + UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr), + UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr), + UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr), + + UnsignedInt(ast::TyUs) | + SignedInt(ast::TyIs) => unreachable!(), + } + } + + fn disr_incr(&self, val: Disr) -> Option { + macro_rules! add1 { + ($e:expr) => { $e.and_then(|v|v.checked_add(1)).map(|v| v as Disr) } + } + match *self { + // SignedInt repr means we *want* to reinterpret the bits + // treating the highest bit of Disr as a sign-bit, so + // cast to i64 before range-checking. + SignedInt(ast::TyI8) => add1!((val as i64).to_i8()), + SignedInt(ast::TyI16) => add1!((val as i64).to_i16()), + SignedInt(ast::TyI32) => add1!((val as i64).to_i32()), + SignedInt(ast::TyI64) => add1!(Some(val as i64)), + + UnsignedInt(ast::TyU8) => add1!(val.to_u8()), + UnsignedInt(ast::TyU16) => add1!(val.to_u16()), + UnsignedInt(ast::TyU32) => add1!(val.to_u32()), + UnsignedInt(ast::TyU64) => add1!(Some(val)), + + UnsignedInt(ast::TyUs) | + SignedInt(ast::TyIs) => unreachable!(), + } + } + + // This returns a String because (1.) it is only used for + // rendering an error message and (2.) a string can represent the + // full range from `i64::MIN` through `u64::MAX`. + fn disr_string(&self, val: Disr) -> String { + match *self { + SignedInt(ast::TyI8) => format!("{}", val as i8 ), + SignedInt(ast::TyI16) => format!("{}", val as i16), + SignedInt(ast::TyI32) => format!("{}", val as i32), + SignedInt(ast::TyI64) => format!("{}", val as i64), + UnsignedInt(ast::TyU8) => format!("{}", val as u8 ), + UnsignedInt(ast::TyU16) => format!("{}", val as u16), + UnsignedInt(ast::TyU32) => format!("{}", val as u32), + UnsignedInt(ast::TyU64) => format!("{}", val as u64), + + UnsignedInt(ast::TyUs) | + SignedInt(ast::TyIs) => unreachable!(), + } + } + + fn disr_wrap_incr(&self, val: Option) -> Disr { + macro_rules! add1 { + ($e:expr) => { ($e).wrapping_add(1) as Disr } + } + let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE); + match *self { + SignedInt(ast::TyI8) => add1!(val as i8 ), + SignedInt(ast::TyI16) => add1!(val as i16), + SignedInt(ast::TyI32) => add1!(val as i32), + SignedInt(ast::TyI64) => add1!(val as i64), + UnsignedInt(ast::TyU8) => add1!(val as u8 ), + UnsignedInt(ast::TyU16) => add1!(val as u16), + UnsignedInt(ast::TyU32) => add1!(val as u32), + UnsignedInt(ast::TyU64) => add1!(val as u64), + + UnsignedInt(ast::TyUs) | + SignedInt(ast::TyIs) => unreachable!(), + } + } +} + +/// Returns `(normalized_type, ty)`, where `normalized_type` is the +/// IntType representation of one of {i64,i32,i16,i8,u64,u32,u16,u8}, +/// and `ty` is the original type (i.e. may include `isize` or +/// `usize`). +pub fn enum_repr_type<'tcx>(cx: &ctxt<'tcx>, + opt_hint: Option<&attr::ReprAttr>) + -> (attr::IntType, Ty<'tcx>) +{ + let repr_type = match opt_hint { + // Feed in the given type + Some(&attr::ReprInt(_, int_t)) => int_t, + // ... but provide sensible default if none provided + // + // NB. Historically `fn enum_variants` generate i64 here, while + // rustc_typeck::check would generate isize. + _ => SignedInt(ast::TyIs), + }; + + let repr_type_ty = repr_type.to_ty(cx); + let repr_type = match repr_type { + SignedInt(ast::TyIs) => + SignedInt(cx.sess.target.int_type), + UnsignedInt(ast::TyUs) => + UnsignedInt(cx.sess.target.uint_type), + other => other + }; + + (repr_type, repr_type_ty) +} + +fn report_discrim_overflow(cx: &ctxt, + variant_span: Span, + variant_name: &str, + repr_type: attr::IntType, + prev_val: Disr) { + let computed_value = repr_type.disr_wrap_incr(Some(prev_val)); + let computed_value = repr_type.disr_string(computed_value); + let prev_val = repr_type.disr_string(prev_val); + let repr_type = repr_type.to_ty(cx).user_string(cx); + span_err!(cx.sess, variant_span, E0370, + "enum discriminant overflowed on value after {}: {}; \ + set explicitly via {} = {} if that is desired outcome", + prev_val, repr_type, variant_name, computed_value); +} + +// This computes the discriminant values for the sequence of Variants +// attached to a particular enum, taking into account the #[repr] (if +// any) provided via the `opt_hint`. +fn compute_enum_variants<'tcx>(cx: &ctxt<'tcx>, + vs: &'tcx [P], + opt_hint: Option<&attr::ReprAttr>) + -> Vec>> { + let mut variants: Vec> = Vec::new(); + let mut prev_disr_val: Option = None; + + let (repr_type, repr_type_ty) = ty::enum_repr_type(cx, opt_hint); + + for v in vs { + // If the discriminant value is specified explicitly in the + // enum, check whether the initialization expression is valid, + // otherwise use the last value plus one. + let current_disr_val; + + // This closure marks cases where, when an error occurs during + // the computation, attempt to assign a (hopefully) fresh + // value to avoid spurious error reports downstream. + let attempt_fresh_value = move || -> Disr { + repr_type.disr_wrap_incr(prev_disr_val) + }; + + match v.node.disr_expr { + Some(ref e) => { + debug!("disr expr, checking {}", pprust::expr_to_string(&**e)); + + // check_expr (from check_const pass) doesn't guarantee + // that the expression is in a form that eval_const_expr can + // handle, so we may still get an internal compiler error + // + // pnkfelix: The above comment was transcribed from + // the version of this code taken from rustc_typeck. + // Presumably the implication is that we need to deal + // with such ICE's as they arise. + // + // Since this can be called from `ty::enum_variants` + // anyway, best thing is to make `eval_const_expr` + // more robust (on case-by-case basis). + + match const_eval::eval_const_expr_partial(cx, &**e, Some(repr_type_ty)) { + Ok(const_eval::const_int(val)) => current_disr_val = val as Disr, + Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr, + Ok(_) => { + span_err!(cx.sess, e.span, E0079, + "expected signed integer constant"); + current_disr_val = attempt_fresh_value(); + } + Err(ref err) => { + span_err!(cx.sess, err.span, E0080, + "constant evaluation error: {}", + err.description()); + current_disr_val = attempt_fresh_value(); + } + } + }, + None => { + current_disr_val = match prev_disr_val { + Some(prev_disr_val) => { + if let Some(v) = repr_type.disr_incr(prev_disr_val) { + v + } else { + report_discrim_overflow(cx, v.span, v.node.name.as_str(), + repr_type, prev_disr_val); + attempt_fresh_value() + } + } + None => ty::INITIAL_DISCRIMINANT_VALUE + } + } + } + + let variant_info = Rc::new(VariantInfo::from_ast_variant(cx, &**v, current_disr_val)); + prev_disr_val = Some(current_disr_val); + + variants.push(variant_info); + } + + return variants; +} + pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) -> Rc>>> { memoized(&cx.enum_var_cache, id, |id: ast::DefId| { if ast::LOCAL_CRATE != id.krate { Rc::new(csearch::get_enum_variants(cx, id)) } else { - /* - Although both this code and check_enum_variants in typeck/check - call eval_const_expr, it should never get called twice for the same - expr, since check_enum_variants also updates the enum_var_cache - */ match cx.map.get(id.node) { ast_map::NodeItem(ref item) => { match item.node { ast::ItemEnum(ref enum_definition, _) => { - let mut last_discriminant: Option = None; - Rc::new(enum_definition.variants.iter().map(|variant| { - - let mut discriminant = INITIAL_DISCRIMINANT_VALUE; - if let Some(ref e) = variant.node.disr_expr { - // Preserve all values, and prefer signed. - let ty = Some(cx.types.i64); - match const_eval::eval_const_expr_partial(cx, &**e, ty) { - Ok(const_eval::const_int(val)) => { - discriminant = val as Disr; - } - Ok(const_eval::const_uint(val)) => { - discriminant = val as Disr; - } - Ok(_) => { - span_err!(cx.sess, e.span, E0304, - "expected signed integer constant"); - } - Err(err) => { - span_err!(cx.sess, err.span, E0305, - "constant evaluation error: {}", - err.description()); - } - } - } else { - if let Some(val) = last_discriminant { - if let Some(v) = val.checked_add(1) { - discriminant = v - } else { - cx.sess.span_err( - variant.span, - &format!("Discriminant overflowed!")); - } - } else { - discriminant = INITIAL_DISCRIMINANT_VALUE; - } - } - - last_discriminant = Some(discriminant); - Rc::new(VariantInfo::from_ast_variant(cx, &**variant, - discriminant)) - }).collect()) + Rc::new(compute_enum_variants( + cx, + &enum_definition.variants, + lookup_repr_hints(cx, id).get(0))) } _ => { cx.sess.bug("enum_variants: id not bound to an enum") diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 16501ec2807..fbff4e84788 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -85,7 +85,7 @@ use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode}; use check::_match::pat_ctxt; use fmt_macros::{Parser, Piece, Position}; use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS}; -use middle::{const_eval, def}; +use middle::def; use middle::infer; use middle::mem_categorization as mc; use middle::mem_categorization::McResult; @@ -94,7 +94,7 @@ use middle::privacy::{AllPublic, LastMod}; use middle::region::{self, CodeExtent}; use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace}; use middle::traits; -use middle::ty::{FnSig, GenericPredicates, VariantInfo, TypeScheme}; +use middle::ty::{FnSig, GenericPredicates, TypeScheme}; use middle::ty::{Disr, ParamTy, ParameterEnvironment}; use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty}; use middle::ty::liberate_late_bound_regions; @@ -4283,68 +4283,30 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, vs: &'tcx [P], id: ast::NodeId, - hint: attr::ReprAttr) - -> Vec>> { + hint: attr::ReprAttr) { #![allow(trivial_numeric_casts)] let rty = ty::node_id_to_type(ccx.tcx, id); - let mut variants: Vec> = Vec::new(); let mut disr_vals: Vec = Vec::new(); - let mut prev_disr_val: Option = None; + let inh = static_inherited_fields(ccx); + let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id); + + let (_, repr_type_ty) = ty::enum_repr_type(ccx.tcx, Some(&hint)); for v in vs { + if let Some(ref e) = v.node.disr_expr { + check_const_with_ty(&fcx, e.span, e, repr_type_ty); + } + } - // If the discriminant value is specified explicitly in the enum check whether the - // initialization expression is valid, otherwise use the last value plus one. - let mut current_disr_val = match prev_disr_val { - Some(prev_disr_val) => { - if let Some(v) = prev_disr_val.checked_add(1) { - v - } else { - ty::INITIAL_DISCRIMINANT_VALUE - } - } - None => ty::INITIAL_DISCRIMINANT_VALUE - }; + let def_id = local_def(id); - match v.node.disr_expr { - Some(ref e) => { - debug!("disr expr, checking {}", pprust::expr_to_string(&**e)); + // ty::enum_variants guards against discriminant overflows, so + // we need not check for that. + let variants = ty::enum_variants(ccx.tcx, def_id); - let inh = static_inherited_fields(ccx); - let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id); - let declty = match hint { - attr::ReprAny | attr::ReprPacked | - attr::ReprExtern => fcx.tcx().types.isize, - - attr::ReprInt(_, attr::SignedInt(ity)) => { - ty::mk_mach_int(fcx.tcx(), ity) - } - attr::ReprInt(_, attr::UnsignedInt(ity)) => { - ty::mk_mach_uint(fcx.tcx(), ity) - }, - }; - check_const_with_ty(&fcx, e.span, &**e, declty); - // check_expr (from check_const pass) doesn't guarantee - // that the expression is in a form that eval_const_expr can - // handle, so we may still get an internal compiler error - - match const_eval::eval_const_expr_partial(ccx.tcx, &**e, Some(declty)) { - Ok(const_eval::const_int(val)) => current_disr_val = val as Disr, - Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr, - Ok(_) => { - span_err!(ccx.tcx.sess, e.span, E0079, - "expected signed integer constant"); - } - Err(ref err) => { - span_err!(ccx.tcx.sess, err.span, E0080, - "constant evaluation error: {}", - err.description()); - } - } - }, - None => () - }; + for (v, variant) in vs.iter().zip(variants.iter()) { + let current_disr_val = variant.disr_val; // Check for duplicate discriminant values match disr_vals.iter().position(|&x| x == current_disr_val) { @@ -4372,15 +4334,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } } disr_vals.push(current_disr_val); - - let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v, - current_disr_val)); - prev_disr_val = Some(current_disr_val); - - variants.push(variant_info); } - - return variants; } let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id }) @@ -4396,10 +4350,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, }; } - let variants = do_check(ccx, vs, id, hint); - - // cache so that ty::enum_variants won't repeat this work - ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants)); + do_check(ccx, vs, id, hint); check_representable(ccx.tcx, sp, id, "enum"); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 7d01bece01c..a8d93c8bd11 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -51,8 +51,6 @@ register_diagnostics! { E0075, E0076, E0077, - E0079, - E0080, E0081, E0082, E0083, From 36b6d0ecdc7cced17e1b7341883a33e42e03b7b2 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Sat, 28 Mar 2015 11:14:06 +0100 Subject: [PATCH 30/46] Added tests for discriminant overflows. --- src/test/compile-fail/discrim-ill-typed.rs | 118 +++++++++++++++ src/test/compile-fail/discrim-overflow-2.rs | 94 ++++++++++++ src/test/compile-fail/discrim-overflow.rs | 108 ++++++++++++++ src/test/run-pass/discrim-explicit-23030.rs | 156 ++++++++++++++++++++ 4 files changed, 476 insertions(+) create mode 100644 src/test/compile-fail/discrim-ill-typed.rs create mode 100644 src/test/compile-fail/discrim-overflow-2.rs create mode 100644 src/test/compile-fail/discrim-overflow.rs create mode 100644 src/test/run-pass/discrim-explicit-23030.rs diff --git a/src/test/compile-fail/discrim-ill-typed.rs b/src/test/compile-fail/discrim-ill-typed.rs new file mode 100644 index 00000000000..23106c99594 --- /dev/null +++ b/src/test/compile-fail/discrim-ill-typed.rs @@ -0,0 +1,118 @@ +// 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. + +// When explicit discriminant value has +// a type that does not match the representation +// type, rustc should fail gracefully. + +// See also run-pass/discrim-explicit-23030.rs where the input types +// are correct. + +#![allow(dead_code, unused_variables, unused_imports)] + +use std::{i8,u8,i16,u16,i32,u32,i64, u64}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo = 0_u8, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo = 0_i8, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo = 0_u16, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo = 0_i16, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo = 0_u32, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo = 0_i32, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo = 0_u64, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo = 0_i64, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn main() { } diff --git a/src/test/compile-fail/discrim-overflow-2.rs b/src/test/compile-fail/discrim-overflow-2.rs new file mode 100644 index 00000000000..76378d5c802 --- /dev/null +++ b/src/test/compile-fail/discrim-overflow-2.rs @@ -0,0 +1,94 @@ +// 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 + +// Issue 23030: Detect overflowing discriminant +// +// Check that we detect the overflow even if enum is not used. + +// See also run-pass/discrim-explicit-23030.rs where the suggested +// workaround is tested. + +use std::{i8,u8,i16,u16,i32,u32,i64, u64}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 127: i8; set explicitly via OhNo = -128 if that is desired outcome + } +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 255: u8; set explicitly via OhNo = 0 if that is desired outcome + } +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn main() { } diff --git a/src/test/compile-fail/discrim-overflow.rs b/src/test/compile-fail/discrim-overflow.rs new file mode 100644 index 00000000000..5d7e61e9d1e --- /dev/null +++ b/src/test/compile-fail/discrim-overflow.rs @@ -0,0 +1,108 @@ +// 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 + +// Issue 23030: Detect overflowing discriminant + +// See also run-pass/discrim-explicit-23030.rs where the suggested +// workaround is tested. + +use std::{i8,u8,i16,u16,i32,u32,i64, u64}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 127: i8; set explicitly via OhNo = -128 if that is desired outcome + } + + let x = A::Ok; +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 255: u8; set explicitly via OhNo = 0 if that is desired outcome + } + + let x = A::Ok; +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn main() { } diff --git a/src/test/run-pass/discrim-explicit-23030.rs b/src/test/run-pass/discrim-explicit-23030.rs new file mode 100644 index 00000000000..aed7b1527ce --- /dev/null +++ b/src/test/run-pass/discrim-explicit-23030.rs @@ -0,0 +1,156 @@ +// 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. + +// Issue 23030: Workaround overflowing discriminant +// with explicit assignments. + +// See also compile-fail/overflow-discrim.rs, which shows what +// happens if you leave the OhNo explicit cases out here. + +use std::{i8,u8,i16,u16,i32,u32,i64,u64,isize,usize}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo = i8::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i8; + assert_eq!(z, 0); +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo = u8::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo = i16::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i16; + assert_eq!(z, 0); +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo = u16::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo = i32::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i32; + assert_eq!(z, 0); +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo = u32::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo = i64::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i64; + assert_eq!(z, 0); +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo = u64::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_isize() { + #[repr(isize)] + enum A { + Ok = isize::MAX - 1, + Ok2, + OhNo = isize::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as isize; + assert_eq!(z, 0); +} + +fn f_usize() { + #[repr(usize)] + enum A { + Ok = usize::MAX - 1, + Ok2, + OhNo = usize::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn main() { + f_i8(); f_u8(); + f_i16(); f_u16(); + f_i32(); f_u32(); + f_i64(); f_u64(); + + f_isize(); f_usize(); +} From 0b57df77b3f7181a4dfb282dc8c4526846a9dddd Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 30 Mar 2015 20:20:35 +0200 Subject: [PATCH 31/46] fix post rebase. --- src/librustc/middle/ty.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c40f31d837a..2130ec4eb63 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -5509,12 +5509,12 @@ impl IntTypeExt for attr::IntType { SignedInt(ast::TyI16) => cx.types.i16, SignedInt(ast::TyI32) => cx.types.i32, SignedInt(ast::TyI64) => cx.types.i64, - SignedInt(ast::TyIs) => cx.types.int, + SignedInt(ast::TyIs) => cx.types.isize, UnsignedInt(ast::TyU8) => cx.types.u8, UnsignedInt(ast::TyU16) => cx.types.u16, UnsignedInt(ast::TyU32) => cx.types.u32, UnsignedInt(ast::TyU64) => cx.types.u64, - UnsignedInt(ast::TyUs) => cx.types.uint, + UnsignedInt(ast::TyUs) => cx.types.usize, } } From 792f6aa4259b438aee1633d495d01d909bfb6ea9 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 31 Mar 2015 17:55:28 +0200 Subject: [PATCH 32/46] Fix #23890: const-eval `_ as usize`, `_ as isize` must dispatch to target type. --- src/librustc/middle/const_eval.rs | 74 ++++++++++++++++++------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 0d9e0d14def..173358d336b 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -509,7 +509,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, // Prefer known type to noop, but always have a type hint. let base_hint = ty::expr_ty_opt(tcx, &**base).unwrap_or(ety); let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint))); - match cast_const(val, ety) { + match cast_const(tcx, val, ety) { Ok(val) => val, Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }), } @@ -607,39 +607,49 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, Ok(result) } -fn cast_const(val: const_val, ty: Ty) -> Result { - macro_rules! define_casts { - ($($ty_pat:pat => ( - $intermediate_ty:ty, - $const_type:ident, - $target_ty:ty - )),*) => (match ty.sty { - $($ty_pat => { - match val { - const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)), - const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)), - const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)), - const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)), - _ => Err(ErrKind::CannotCastTo(stringify!($const_type))), - } - },)* - _ => Err(ErrKind::CannotCast), - }) +fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, ty: Ty) -> Result { + macro_rules! convert_val { + ($intermediate_ty:ty, $const_type:ident, $target_ty:ty) => { + match val { + const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)), + const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)), + const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)), + const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)), + _ => Err(ErrKind::CannotCastTo(stringify!($const_type))), + } + } } - define_casts!{ - ty::ty_int(ast::TyIs) => (isize, const_int, i64), - ty::ty_int(ast::TyI8) => (i8, const_int, i64), - ty::ty_int(ast::TyI16) => (i16, const_int, i64), - ty::ty_int(ast::TyI32) => (i32, const_int, i64), - ty::ty_int(ast::TyI64) => (i64, const_int, i64), - ty::ty_uint(ast::TyUs) => (usize, const_uint, u64), - ty::ty_uint(ast::TyU8) => (u8, const_uint, u64), - ty::ty_uint(ast::TyU16) => (u16, const_uint, u64), - ty::ty_uint(ast::TyU32) => (u32, const_uint, u64), - ty::ty_uint(ast::TyU64) => (u64, const_uint, u64), - ty::ty_float(ast::TyF32) => (f32, const_float, f64), - ty::ty_float(ast::TyF64) => (f64, const_float, f64) + // Issue #23890: If isize/usize, then dispatch to appropriate target representation type + match (&ty.sty, tcx.sess.target.int_type, tcx.sess.target.uint_type) { + (&ty::ty_int(ast::TyIs), ast::TyI32, _) => return convert_val!(i32, const_int, i64), + (&ty::ty_int(ast::TyIs), ast::TyI64, _) => return convert_val!(i64, const_int, i64), + (&ty::ty_int(ast::TyIs), _, _) => panic!("unexpected target.int_type"), + + (&ty::ty_uint(ast::TyUs), _, ast::TyU32) => return convert_val!(u32, const_uint, u64), + (&ty::ty_uint(ast::TyUs), _, ast::TyU64) => return convert_val!(u64, const_uint, u64), + (&ty::ty_uint(ast::TyUs), _, _) => panic!("unexpected target.uint_type"), + + _ => {} + } + + match ty.sty { + ty::ty_int(ast::TyIs) => unreachable!(), + ty::ty_uint(ast::TyUs) => unreachable!(), + + ty::ty_int(ast::TyI8) => convert_val!(i8, const_int, i64), + ty::ty_int(ast::TyI16) => convert_val!(i16, const_int, i64), + ty::ty_int(ast::TyI32) => convert_val!(i32, const_int, i64), + ty::ty_int(ast::TyI64) => convert_val!(i64, const_int, i64), + + ty::ty_uint(ast::TyU8) => convert_val!(u8, const_uint, u64), + ty::ty_uint(ast::TyU16) => convert_val!(u16, const_uint, u64), + ty::ty_uint(ast::TyU32) => convert_val!(u32, const_uint, u64), + ty::ty_uint(ast::TyU64) => convert_val!(u64, const_uint, u64), + + ty::ty_float(ast::TyF32) => convert_val!(f32, const_float, f64), + ty::ty_float(ast::TyF64) => convert_val!(f64, const_float, f64), + _ => Err(ErrKind::CannotCast), } } From 60289ac7e704853049a441893f69a8eec5a00fa4 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 27 Mar 2015 14:17:10 +0100 Subject: [PATCH 33/46] Added overflowing_{div,rem,shl,shr} method implementations to WrappingOps. --- src/libcore/num/wrapping.rs | 130 ++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index bda05a3d9e8..a78eed8ae5f 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -30,6 +30,8 @@ use intrinsics::{i16_mul_with_overflow, u16_mul_with_overflow}; use intrinsics::{i32_mul_with_overflow, u32_mul_with_overflow}; use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow}; +use ::{i8,i16,i32,i64,u8,u16,u32,u64}; + #[unstable(feature = "core", reason = "may be removed, renamed, or relocated")] #[deprecated(since = "1.0.0", reason = "moved to inherent methods")] pub trait WrappingOps { @@ -43,6 +45,12 @@ pub trait OverflowingOps { fn overflowing_add(self, rhs: Self) -> (Self, bool); fn overflowing_sub(self, rhs: Self) -> (Self, bool); fn overflowing_mul(self, rhs: Self) -> (Self, bool); + + fn overflowing_div(self, rhs: Self) -> (Self, bool); + fn overflowing_rem(self, rhs: Self) -> (Self, bool); + + fn overflowing_shl(self, rhs: u32) -> (Self, bool); + fn overflowing_shr(self, rhs: u32) -> (Self, bool); } macro_rules! sh_impl { @@ -184,6 +192,20 @@ macro_rules! wrapping_impl { wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +mod shift_max { + #![allow(non_upper_case_globals)] + + pub const i8: u32 = (1 << 3) - 1; + pub const i16: u32 = (1 << 4) - 1; + pub const i32: u32 = (1 << 5) - 1; + pub const i64: u32 = (1 << 6) - 1; + + pub const u8: u32 = i8; + pub const u16: u32 = i16; + pub const u32: u32 = i32; + pub const u64: u32 = i64; +} + macro_rules! overflowing_impl { ($($t:ident)*) => ($( impl OverflowingOps for $t { @@ -205,6 +227,34 @@ macro_rules! overflowing_impl { concat_idents!($t, _mul_with_overflow)(self, rhs) } } + + #[inline(always)] + fn overflowing_div(self, rhs: $t) -> ($t, bool) { + if self == $t::MIN && rhs == -1 { + (1, true) + } else { + (self/rhs, false) + } + } + #[inline(always)] + fn overflowing_rem(self, rhs: $t) -> ($t, bool) { + if self == $t::MIN && rhs == -1 { + (0, true) + } else { + (self % rhs, false) + } + } + + #[inline(always)] + fn overflowing_shl(self, rhs: u32) -> ($t, bool) { + (self << (rhs & self::shift_max::$t), + (rhs > self::shift_max::$t)) + } + #[inline(always)] + fn overflowing_shr(self, rhs: u32) -> ($t, bool) { + (self >> (rhs & self::shift_max::$t), + (rhs > self::shift_max::$t)) + } } )*) } @@ -234,6 +284,26 @@ impl OverflowingOps for usize { (res.0 as usize, res.1) } } + #[inline(always)] + fn overflowing_div(self, rhs: usize) -> (usize, bool) { + let (r, f) = (self as u64).overflowing_div(rhs as u64); + (r as usize, f) + } + #[inline(always)] + fn overflowing_rem(self, rhs: usize) -> (usize, bool) { + let (r, f) = (self as u64).overflowing_rem(rhs as u64); + (r as usize, f) + } + #[inline(always)] + fn overflowing_shl(self, rhs: u32) -> (usize, bool) { + let (r, f) = (self as u64).overflowing_shl(rhs); + (r as usize, f) + } + #[inline(always)] + fn overflowing_shr(self, rhs: u32) -> (usize, bool) { + let (r, f) = (self as u64).overflowing_shr(rhs); + (r as usize, f) + } } #[cfg(target_pointer_width = "32")] @@ -259,6 +329,26 @@ impl OverflowingOps for usize { (res.0 as usize, res.1) } } + #[inline(always)] + fn overflowing_div(self, rhs: usize) -> (usize, bool) { + let (r, f) = (self as u32).overflowing_div(rhs as u32); + (r as usize, f) + } + #[inline(always)] + fn overflowing_rem(self, rhs: usize) -> (usize, bool) { + let (r, f) = (self as u32).overflowing_rem(rhs as u32); + (r as usize, f) + } + #[inline(always)] + fn overflowing_shl(self, rhs: u32) -> (usize, bool) { + let (r, f) = (self as u32).overflowing_shl(rhs); + (r as usize, f) + } + #[inline(always)] + fn overflowing_shr(self, rhs: u32) -> (usize, bool) { + let (r, f) = (self as u32).overflowing_shr(rhs); + (r as usize, f) + } } #[cfg(target_pointer_width = "64")] @@ -284,6 +374,26 @@ impl OverflowingOps for isize { (res.0 as isize, res.1) } } + #[inline(always)] + fn overflowing_div(self, rhs: isize) -> (isize, bool) { + let (r, f) = (self as i64).overflowing_div(rhs as i64); + (r as isize, f) + } + #[inline(always)] + fn overflowing_rem(self, rhs: isize) -> (isize, bool) { + let (r, f) = (self as i64).overflowing_rem(rhs as i64); + (r as isize, f) + } + #[inline(always)] + fn overflowing_shl(self, rhs: u32) -> (isize, bool) { + let (r, f) = (self as i64).overflowing_shl(rhs); + (r as isize, f) + } + #[inline(always)] + fn overflowing_shr(self, rhs: u32) -> (isize, bool) { + let (r, f) = (self as i64).overflowing_shr(rhs); + (r as isize, f) + } } #[cfg(target_pointer_width = "32")] @@ -309,4 +419,24 @@ impl OverflowingOps for isize { (res.0 as isize, res.1) } } + #[inline(always)] + fn overflowing_div(self, rhs: isize) -> (isize, bool) { + let (r, f) = (self as i32).overflowing_div(rhs as i32); + (r as isize, f) + } + #[inline(always)] + fn overflowing_rem(self, rhs: isize) -> (isize, bool) { + let (r, f) = (self as i32).overflowing_rem(rhs as i32); + (r as isize, f) + } + #[inline(always)] + fn overflowing_shl(self, rhs: u32) -> (isize, bool) { + let (r, f) = (self as i32).overflowing_shl(rhs); + (r as isize, f) + } + #[inline(always)] + fn overflowing_shr(self, rhs: u32) -> (isize, bool) { + let (r, f) = (self as i32).overflowing_shr(rhs); + (r as isize, f) + } } From 2f7658a52829b8208330401735c1b88638ed44c0 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 26 Mar 2015 10:57:42 +0100 Subject: [PATCH 34/46] Refactored ty::ctxt so node_types mutations must go through ty methods. --- src/librustc/middle/astencode.rs | 4 ++-- src/librustc/middle/ty.rs | 11 +++++++++-- src/librustc_trans/save/mod.rs | 6 +++--- src/librustc_trans/trans/debuginfo.rs | 2 +- src/librustc_typeck/lib.rs | 2 +- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 1ea632d9618..b6061f39233 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1197,7 +1197,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, }) } - if let Some(ty) = tcx.node_types.borrow().get(&id) { + if let Some(ty) = tcx.node_types().get(&id) { rbml_w.tag(c::tag_table_node_type, |rbml_w| { rbml_w.id(id); rbml_w.emit_ty(ecx, *ty); @@ -1884,7 +1884,7 @@ fn decode_side_tables(dcx: &DecodeContext, let ty = val_dsr.read_ty(dcx); debug!("inserting ty for node {}: {}", id, ty_to_string(dcx.tcx, ty)); - dcx.tcx.node_types.borrow_mut().insert(id, ty); + dcx.tcx.node_type_insert(id, ty); } c::tag_table_item_subst => { let item_substs = ty::ItemSubsts { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 2130ec4eb63..2bfc9689ac2 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -68,7 +68,7 @@ use util::nodemap::FnvHashMap; use arena::TypedArena; use std::borrow::{Borrow, Cow}; -use std::cell::{Cell, RefCell}; +use std::cell::{Cell, RefCell, Ref}; use std::cmp; use std::fmt; use std::hash::{Hash, SipHasher, Hasher}; @@ -689,7 +689,7 @@ pub struct ctxt<'tcx> { /// Stores the types for various nodes in the AST. Note that this table /// is not guaranteed to be populated until after typeck. See /// typeck::check::fn_ctxt for details. - pub node_types: RefCell>>, + node_types: RefCell>>, /// Stores the type parameters which were substituted to obtain the type /// of this node. This only applies to nodes that refer to entities @@ -854,6 +854,13 @@ pub struct ctxt<'tcx> { pub const_qualif_map: RefCell>, } +impl<'tcx> ctxt<'tcx> { + pub fn node_types(&self) -> Ref>> { self.node_types.borrow() } + pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) { + self.node_types.borrow_mut().insert(id, ty); + } +} + // Flags that we track on types. These flags are propagated upwards // through the type during type construction, so that we can quickly // check whether the type has various kinds of types in it without diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index a415875d852..26fcf947e4f 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -272,7 +272,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { let typ = ppaux::ty_to_string( &self.analysis.ty_cx, - *self.analysis.ty_cx.node_types.borrow().get(&id).unwrap()); + *self.analysis.ty_cx.node_types().get(&id).unwrap()); // get the span only for the name of the variable (I hope the path is only ever a // variable name, but who knows?) self.fmt.formal_str(p.span, @@ -436,7 +436,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { let typ = ppaux::ty_to_string( &self.analysis.ty_cx, - *self.analysis.ty_cx.node_types.borrow().get(&field.node.id).unwrap()); + *self.analysis.ty_cx.node_types().get(&field.node.id).unwrap()); match self.span.sub_span_before_token(field.span, token::Colon) { Some(sub_span) => self.fmt.field_str(field.span, Some(sub_span), @@ -1471,7 +1471,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { for &(id, ref p, ref immut, _) in &self.collected_paths { let value = if *immut { value.to_string() } else { "".to_string() }; - let types = self.analysis.ty_cx.node_types.borrow(); + let types = self.analysis.ty_cx.node_types(); let typ = ppaux::ty_to_string(&self.analysis.ty_cx, *types.get(&id).unwrap()); // Get the span only for the name of the variable (I hope the path // is only ever a variable name, but who knows?). diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index f2c24501c66..8e9ae2eba0b 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -3207,7 +3207,7 @@ fn fn_should_be_ignored(fcx: &FunctionContext) -> bool { fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_reporting_span: Span) { - if !cx.tcx().node_types.borrow().contains_key(&node_id) { + if !cx.tcx().node_types().contains_key(&node_id) { cx.sess().span_bug(error_reporting_span, "debuginfo: Could not find type for node id!"); } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 91410fa808c..9d6c04b1ad4 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -146,7 +146,7 @@ pub struct CrateCtxt<'a, 'tcx: 'a> { fn write_ty_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) { debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_string(tcx, ty)); assert!(!ty::type_needs_infer(ty)); - tcx.node_types.borrow_mut().insert(node_id, ty); + tcx.node_type_insert(node_id, ty); } fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, From 7875dae83fac23fdf59765eb548c2237850d6b15 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Sat, 28 Mar 2015 18:47:08 +0100 Subject: [PATCH 35/46] ty.rs improve error feedback when const-eval errs during repeat count eval. --- src/librustc/middle/ty.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 2bfc9689ac2..87d17cbc04f 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6047,19 +6047,20 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> usize { "expected positive integer for repeat count, found {}", found); } - Err(_) => { + Err(err) => { + let err_description = err.description(); let found = match count_expr.node { ast::ExprPath(None, ast::Path { global: false, ref segments, .. }) if segments.len() == 1 => - "variable", + format!("{}", "found variable"), _ => - "non-constant expression" + format!("but {}", err_description), }; span_err!(tcx.sess, count_expr.span, E0307, - "expected constant integer for repeat count, found {}", + "expected constant integer for repeat count, {}", found); } } From 2e93e386fd228176aeb1100bfdf961bdae2b51b9 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 27 Mar 2015 01:37:10 +0100 Subject: [PATCH 36/46] rust_llvm: Add way to reflectively ask if a ValueRef is a known constant int. Add option-returning variants to `const_to_int`/`const_to_uint` that never assert fail. (These will be used for overflow checking from rustc_trans::trans::consts.) --- src/librustc_llvm/lib.rs | 1 + src/librustc_trans/trans/common.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index c7b5b2e7534..2c4305d3c45 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -1976,6 +1976,7 @@ extern { pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef; pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef; + pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef; pub fn LLVMInitializeX86TargetInfo(); pub fn LLVMInitializeX86Target(); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 745098d6e87..995f3caf588 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -963,6 +963,32 @@ pub fn const_to_uint(v: ValueRef) -> u64 { } } +fn is_const_integral(v: ValueRef) -> bool { + unsafe { + !llvm::LLVMIsAConstantInt(v).is_null() + } +} + +pub fn const_to_opt_int(v: ValueRef) -> Option { + unsafe { + if is_const_integral(v) { + Some(llvm::LLVMConstIntGetSExtValue(v)) + } else { + None + } + } +} + +pub fn const_to_opt_uint(v: ValueRef) -> Option { + unsafe { + if is_const_integral(v) { + Some(llvm::LLVMConstIntGetZExtValue(v)) + } else { + None + } + } +} + pub fn is_undef(val: ValueRef) -> bool { unsafe { llvm::LLVMIsUndef(val) != False From b02f7d2faceac576760f9cd1bd49153b37172479 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 25 Mar 2015 11:10:09 +0100 Subject: [PATCH 37/46] rustc::middle::const_eval : add overflow-checking for {+, -, *}. The overflow-checking attempts to accommodate early evaluation where we do not have type information yet. Also, add fixme note about something that has been bothering me. --- src/librustc/middle/const_eval.rs | 390 +++++++++++++++++++++++------- 1 file changed, 303 insertions(+), 87 deletions(-) diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 173358d336b..e3e5efc53c7 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -13,6 +13,8 @@ pub use self::const_val::*; +use self::ErrKind::*; + use metadata::csearch; use middle::{astencode, def}; use middle::pat_util::def_to_path; @@ -27,6 +29,7 @@ use syntax::{ast_map, ast_util, codemap}; use std::borrow::{Cow, IntoCow}; use std::num::wrapping::OverflowingOps; +use std::num::ToPrimitive; use std::cmp::Ordering; use std::collections::hash_map::Entry::Vacant; use std::{i8, i16, i32, i64}; @@ -234,6 +237,7 @@ pub enum ErrKind { NotOnStruct, NotOnTuple, + NegateWithOverflow(i64), AddiWithOverflow(i64, i64), SubiWithOverflow(i64, i64), MuliWithOverflow(i64, i64), @@ -244,6 +248,8 @@ pub enum ErrKind { DivideWithOverflow, ModuloByZero, ModuloWithOverflow, + ShiftLeftWithOverflow, + ShiftRightWithOverflow, MissingStructField, NonConstPath, ExpectedConstTuple, @@ -257,6 +263,7 @@ pub enum ErrKind { impl ConstEvalErr { pub fn description(&self) -> Cow { use self::ErrKind::*; + match self.kind { CannotCast => "can't cast this type".into_cow(), CannotCastTo(s) => format!("can't cast this type to {}", s).into_cow(), @@ -275,6 +282,7 @@ impl ConstEvalErr { NotOnStruct => "not on struct".into_cow(), NotOnTuple => "not on tuple".into_cow(), + NegateWithOverflow(..) => "attempted to negate with overflow".into_cow(), AddiWithOverflow(..) => "attempted to add with overflow".into_cow(), SubiWithOverflow(..) => "attempted to sub with overflow".into_cow(), MuliWithOverflow(..) => "attempted to mul with overflow".into_cow(), @@ -285,6 +293,8 @@ impl ConstEvalErr { DivideWithOverflow => "attempted to divide with overflow".into_cow(), ModuloByZero => "attempted remainder with a divisor of zero".into_cow(), ModuloWithOverflow => "attempted remainder with overflow".into_cow(), + ShiftLeftWithOverflow => "attempted left shift with overflow".into_cow(), + ShiftRightWithOverflow => "attempted right shift with overflow".into_cow(), MissingStructField => "nonexistent struct field".into_cow(), NonConstPath => "non-constant path in constant expr".into_cow(), ExpectedConstTuple => "expected constant tuple".into_cow(), @@ -297,57 +307,294 @@ impl ConstEvalErr { } } -macro_rules! signal { - ($e:expr, $ctor:ident) => { - return Err(ConstEvalErr { span: $e.span, kind: ErrKind::$ctor }) - }; +pub type EvalResult = Result; +pub type CastResult = Result; - ($e:expr, $ctor:ident($($arg:expr),*)) => { - return Err(ConstEvalErr { span: $e.span, kind: ErrKind::$ctor($($arg),*) }) +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum IntTy { I8, I16, I32, I64 } +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum UintTy { U8, U16, U32, U64 } + +impl IntTy { + pub fn from(tcx: &ty::ctxt, t: ast::IntTy) -> IntTy { + let t = if let ast::TyIs = t { + tcx.sess.target.int_type + } else { + t + }; + match t { + ast::TyIs => unreachable!(), + ast::TyI8 => IntTy::I8, + ast::TyI16 => IntTy::I16, + ast::TyI32 => IntTy::I32, + ast::TyI64 => IntTy::I64, + } } } -fn checked_add_int(e: &Expr, a: i64, b: i64) -> Result { - let (ret, oflo) = a.overflowing_add(b); - if !oflo { Ok(const_int(ret)) } else { signal!(e, AddiWithOverflow(a, b)) } -} -fn checked_sub_int(e: &Expr, a: i64, b: i64) -> Result { - let (ret, oflo) = a.overflowing_sub(b); - if !oflo { Ok(const_int(ret)) } else { signal!(e, SubiWithOverflow(a, b)) } -} -fn checked_mul_int(e: &Expr, a: i64, b: i64) -> Result { - let (ret, oflo) = a.overflowing_mul(b); - if !oflo { Ok(const_int(ret)) } else { signal!(e, MuliWithOverflow(a, b)) } +impl UintTy { + pub fn from(tcx: &ty::ctxt, t: ast::UintTy) -> UintTy { + let t = if let ast::TyUs = t { + tcx.sess.target.uint_type + } else { + t + }; + match t { + ast::TyUs => unreachable!(), + ast::TyU8 => UintTy::U8, + ast::TyU16 => UintTy::U16, + ast::TyU32 => UintTy::U32, + ast::TyU64 => UintTy::U64, + } + } } -fn checked_add_uint(e: &Expr, a: u64, b: u64) -> Result { - let (ret, oflo) = a.overflowing_add(b); - if !oflo { Ok(const_uint(ret)) } else { signal!(e, AdduWithOverflow(a, b)) } -} -fn checked_sub_uint(e: &Expr, a: u64, b: u64) -> Result { - let (ret, oflo) = a.overflowing_sub(b); - if !oflo { Ok(const_uint(ret)) } else { signal!(e, SubuWithOverflow(a, b)) } -} -fn checked_mul_uint(e: &Expr, a: u64, b: u64) -> Result { - let (ret, oflo) = a.overflowing_mul(b); - if !oflo { Ok(const_uint(ret)) } else { signal!(e, MuluWithOverflow(a, b)) } +macro_rules! signal { + ($e:expr, $exn:expr) => { + return Err(ConstEvalErr { span: $e.span, kind: $exn }) + } } +// The const_{int,uint}_checked_{neg,add,sub,mul,div,shl,shr} family +// of functions catch and signal overflow errors during constant +// evaluation. +// +// They all take the operator's arguments (`a` and `b` if binary), the +// overall expression (`e`) and, if available, whole expression's +// concrete type (`opt_ety`). +// +// If the whole expression's concrete type is None, then this is a +// constant evaluation happening before type check (e.g. in the check +// to confirm that a pattern range's left-side is not greater than its +// right-side). We do not do arithmetic modulo the type's bitwidth in +// such a case; we just do 64-bit arithmetic and assume that later +// passes will do it again with the type information, and thus do the +// overflow checks then. + +pub fn const_int_checked_neg<'a>( + a: i64, e: &'a Expr, opt_ety: Option) -> EvalResult { + + let (min,max) = match opt_ety { + // (-i8::MIN is itself not an i8, etc, but this is an easy way + // to allow literals to pass the check. Of course that does + // not work for i64::MIN.) + Some(IntTy::I8) => (-(i8::MAX as i64), -(i8::MIN as i64)), + Some(IntTy::I16) => (-(i16::MAX as i64), -(i16::MIN as i64)), + Some(IntTy::I32) => (-(i32::MAX as i64), -(i32::MIN as i64)), + None | Some(IntTy::I64) => (-i64::MAX, -(i64::MIN+1)), + }; + + let oflo = a < min || a > max; + if oflo { + signal!(e, NegateWithOverflow(a)); + } else { + Ok(const_int(-a)) + } +} + +pub fn const_uint_checked_neg<'a>( + a: u64, _e: &'a Expr, _opt_ety: Option) -> EvalResult { + // This always succeeds, and by definition, returns `(!a)+1`. + Ok(const_uint(-a)) +} + +macro_rules! overflow_checking_body { + ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident, + lhs: $to_8_lhs:ident $to_16_lhs:ident $to_32_lhs:ident, + rhs: $to_8_rhs:ident $to_16_rhs:ident $to_32_rhs:ident $to_64_rhs:ident, + $EnumTy:ident $T8: ident $T16: ident $T32: ident $T64: ident, + $result_type: ident) => { { + let (a,b,opt_ety) = ($a,$b,$ety); + match opt_ety { + Some($EnumTy::$T8) => match (a.$to_8_lhs(), b.$to_8_rhs()) { + (Some(a), Some(b)) => { + let (a, oflo) = a.$overflowing_op(b); + (a as $result_type, oflo) + } + (None, _) | (_, None) => (0, true) + }, + Some($EnumTy::$T16) => match (a.$to_16_lhs(), b.$to_16_rhs()) { + (Some(a), Some(b)) => { + let (a, oflo) = a.$overflowing_op(b); + (a as $result_type, oflo) + } + (None, _) | (_, None) => (0, true) + }, + Some($EnumTy::$T32) => match (a.$to_32_lhs(), b.$to_32_rhs()) { + (Some(a), Some(b)) => { + let (a, oflo) = a.$overflowing_op(b); + (a as $result_type, oflo) + } + (None, _) | (_, None) => (0, true) + }, + None | Some($EnumTy::$T64) => match b.$to_64_rhs() { + Some(b) => a.$overflowing_op(b), + None => (0, true), + } + } + } } +} + +macro_rules! int_arith_body { + ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => { + overflow_checking_body!( + $a, $b, $ety, $overflowing_op, + lhs: to_i8 to_i16 to_i32, + rhs: to_i8 to_i16 to_i32 to_i64, IntTy I8 I16 I32 I64, i64) + } +} + +macro_rules! uint_arith_body { + ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => { + overflow_checking_body!( + $a, $b, $ety, $overflowing_op, + lhs: to_u8 to_u16 to_u32, + rhs: to_u8 to_u16 to_u32 to_u64, UintTy U8 U16 U32 U64, u64) + } +} + +macro_rules! int_shift_body { + ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => { + overflow_checking_body!( + $a, $b, $ety, $overflowing_op, + lhs: to_i8 to_i16 to_i32, + rhs: to_u32 to_u32 to_u32 to_u32, IntTy I8 I16 I32 I64, i64) + } +} + +macro_rules! uint_shift_body { + ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => { + overflow_checking_body!( + $a, $b, $ety, $overflowing_op, + lhs: to_u8 to_u16 to_u32, + rhs: to_u32 to_u32 to_u32 to_u32, UintTy U8 U16 U32 U64, u64) + } +} + +macro_rules! pub_fn_checked_op { + {$fn_name:ident ($a:ident : $a_ty:ty, $b:ident : $b_ty:ty,.. $WhichTy:ident) { + $ret_oflo_body:ident $overflowing_op:ident + $const_ty:ident $signal_exn:expr + }} => { + pub fn $fn_name<'a>($a: $a_ty, + $b: $b_ty, + e: &'a Expr, + opt_ety: Option<$WhichTy>) -> EvalResult { + let (ret, oflo) = $ret_oflo_body!($a, $b, opt_ety, $overflowing_op); + if !oflo { Ok($const_ty(ret)) } else { signal!(e, $signal_exn) } + } + } +} + +pub_fn_checked_op!{ const_int_checked_add(a: i64, b: i64,.. IntTy) { + int_arith_body overflowing_add const_int AddiWithOverflow(a, b) +}} + +pub_fn_checked_op!{ const_int_checked_sub(a: i64, b: i64,.. IntTy) { + int_arith_body overflowing_sub const_int SubiWithOverflow(a, b) +}} + +pub_fn_checked_op!{ const_int_checked_mul(a: i64, b: i64,.. IntTy) { + int_arith_body overflowing_mul const_int MuliWithOverflow(a, b) +}} + +pub fn const_int_checked_div<'a>( + a: i64, b: i64, e: &'a Expr, opt_ety: Option) -> EvalResult { + if b == 0 { signal!(e, DivideByZero); } + let (ret, oflo) = int_arith_body!(a, b, opt_ety, overflowing_div); + if !oflo { Ok(const_int(ret)) } else { signal!(e, DivideWithOverflow) } +} + +pub fn const_int_checked_rem<'a>( + a: i64, b: i64, e: &'a Expr, opt_ety: Option) -> EvalResult { + if b == 0 { signal!(e, ModuloByZero); } + let (ret, oflo) = int_arith_body!(a, b, opt_ety, overflowing_rem); + if !oflo { Ok(const_int(ret)) } else { signal!(e, ModuloWithOverflow) } +} + +pub_fn_checked_op!{ const_int_checked_shl(a: i64, b: i64,.. IntTy) { + int_shift_body overflowing_shl const_int ShiftLeftWithOverflow +}} + +pub_fn_checked_op!{ const_int_checked_shl_via_uint(a: i64, b: u64,.. IntTy) { + int_shift_body overflowing_shl const_int ShiftLeftWithOverflow +}} + +pub_fn_checked_op!{ const_int_checked_shr(a: i64, b: i64,.. IntTy) { + int_shift_body overflowing_shr const_int ShiftRightWithOverflow +}} + +pub_fn_checked_op!{ const_int_checked_shr_via_uint(a: i64, b: u64,.. IntTy) { + int_shift_body overflowing_shr const_int ShiftRightWithOverflow +}} + +pub_fn_checked_op!{ const_uint_checked_add(a: u64, b: u64,.. UintTy) { + uint_arith_body overflowing_add const_uint AdduWithOverflow(a, b) +}} + +pub_fn_checked_op!{ const_uint_checked_sub(a: u64, b: u64,.. UintTy) { + uint_arith_body overflowing_sub const_uint SubuWithOverflow(a, b) +}} + +pub_fn_checked_op!{ const_uint_checked_mul(a: u64, b: u64,.. UintTy) { + uint_arith_body overflowing_mul const_uint MuluWithOverflow(a, b) +}} + +pub fn const_uint_checked_div<'a>( + a: u64, b: u64, e: &'a Expr, opt_ety: Option) -> EvalResult { + if b == 0 { signal!(e, DivideByZero); } + let (ret, oflo) = uint_arith_body!(a, b, opt_ety, overflowing_div); + if !oflo { Ok(const_uint(ret)) } else { signal!(e, DivideWithOverflow) } +} + +pub fn const_uint_checked_rem<'a>( + a: u64, b: u64, e: &'a Expr, opt_ety: Option) -> EvalResult { + if b == 0 { signal!(e, ModuloByZero); } + let (ret, oflo) = uint_arith_body!(a, b, opt_ety, overflowing_rem); + if !oflo { Ok(const_uint(ret)) } else { signal!(e, ModuloWithOverflow) } +} + +pub_fn_checked_op!{ const_uint_checked_shl(a: u64, b: u64,.. UintTy) { + uint_shift_body overflowing_shl const_uint ShiftLeftWithOverflow +}} + +pub_fn_checked_op!{ const_uint_checked_shl_via_int(a: u64, b: i64,.. UintTy) { + uint_shift_body overflowing_shl const_uint ShiftLeftWithOverflow +}} + +pub_fn_checked_op!{ const_uint_checked_shr(a: u64, b: u64,.. UintTy) { + uint_shift_body overflowing_shr const_uint ShiftRightWithOverflow +}} + +pub_fn_checked_op!{ const_uint_checked_shr_via_int(a: u64, b: i64,.. UintTy) { + uint_shift_body overflowing_shr const_uint ShiftRightWithOverflow +}} pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, e: &Expr, - ty_hint: Option>) - -> Result { + ty_hint: Option>) -> EvalResult { fn fromb(b: bool) -> const_val { const_int(b as i64) } let ety = ty_hint.or_else(|| ty::expr_ty_opt(tcx, e)); + // If type of expression itself is int or uint, normalize in these + // bindings so that isize/usize is mapped to a type with an + // inherently known bitwidth. + let expr_int_type = ety.and_then(|ty| { + if let ty::ty_int(t) = ty.sty { + Some(IntTy::from(tcx, t)) } else { None } + }); + let expr_uint_type = ety.and_then(|ty| { + if let ty::ty_uint(t) = ty.sty { + Some(UintTy::from(tcx, t)) } else { None } + }); + let result = match e.node { ast::ExprUnary(ast::UnNeg, ref inner) => { match try!(eval_const_expr_partial(tcx, &**inner, ety)) { const_float(f) => const_float(-f), - const_int(i) => const_int(-i), - const_uint(i) => const_uint(-i), + const_int(n) => try!(const_int_checked_neg(n, e, expr_int_type)), + const_uint(n) => try!(const_uint_checked_neg(n, e, expr_uint_type)), const_str(_) => signal!(e, NegateOnString), const_bool(_) => signal!(e, NegateOnBoolean), const_binary(_) => signal!(e, NegateOnBinary), @@ -391,51 +638,17 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, } } (const_int(a), const_int(b)) => { - let is_a_min_value = || { - let int_ty = match ty::expr_ty_opt(tcx, e).map(|ty| &ty.sty) { - Some(&ty::ty_int(int_ty)) => int_ty, - _ => return false - }; - let int_ty = if let ast::TyIs = int_ty { - tcx.sess.target.int_type - } else { - int_ty - }; - match int_ty { - ast::TyI8 => (a as i8) == i8::MIN, - ast::TyI16 => (a as i16) == i16::MIN, - ast::TyI32 => (a as i32) == i32::MIN, - ast::TyI64 => (a as i64) == i64::MIN, - ast::TyIs => unreachable!() - } - }; match op.node { - ast::BiAdd => try!(checked_add_int(e, a, b)), - ast::BiSub => try!(checked_sub_int(e, a, b)), - ast::BiMul => try!(checked_mul_int(e, a, b)), - ast::BiDiv => { - if b == 0 { - signal!(e, DivideByZero); - } else if b == -1 && is_a_min_value() { - signal!(e, DivideWithOverflow); - } else { - const_int(a / b) - } - } - ast::BiRem => { - if b == 0 { - signal!(e, ModuloByZero) - } else if b == -1 && is_a_min_value() { - signal!(e, ModuloWithOverflow) - } else { - const_int(a % b) - } - } + ast::BiAdd => try!(const_int_checked_add(a,b,e,expr_int_type)), + ast::BiSub => try!(const_int_checked_sub(a,b,e,expr_int_type)), + ast::BiMul => try!(const_int_checked_mul(a,b,e,expr_int_type)), + ast::BiDiv => try!(const_int_checked_div(a,b,e,expr_int_type)), + ast::BiRem => try!(const_int_checked_rem(a,b,e,expr_int_type)), ast::BiAnd | ast::BiBitAnd => const_int(a & b), ast::BiOr | ast::BiBitOr => const_int(a | b), ast::BiBitXor => const_int(a ^ b), - ast::BiShl => const_int(a << b as usize), - ast::BiShr => const_int(a >> b as usize), + ast::BiShl => try!(const_int_checked_shl(a,b,e,expr_int_type)), + ast::BiShr => try!(const_int_checked_shr(a,b,e,expr_int_type)), ast::BiEq => fromb(a == b), ast::BiLt => fromb(a < b), ast::BiLe => fromb(a <= b), @@ -446,18 +659,16 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, } (const_uint(a), const_uint(b)) => { match op.node { - ast::BiAdd => try!(checked_add_uint(e, a, b)), - ast::BiSub => try!(checked_sub_uint(e, a, b)), - ast::BiMul => try!(checked_mul_uint(e, a, b)), - ast::BiDiv if b == 0 => signal!(e, DivideByZero), - ast::BiDiv => const_uint(a / b), - ast::BiRem if b == 0 => signal!(e, ModuloByZero), - ast::BiRem => const_uint(a % b), + ast::BiAdd => try!(const_uint_checked_add(a,b,e,expr_uint_type)), + ast::BiSub => try!(const_uint_checked_sub(a,b,e,expr_uint_type)), + ast::BiMul => try!(const_uint_checked_mul(a,b,e,expr_uint_type)), + ast::BiDiv => try!(const_uint_checked_div(a,b,e,expr_uint_type)), + ast::BiRem => try!(const_uint_checked_rem(a,b,e,expr_uint_type)), ast::BiAnd | ast::BiBitAnd => const_uint(a & b), ast::BiOr | ast::BiBitOr => const_uint(a | b), ast::BiBitXor => const_uint(a ^ b), - ast::BiShl => const_uint(a << b as usize), - ast::BiShr => const_uint(a >> b as usize), + ast::BiShl => try!(const_uint_checked_shl(a,b,e,expr_uint_type)), + ast::BiShr => try!(const_uint_checked_shr(a,b,e,expr_uint_type)), ast::BiEq => fromb(a == b), ast::BiLt => fromb(a < b), ast::BiLe => fromb(a <= b), @@ -469,15 +680,15 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, // shifts can have any integral type as their rhs (const_int(a), const_uint(b)) => { match op.node { - ast::BiShl => const_int(a << b as usize), - ast::BiShr => const_int(a >> b as usize), + ast::BiShl => try!(const_int_checked_shl_via_uint(a,b,e,expr_int_type)), + ast::BiShr => try!(const_int_checked_shr_via_uint(a,b,e,expr_int_type)), _ => signal!(e, InvalidOpForIntUint(op.node)), } } (const_uint(a), const_int(b)) => { match op.node { - ast::BiShl => const_uint(a << b as usize), - ast::BiShr => const_uint(a >> b as usize), + ast::BiShl => try!(const_uint_checked_shl_via_int(a,b,e,expr_uint_type)), + ast::BiShr => try!(const_uint_checked_shr_via_int(a,b,e,expr_uint_type)), _ => signal!(e, InvalidOpForUintInt(op.node)), } } @@ -506,7 +717,12 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, tcx.sess.span_fatal(target_ty.span, "target type not found for const cast") }); + // Prefer known type to noop, but always have a type hint. + // + // FIXME (#23833): the type-hint can cause problems, + // e.g. `(i8::MAX + 1_i8) as u32` feeds in `u32` as result + // type to the sum, and thus no overflow is signaled. let base_hint = ty::expr_ty_opt(tcx, &**base).unwrap_or(ety); let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint))); match cast_const(tcx, val, ety) { @@ -607,7 +823,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, Ok(result) } -fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, ty: Ty) -> Result { +fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, ty: Ty) -> CastResult { macro_rules! convert_val { ($intermediate_ty:ty, $const_type:ident, $target_ty:ty) => { match val { From 6808e414c7b29bfb066c1bbabff684bde1190a4e Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 27 Mar 2015 14:25:48 +0100 Subject: [PATCH 38/46] rustc_trans::trans::consts add overflow checking --- src/librustc_trans/trans/consts.rs | 129 +++++++++++++++++++++++++++-- 1 file changed, 124 insertions(+), 5 deletions(-) diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 0a9df2b5dc1..cf4675cbe46 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -14,6 +14,14 @@ use llvm; use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr}; use llvm::{InternalLinkage, ValueRef, Bool, True}; use middle::{check_const, const_eval, def}; +use middle::const_eval::{const_int_checked_neg, const_uint_checked_neg}; +use middle::const_eval::{const_int_checked_add, const_uint_checked_add}; +use middle::const_eval::{const_int_checked_sub, const_uint_checked_sub}; +use middle::const_eval::{const_int_checked_mul, const_uint_checked_mul}; +use middle::const_eval::{const_int_checked_div, const_uint_checked_div}; +use middle::const_eval::{const_int_checked_rem, const_uint_checked_rem}; +use middle::const_eval::{const_int_checked_shl, const_uint_checked_shl}; +use middle::const_eval::{const_int_checked_shr, const_uint_checked_shr}; use trans::{adt, closure, debuginfo, expr, inline, machine}; use trans::base::{self, push_ctxt}; use trans::common::*; @@ -336,6 +344,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let csize = machine::llsize_of_alloc(cx, val_ty(llconst)); let tsize = machine::llsize_of_alloc(cx, llty); if csize != tsize { + cx.sess().abort_if_errors(); unsafe { // FIXME these values could use some context llvm::LLVMDumpValue(llconst); @@ -348,6 +357,100 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, (llconst, ety_adjusted) } +fn check_unary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty, + te: ValueRef) { + // The only kind of unary expression that we check for validity + // here is `-expr`, to check if it "overflows" (e.g. `-i32::MIN`). + if let ast::ExprUnary(ast::UnNeg, ref inner_e) = e.node { + + // An unfortunate special case: we parse e.g. -128 as a + // negation of the literal 128, which means if we're expecting + // a i8 (or if it was already suffixed, e.g. `-128_i8`), then + // 128 will have already overflowed to -128, and so then the + // constant evaluator thinks we're trying to negate -128. + // + // Catch this up front by looking for ExprLit directly, + // and just accepting it. + if let ast::ExprLit(_) = inner_e.node { return; } + + let result = match t.sty { + ty::ty_int(int_type) => { + let input = match const_to_opt_int(te) { + Some(v) => v, + None => return, + }; + const_int_checked_neg( + input, e, Some(const_eval::IntTy::from(cx.tcx(), int_type))) + } + ty::ty_uint(uint_type) => { + let input = match const_to_opt_uint(te) { + Some(v) => v, + None => return, + }; + const_uint_checked_neg( + input, e, Some(const_eval::UintTy::from(cx.tcx(), uint_type))) + } + _ => return, + }; + + // We do not actually care about a successful result. + if let Err(err) = result { + cx.tcx().sess.span_err(e.span, &err.description()); + } + } +} + +fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty, + te1: ValueRef, te2: ValueRef) { + let b = if let ast::ExprBinary(b, _, _) = e.node { b } else { return }; + + let result = match t.sty { + ty::ty_int(int_type) => { + let (lhs, rhs) = match (const_to_opt_int(te1), + const_to_opt_int(te2)) { + (Some(v1), Some(v2)) => (v1, v2), + _ => return, + }; + + let opt_ety = Some(const_eval::IntTy::from(cx.tcx(), int_type)); + match b.node { + ast::BiAdd => const_int_checked_add(lhs, rhs, e, opt_ety), + ast::BiSub => const_int_checked_sub(lhs, rhs, e, opt_ety), + ast::BiMul => const_int_checked_mul(lhs, rhs, e, opt_ety), + ast::BiDiv => const_int_checked_div(lhs, rhs, e, opt_ety), + ast::BiRem => const_int_checked_rem(lhs, rhs, e, opt_ety), + ast::BiShl => const_int_checked_shl(lhs, rhs, e, opt_ety), + ast::BiShr => const_int_checked_shr(lhs, rhs, e, opt_ety), + _ => return, + } + } + ty::ty_uint(uint_type) => { + let (lhs, rhs) = match (const_to_opt_uint(te1), + const_to_opt_uint(te2)) { + (Some(v1), Some(v2)) => (v1, v2), + _ => return, + }; + + let opt_ety = Some(const_eval::UintTy::from(cx.tcx(), uint_type)); + match b.node { + ast::BiAdd => const_uint_checked_add(lhs, rhs, e, opt_ety), + ast::BiSub => const_uint_checked_sub(lhs, rhs, e, opt_ety), + ast::BiMul => const_uint_checked_mul(lhs, rhs, e, opt_ety), + ast::BiDiv => const_uint_checked_div(lhs, rhs, e, opt_ety), + ast::BiRem => const_uint_checked_rem(lhs, rhs, e, opt_ety), + ast::BiShl => const_uint_checked_shl(lhs, rhs, e, opt_ety), + ast::BiShr => const_uint_checked_shr(lhs, rhs, e, opt_ety), + _ => return, + } + } + _ => return, + }; + // We do not actually care about a successful result. + if let Err(err) = result { + cx.tcx().sess.span_err(e.span, &err.description()); + } +} + fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr, ety: Ty<'tcx>, @@ -386,7 +489,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let signed = ty::type_is_signed(intype); let (te2, _) = const_expr(cx, &**e2, param_substs); - let te2 = base::cast_shift_const_rhs(b.node, te1, te2); + + check_binary_expr_validity(cx, e, ty, te1, te2); match b.node { ast::BiAdd => { @@ -416,8 +520,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ast::BiBitXor => llvm::LLVMConstXor(te1, te2), ast::BiBitAnd => llvm::LLVMConstAnd(te1, te2), ast::BiBitOr => llvm::LLVMConstOr(te1, te2), - ast::BiShl => llvm::LLVMConstShl(te1, te2), + ast::BiShl => { + let te2 = base::cast_shift_const_rhs(b.node, te1, te2); + llvm::LLVMConstShl(te1, te2) + } ast::BiShr => { + let te2 = base::cast_shift_const_rhs(b.node, te1, te2); if signed { llvm::LLVMConstAShr(te1, te2) } else { llvm::LLVMConstLShr(te1, te2) } } @@ -439,8 +547,11 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } }, - ast::ExprUnary(u, ref e) => { - let (te, ty) = const_expr(cx, &**e, param_substs); + ast::ExprUnary(u, ref inner_e) => { + let (te, ty) = const_expr(cx, &**inner_e, param_substs); + + check_unary_expr_validity(cx, e, ty, te); + let is_float = ty::type_is_fp(ty); match u { ast::UnUniq | ast::UnDeref => { @@ -664,7 +775,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let n = match const_eval::eval_const_expr_partial(cx.tcx(), &**count, None) { Ok(const_eval::const_int(i)) => i as usize, Ok(const_eval::const_uint(i)) => i as usize, - _ => cx.sess().span_bug(count.span, "count must be integral const expression.") + Ok(_) => { + cx.sess().span_bug(count.span, "count must be integral const expression.") + } + Err(err) => { + cx.sess().span_err(count.span, &format!("error evaluating count: {}", + err.description())); + // return 1 to allow compilation to proceed + 1 as usize + } }; let unit_val = const_expr(cx, &**elem, param_substs).0; let vs: Vec<_> = repeat(unit_val).take(n).collect(); From 8d54ea3ec9c48eaeaab8fa9061cf28c2678e8ae9 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 30 Mar 2015 01:23:15 +0200 Subject: [PATCH 39/46] Fallout from changes for overflow-checking during constant evaluation. --- src/libcoretest/num/uint_macros.rs | 2 +- src/libstd/old_io/extensions.rs | 3 ++- src/test/compile-fail/non-constant-enum-for-vec-repeat.rs | 5 ++++- src/test/compile-fail/non-constant-expr-for-vec-repeat.rs | 3 ++- src/test/run-pass/big-literals.rs | 7 ++++++- src/test/run-pass/small-enum-range-edge.rs | 4 ++-- 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/libcoretest/num/uint_macros.rs b/src/libcoretest/num/uint_macros.rs index 39e41a4fad3..e3eff6e7512 100644 --- a/src/libcoretest/num/uint_macros.rs +++ b/src/libcoretest/num/uint_macros.rs @@ -20,7 +20,7 @@ mod tests { fn test_overflows() { assert!(MAX > 0); assert!(MIN <= 0); - assert!(MIN + MAX + 1 == 0); + assert!((MIN + MAX).wrapping_add(1) == 0); } #[test] diff --git a/src/libstd/old_io/extensions.rs b/src/libstd/old_io/extensions.rs index 0e5dd3aa4aa..aec794af759 100644 --- a/src/libstd/old_io/extensions.rs +++ b/src/libstd/old_io/extensions.rs @@ -519,7 +519,8 @@ mod bench { ({ use super::u64_from_be_bytes; - let data = (0..$stride*100+$start_index).collect::>(); + let len = $stride.wrapping_mul(100).wrapping_add($start_index); + let data = (0..len).collect::>(); let mut sum = 0; $b.iter(|| { let mut i = $start_index; diff --git a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs index 0212adff305..a7cabae16be 100644 --- a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Note: This test is checking that we forbid a coding pattern that +// Issue #5873 explicitly wants to allow. + enum State { ST_NULL, ST_WHITESPACE } fn main() { [State::ST_NULL; (State::ST_WHITESPACE as usize)]; - //~^ ERROR expected constant integer for repeat count, found non-constant expression + //~^ ERROR expected constant integer for repeat count, but non-constant path } diff --git a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs index 26528543b43..3ce206ff7fb 100644 --- a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs @@ -12,6 +12,7 @@ fn main() { fn bar(n: usize) { - let _x = [0; n]; //~ ERROR expected constant integer for repeat count, found variable + let _x = [0; n]; + //~^ ERROR expected constant integer for repeat count, found variable } } diff --git a/src/test/run-pass/big-literals.rs b/src/test/run-pass/big-literals.rs index 09746380eba..ff13a1345d2 100644 --- a/src/test/run-pass/big-literals.rs +++ b/src/test/run-pass/big-literals.rs @@ -10,11 +10,16 @@ // pretty-expanded FIXME #23616 +#![feature(core)] + +// Catch mistakes in the overflowing literals lint. +#![deny(overflowing_literals)] + pub fn main() { assert_eq!(0xffffffff, (-1 as u32)); assert_eq!(4294967295, (-1 as u32)); assert_eq!(0xffffffffffffffff, (-1 as u64)); assert_eq!(18446744073709551615, (-1 as u64)); - assert_eq!(-2147483648 - 1, 2147483647); + assert_eq!((-2147483648).wrapping_sub(1), 2147483647); } diff --git a/src/test/run-pass/small-enum-range-edge.rs b/src/test/run-pass/small-enum-range-edge.rs index df204065d16..ded66fb86ad 100644 --- a/src/test/run-pass/small-enum-range-edge.rs +++ b/src/test/run-pass/small-enum-range-edge.rs @@ -29,8 +29,8 @@ static CLs: Es = Es::Ls; static CHs: Es = Es::Hs; pub fn main() { - assert_eq!((Eu::Hu as u8) + 1, Eu::Lu as u8); - assert_eq!((Es::Hs as i8) + 1, Es::Ls as i8); + assert_eq!((Eu::Hu as u8).wrapping_add(1), Eu::Lu as u8); + assert_eq!((Es::Hs as i8).wrapping_add(1), Es::Ls as i8); assert_eq!(CLu as u8, Eu::Lu as u8); assert_eq!(CHu as u8, Eu::Hu as u8); assert_eq!(CLs as i8, Es::Ls as i8); From 41b3c86e9a77dcddab417076b607c7b096ac5cfc Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 30 Mar 2015 13:26:02 +0200 Subject: [PATCH 40/46] Test cases for checking arithmetic overflow during const eval. --- .../compile-fail/const-eval-overflow-2.rs | 30 ++++ .../compile-fail/const-eval-overflow-3.rs | 34 +++++ .../compile-fail/const-eval-overflow-3b.rs | 38 ++++++ .../compile-fail/const-eval-overflow-4.rs | 36 +++++ .../compile-fail/const-eval-overflow-4b.rs | 34 +++++ src/test/compile-fail/const-eval-overflow.rs | 129 ++++++++++++++++++ 6 files changed, 301 insertions(+) create mode 100644 src/test/compile-fail/const-eval-overflow-2.rs create mode 100644 src/test/compile-fail/const-eval-overflow-3.rs create mode 100644 src/test/compile-fail/const-eval-overflow-3b.rs create mode 100644 src/test/compile-fail/const-eval-overflow-4.rs create mode 100644 src/test/compile-fail/const-eval-overflow-4b.rs create mode 100644 src/test/compile-fail/const-eval-overflow.rs diff --git a/src/test/compile-fail/const-eval-overflow-2.rs b/src/test/compile-fail/const-eval-overflow-2.rs new file mode 100644 index 00000000000..be04bc9bd3b --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-2.rs @@ -0,0 +1,30 @@ +// 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. + +// Evaluation of constants in refutable patterns goes through +// different compiler control-flow paths. + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const NEG_128: i8 = -128; +const NEG_NEG_128: i8 = -NEG_128; +//~^ ERROR constant evaluation error: attempted to negate with overflow +//~| ERROR attempted to negate with overflow + +fn main() { + match -128i8 { + NEG_NEG_128 => println!("A"), + _ => println!("B"), + } +} diff --git a/src/test/compile-fail/const-eval-overflow-3.rs b/src/test/compile-fail/const-eval-overflow-3.rs new file mode 100644 index 00000000000..df03324e1f7 --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-3.rs @@ -0,0 +1,34 @@ +// 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. + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array expression. + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_I + : [u32; (i8::MAX as usize) + 1] + = [0; (i8::MAX + 1) as usize]; +//~^ ERROR error evaluating count: attempted to add with overflow + +fn main() { + foo(&A_I8_I[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow-3b.rs b/src/test/compile-fail/const-eval-overflow-3b.rs new file mode 100644 index 00000000000..31dcb483c4a --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-3b.rs @@ -0,0 +1,38 @@ +// 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. + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array expression. +// +// This is a variation of another such test, but in this case the +// types for the left- and right-hand sides of the addition do not +// match (as well as overflow). + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_I + : [u32; (i8::MAX as usize) + 1] + = [0; (i8::MAX + 1u8) as usize]; +//~^ ERROR mismatched types + +fn main() { + foo(&A_I8_I[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow-4.rs b/src/test/compile-fail/const-eval-overflow-4.rs new file mode 100644 index 00000000000..f1f125adaa7 --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-4.rs @@ -0,0 +1,36 @@ +// 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-test this should fail to compile (#23833) + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array type. + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_T + : [u32; (i8::MAX as i8 + 1i8) as usize] + //~^ ERROR error evaluating count: attempted to add with overflow + = [0; (i8::MAX as usize) + 1]; + +fn main() { + foo(&A_I8_T[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs new file mode 100644 index 00000000000..ca354ad78ea --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-4b.rs @@ -0,0 +1,34 @@ +// 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. + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array type. + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_T + : [u32; (i8::MAX as i8 + 1u8) as usize] + //~^ ERROR mismatched types + = [0; (i8::MAX as usize) + 1]; + +fn main() { + foo(&A_I8_T[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow.rs b/src/test/compile-fail/const-eval-overflow.rs new file mode 100644 index 00000000000..f647c43e137 --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow.rs @@ -0,0 +1,129 @@ +// 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. + +#![allow(unused_imports)] + +// Note: the relevant lint pass here runs before some of the constant +// evaluation below (e.g. that performed by trans and llvm), so if you +// change this warn to a deny, then the compiler will exit before +// those errors are detected. +#![warn(unsigned_negation)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const VALS_I8: (i8, i8, i8, i8) = + (-i8::MIN, + //~^ ERROR attempted to negate with overflow + i8::MIN - 1, + //~^ ERROR attempted to sub with overflow + i8::MAX + 1, + //~^ ERROR attempted to add with overflow + i8::MIN * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_I16: (i16, i16, i16, i16) = + (-i16::MIN, + //~^ ERROR attempted to negate with overflow + i16::MIN - 1, + //~^ ERROR attempted to sub with overflow + i16::MAX + 1, + //~^ ERROR attempted to add with overflow + i16::MIN * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_I32: (i32, i32, i32, i32) = + (-i32::MIN, + //~^ ERROR attempted to negate with overflow + i32::MIN - 1, + //~^ ERROR attempted to sub with overflow + i32::MAX + 1, + //~^ ERROR attempted to add with overflow + i32::MIN * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_I64: (i64, i64, i64, i64) = + (-i64::MIN, + //~^ ERROR attempted to negate with overflow + i64::MIN - 1, + //~^ ERROR attempted to sub with overflow + i64::MAX + 1, + //~^ ERROR attempted to add with overflow + i64::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U8: (u8, u8, u8, u8) = + (-u8::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u8::MIN - 1, + //~^ ERROR attempted to sub with overflow + u8::MAX + 1, + //~^ ERROR attempted to add with overflow + u8::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U16: (u16, u16, u16, u16) = + (-u16::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u16::MIN - 1, + //~^ ERROR attempted to sub with overflow + u16::MAX + 1, + //~^ ERROR attempted to add with overflow + u16::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U32: (u32, u32, u32, u32) = + (-u32::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u32::MIN - 1, + //~^ ERROR attempted to sub with overflow + u32::MAX + 1, + //~^ ERROR attempted to add with overflow + u32::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U64: (u64, u64, u64, u64) = + (-u64::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u64::MIN - 1, + //~^ ERROR attempted to sub with overflow + u64::MAX + 1, + //~^ ERROR attempted to add with overflow + u64::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +fn main() { + foo(VALS_I8); + foo(VALS_I16); + foo(VALS_I32); + foo(VALS_I64); + + foo(VALS_U8); + foo(VALS_U16); + foo(VALS_U32); + foo(VALS_U64); +} + +fn foo(x: T) { + println!("{:?}", x); +} From 1f5e45b76961d54e3b825c3c6af6b6e02504d2be Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 31 Mar 2015 21:53:12 +0200 Subject: [PATCH 41/46] Include feature `core` to get access to `wrapping_add`. --- src/test/run-pass/small-enum-range-edge.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/run-pass/small-enum-range-edge.rs b/src/test/run-pass/small-enum-range-edge.rs index ded66fb86ad..a87a3072c8a 100644 --- a/src/test/run-pass/small-enum-range-edge.rs +++ b/src/test/run-pass/small-enum-range-edge.rs @@ -10,6 +10,9 @@ // pretty-expanded FIXME #23616 +// this is for the wrapping_add call below. +#![feature(core)] + /*! * Tests the range assertion wraparound case in trans::middle::adt::load_discr. */ From 1973f7ebe5c67ef9ed57f7a64781d13868a70d3d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 1 Apr 2015 00:15:09 +0200 Subject: [PATCH 42/46] Fixes to compile-fail error messages post-rebase. --- src/test/compile-fail/const-eval-overflow-3.rs | 3 ++- src/test/compile-fail/const-eval-overflow-3b.rs | 4 ++++ src/test/compile-fail/const-eval-overflow-4b.rs | 2 ++ src/test/compile-fail/huge-array-simple.rs | 6 ++++-- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/test/compile-fail/const-eval-overflow-3.rs b/src/test/compile-fail/const-eval-overflow-3.rs index df03324e1f7..7d84562c6bd 100644 --- a/src/test/compile-fail/const-eval-overflow-3.rs +++ b/src/test/compile-fail/const-eval-overflow-3.rs @@ -22,7 +22,8 @@ use std::{u8, u16, u32, u64, usize}; const A_I8_I : [u32; (i8::MAX as usize) + 1] = [0; (i8::MAX + 1) as usize]; -//~^ ERROR error evaluating count: attempted to add with overflow +//~^ ERROR mismatched types +//~| ERROR expected constant integer for repeat count, but attempted to add with overflow fn main() { foo(&A_I8_I[..]); diff --git a/src/test/compile-fail/const-eval-overflow-3b.rs b/src/test/compile-fail/const-eval-overflow-3b.rs index 31dcb483c4a..950620fe019 100644 --- a/src/test/compile-fail/const-eval-overflow-3b.rs +++ b/src/test/compile-fail/const-eval-overflow-3b.rs @@ -27,6 +27,10 @@ const A_I8_I : [u32; (i8::MAX as usize) + 1] = [0; (i8::MAX + 1u8) as usize]; //~^ ERROR mismatched types +//~| ERROR mismatched types +//~| ERROR expected constant integer for repeat count, but attempted to add with overflow +//~| ERROR the trait `core::ops::Add` is not implemented for the type `i8` +//~| ERROR the trait `core::ops::Add` is not implemented for the type `i8` fn main() { foo(&A_I8_I[..]); diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs index ca354ad78ea..6322b56a82f 100644 --- a/src/test/compile-fail/const-eval-overflow-4b.rs +++ b/src/test/compile-fail/const-eval-overflow-4b.rs @@ -22,6 +22,8 @@ use std::{u8, u16, u32, u64, usize}; const A_I8_T : [u32; (i8::MAX as i8 + 1u8) as usize] //~^ ERROR mismatched types + //~| the trait `core::ops::Add` is not implemented for the type `i8` + //~| the trait `core::ops::Add` is not implemented for the type `i8` = [0; (i8::MAX as usize) + 1]; fn main() { diff --git a/src/test/compile-fail/huge-array-simple.rs b/src/test/compile-fail/huge-array-simple.rs index 105f885f287..e6446304177 100644 --- a/src/test/compile-fail/huge-array-simple.rs +++ b/src/test/compile-fail/huge-array-simple.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: too big for the current #![allow(exceeding_bitshifts)] fn main() { - let fat : [u8; (1<<61)+(1<<31)] = [0; (1u64<<61) as usize +(1u64<<31) as usize]; + let fat : [u8; (1<<61)+(1<<31)] = + //~^ ERROR array length constant evaluation error: attempted left shift with overflow + [0; (1u64<<61) as usize +(1u64<<31) as usize]; + //~^ ERROR expected constant integer for repeat count, but attempted left shift with overflow } From 2243a2cceddd6c9708e3d296b5375da72a6b3d2a Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 1 Apr 2015 02:40:56 +0200 Subject: [PATCH 43/46] Unify handling of checking repeat-count validity. --- src/librustc_trans/trans/consts.rs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index cf4675cbe46..c32cb28ec78 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -772,19 +772,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ast::ExprRepeat(ref elem, ref count) => { let unit_ty = ty::sequence_element_type(cx.tcx(), ety); let llunitty = type_of::type_of(cx, unit_ty); - let n = match const_eval::eval_const_expr_partial(cx.tcx(), &**count, None) { - Ok(const_eval::const_int(i)) => i as usize, - Ok(const_eval::const_uint(i)) => i as usize, - Ok(_) => { - cx.sess().span_bug(count.span, "count must be integral const expression.") - } - Err(err) => { - cx.sess().span_err(count.span, &format!("error evaluating count: {}", - err.description())); - // return 1 to allow compilation to proceed - 1 as usize - } - }; + let n = ty::eval_repeat_count(cx.tcx(), count); let unit_val = const_expr(cx, &**elem, param_substs).0; let vs: Vec<_> = repeat(unit_val).take(n).collect(); if val_ty(unit_val) != llunitty { From 2a9de1d989d7f95846b711eec2695cbd86794ee3 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 1 Apr 2015 02:51:45 +0200 Subject: [PATCH 44/46] dealing with fallout to the tests, in particular diffs between 32- vs 64-bit targets. See also #23926. --- src/test/compile-fail/const-eval-overflow-3.rs | 8 ++++++-- src/test/compile-fail/const-eval-overflow-3b.rs | 11 ++++++----- src/test/compile-fail/huge-array-simple.rs | 9 ++++++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/test/compile-fail/const-eval-overflow-3.rs b/src/test/compile-fail/const-eval-overflow-3.rs index 7d84562c6bd..c2bc5b2648a 100644 --- a/src/test/compile-fail/const-eval-overflow-3.rs +++ b/src/test/compile-fail/const-eval-overflow-3.rs @@ -13,6 +13,12 @@ // // This test is checking the count in an array expression. +// FIXME (#23926): the error output is not consistent between a +// self-hosted and a cross-compiled setup; therefore resorting to +// error-pattern for now. + +// error-pattern: expected constant integer for repeat count, but attempted to add with overflow + #![allow(unused_imports)] use std::fmt; @@ -22,8 +28,6 @@ use std::{u8, u16, u32, u64, usize}; const A_I8_I : [u32; (i8::MAX as usize) + 1] = [0; (i8::MAX + 1) as usize]; -//~^ ERROR mismatched types -//~| ERROR expected constant integer for repeat count, but attempted to add with overflow fn main() { foo(&A_I8_I[..]); diff --git a/src/test/compile-fail/const-eval-overflow-3b.rs b/src/test/compile-fail/const-eval-overflow-3b.rs index 950620fe019..719b21000f7 100644 --- a/src/test/compile-fail/const-eval-overflow-3b.rs +++ b/src/test/compile-fail/const-eval-overflow-3b.rs @@ -17,6 +17,12 @@ // types for the left- and right-hand sides of the addition do not // match (as well as overflow). +// FIXME (#23926): the error output is not consistent between a +// self-hosted and a cross-compiled setup; therefore resorting to +// error-pattern for now. + +// error-pattern: mismatched types + #![allow(unused_imports)] use std::fmt; @@ -26,11 +32,6 @@ use std::{u8, u16, u32, u64, usize}; const A_I8_I : [u32; (i8::MAX as usize) + 1] = [0; (i8::MAX + 1u8) as usize]; -//~^ ERROR mismatched types -//~| ERROR mismatched types -//~| ERROR expected constant integer for repeat count, but attempted to add with overflow -//~| ERROR the trait `core::ops::Add` is not implemented for the type `i8` -//~| ERROR the trait `core::ops::Add` is not implemented for the type `i8` fn main() { foo(&A_I8_I[..]); diff --git a/src/test/compile-fail/huge-array-simple.rs b/src/test/compile-fail/huge-array-simple.rs index e6446304177..54340cf7ac4 100644 --- a/src/test/compile-fail/huge-array-simple.rs +++ b/src/test/compile-fail/huge-array-simple.rs @@ -8,11 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// FIXME (#23926): the error output is not consistent between a +// self-hosted and a cross-compiled setup. Skipping for now. + +// ignore-test FIXME(#23926) + #![allow(exceeding_bitshifts)] fn main() { - let fat : [u8; (1<<61)+(1<<31)] = - //~^ ERROR array length constant evaluation error: attempted left shift with overflow + let _fat : [u8; (1<<61)+(1<<31)] = [0; (1u64<<61) as usize +(1u64<<31) as usize]; - //~^ ERROR expected constant integer for repeat count, but attempted left shift with overflow } From 8dff0ac143a689b7a1e04e55273d3f006b8369d1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 31 Mar 2015 18:59:36 -0700 Subject: [PATCH 45/46] Test fixes and rebase conflicts --- src/librustc/middle/ty.rs | 1 - src/libstd/old_io/extensions.rs | 2 +- src/libstd/sys/windows/fs.rs | 7 +++++++ src/libstd/sys/windows/process.rs | 4 ++-- src/libstd/sys/windows/process2.rs | 7 +++---- src/test/run-pass-fulldeps/create-dir-all-bare.rs | 2 ++ src/test/run-pass-fulldeps/rename-directory.rs | 1 + src/test/run-pass/big-literals.rs | 2 +- src/test/run-pass/tcp-stress.rs | 6 +++--- 9 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 87d17cbc04f..6e81d14d73c 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -74,7 +74,6 @@ use std::fmt; use std::hash::{Hash, SipHasher, Hasher}; use std::mem; use std::num::ToPrimitive; -use std::num::wrapping::WrappingOps; use std::ops; use std::rc::Rc; use std::vec::IntoIter; diff --git a/src/libstd/old_io/extensions.rs b/src/libstd/old_io/extensions.rs index aec794af759..73973d0db28 100644 --- a/src/libstd/old_io/extensions.rs +++ b/src/libstd/old_io/extensions.rs @@ -519,7 +519,7 @@ mod bench { ({ use super::u64_from_be_bytes; - let len = $stride.wrapping_mul(100).wrapping_add($start_index); + let len = ($stride as u8).wrapping_mul(100).wrapping_add($start_index); let data = (0..len).collect::>(); let mut sum = 0; $b.iter(|| { diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index f534a33d8cc..0bbb1a9e927 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -135,6 +135,13 @@ impl FileDesc { _ => Err(super::last_error()), } } + + #[allow(dead_code)] + pub fn unwrap(self) -> fd_t { + let fd = self.fd; + unsafe { mem::forget(self) }; + fd + } } impl Drop for FileDesc { diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 414083bc41f..b10042090dd 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -487,9 +487,9 @@ mod tests { #[test] fn test_make_command_line() { fn test_wrapper(prog: &str, args: &[&str]) -> String { - make_command_line(&CString::new(prog), + make_command_line(&CString::new(prog).unwrap(), &args.iter() - .map(|a| CString::new(a)) + .map(|a| CString::new(*a).unwrap()) .collect::>()) } diff --git a/src/libstd/sys/windows/process2.rs b/src/libstd/sys/windows/process2.rs index 9e9bb86446e..7e832b6384d 100644 --- a/src/libstd/sys/windows/process2.rs +++ b/src/libstd/sys/windows/process2.rs @@ -445,10 +445,9 @@ mod tests { fn test_wrapper(prog: &str, args: &[&str]) -> String { String::from_utf16( &make_command_line(OsStr::from_str(prog), - args.iter() - .map(|a| OsString::from_str(a)) - .collect::>() - .as_slice())).unwrap() + &args.iter() + .map(|a| OsString::from(a)) + .collect::>())).unwrap() } assert_eq!( diff --git a/src/test/run-pass-fulldeps/create-dir-all-bare.rs b/src/test/run-pass-fulldeps/create-dir-all-bare.rs index d09d7c55722..e4fb7c19909 100644 --- a/src/test/run-pass-fulldeps/create-dir-all-bare.rs +++ b/src/test/run-pass-fulldeps/create-dir-all-bare.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-android + #![feature(rustc_private)] extern crate rustc_back; diff --git a/src/test/run-pass-fulldeps/rename-directory.rs b/src/test/run-pass-fulldeps/rename-directory.rs index fa810f72fcb..a1e016bf2ea 100644 --- a/src/test/run-pass-fulldeps/rename-directory.rs +++ b/src/test/run-pass-fulldeps/rename-directory.rs @@ -11,6 +11,7 @@ // This test can't be a unit test in std, // because it needs TempDir, which is in extra +// ignore-android // pretty-expanded FIXME #23616 #![feature(rustc_private, path_ext)] diff --git a/src/test/run-pass/big-literals.rs b/src/test/run-pass/big-literals.rs index ff13a1345d2..b73eac0c714 100644 --- a/src/test/run-pass/big-literals.rs +++ b/src/test/run-pass/big-literals.rs @@ -21,5 +21,5 @@ pub fn main() { assert_eq!(0xffffffffffffffff, (-1 as u64)); assert_eq!(18446744073709551615, (-1 as u64)); - assert_eq!((-2147483648).wrapping_sub(1), 2147483647); + assert_eq!((-2147483648i32).wrapping_sub(1), 2147483647); } diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs index 489abf163c0..4209d5986ba 100644 --- a/src/test/run-pass/tcp-stress.rs +++ b/src/test/run-pass/tcp-stress.rs @@ -23,12 +23,12 @@ extern crate libc; use std::sync::mpsc::channel; use std::old_io::net::tcp::{TcpListener, TcpStream}; use std::old_io::{Acceptor, Listener, Reader, Writer}; -use std::thread::{Builder, Thread}; +use std::thread::{self, Builder}; use std::time::Duration; fn main() { // This test has a chance to time out, try to not let it time out - Thread::spawn(move|| -> () { + thread::spawn(move|| -> () { use std::old_io::timer; timer::sleep(Duration::milliseconds(30 * 1000)); println!("timed out!"); @@ -36,7 +36,7 @@ fn main() { }); let (tx, rx) = channel(); - Thread::spawn(move || -> () { + thread::spawn(move || -> () { let mut listener = TcpListener::bind("127.0.0.1:0").unwrap(); tx.send(listener.socket_name().unwrap()).unwrap(); let mut acceptor = listener.listen(); From 2b71aed003997cc09b85c01306083187cb924a29 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 1 Apr 2015 11:59:51 +0200 Subject: [PATCH 46/46] Update android tests to reflect API switch from `os::env` to `env::vars`. --- src/libstd/old_io/process.rs | 2 +- src/libstd/process.rs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index 7e1865a9ed6..ad2d5b46819 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -1074,7 +1074,7 @@ mod tests { let mut prog = env_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); - let r = env::vars(); + let r = ::env::vars(); for (k, v) in r { // don't check android RANDOM variables if k != "RANDOM".to_string() { diff --git a/src/libstd/process.rs b/src/libstd/process.rs index c2d43ba2a05..52f5965db80 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -832,14 +832,13 @@ mod tests { #[cfg(target_os="android")] #[test] fn test_inherit_env() { - use os; + use std::env; if running_on_valgrind() { return; } let mut result = env_cmd().output().unwrap(); let output = String::from_utf8(result.stdout).unwrap(); - let r = os::env(); - for &(ref k, ref v) in &r { + for (ref k, ref v) in env::vars() { // don't check android RANDOM variables if *k != "RANDOM".to_string() { assert!(output.contains(&format!("{}={}",