diff options
Diffstat (limited to 'src/libstd')
48 files changed, 813 insertions, 367 deletions
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 9ab440f289e..e43101b7c9d 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1346,11 +1346,15 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> { pub enum Entry<'a, K: 'a, V: 'a> { /// An occupied Entry. #[stable(feature = "rust1", since = "1.0.0")] - Occupied(OccupiedEntry<'a, K, V>), + Occupied( + #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] OccupiedEntry<'a, K, V> + ), /// A vacant Entry. #[stable(feature = "rust1", since = "1.0.0")] - Vacant(VacantEntry<'a, K, V>), + Vacant( + #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] VacantEntry<'a, K, V> + ), } /// Possible states of a VacantEntry. diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index 62ec23ccb20..41001153c3c 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -16,7 +16,7 @@ reason = "API has not been scrutinized and is highly likely to \ either disappear or change", issue = "27810")] -#![rustc_deprecated(since = "1.5.0", reason = "replaced with crates.io crates")] +#![rustc_deprecated(since = "1.5.0", reason = "replaced with 'dylib' on crates.io")] #![allow(missing_docs)] #![allow(deprecated)] @@ -132,6 +132,7 @@ mod tests { #[cfg_attr(any(windows, target_os = "android", // FIXME #10379 target_env = "musl"), ignore)] + #[allow(deprecated)] fn test_loading_cosine() { // The math library does not need to be loaded since it is already // statically linked in @@ -164,6 +165,7 @@ mod tests { target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))] + #[allow(deprecated)] fn test_errors_do_not_crash() { // Open /dev/null as a library to get an error, and make sure // that only causes an error, and not a crash. diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 760733872ea..db136190082 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -218,7 +218,7 @@ pub enum VarError { /// valid unicode data. The found data is returned as a payload of this /// variant. #[stable(feature = "env", since = "1.0.0")] - NotUnicode(OsString), + NotUnicode(#[cfg_attr(not(stage0), stable(feature = "env", since = "1.0.0"))] OsString), } #[stable(feature = "env", since = "1.0.0")] @@ -615,6 +615,8 @@ pub mod consts { /// - mips /// - mipsel /// - powerpc + /// - powerpc64 + /// - powerpc64le #[stable(feature = "env", since = "1.0.0")] pub const ARCH: &'static str = super::arch::ARCH; @@ -867,6 +869,16 @@ mod arch { pub const ARCH: &'static str = "powerpc"; } +#[cfg(target_arch = "powerpc64")] +mod arch { + pub const ARCH: &'static str = "powerpc64"; +} + +#[cfg(target_arch = "powerpc64le")] +mod arch { + pub const ARCH: &'static str = "powerpc64le"; +} + #[cfg(target_arch = "le32")] mod arch { pub const ARCH: &'static str = "le32"; diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 46d03169b2d..c44a4bfe0f1 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -119,6 +119,15 @@ impl From<String> for Box<Error + Send + Sync> { } } +#[stable(feature = "string_box_error", since = "1.7.0")] +impl From<String> for Box<Error> { + fn from(str_err: String) -> Box<Error> { + let err1: Box<Error + Send + Sync> = From::from(str_err); + let err2: Box<Error> = err1; + err2 + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a> { fn from(err: &'b str) -> Box<Error + Send + Sync + 'a> { @@ -126,6 +135,13 @@ impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a> { } } +#[stable(feature = "string_box_error", since = "1.7.0")] +impl<'a> From<&'a str> for Box<Error> { + fn from(err: &'a str) -> Box<Error> { + From::from(String::from(err)) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Error for str::ParseBoolError { fn description(&self) -> &str { "failed to parse bool" } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 3f3913471b8..9a41272299e 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -20,7 +20,7 @@ use iter::Iterator; use libc; use mem; use memchr; -use ops::Deref; +use ops; use option::Option::{self, Some, None}; use os::raw::c_char; use result::Result::{self, Ok, Err}; @@ -282,7 +282,7 @@ impl CString { } #[stable(feature = "rust1", since = "1.0.0")] -impl Deref for CString { +impl ops::Deref for CString { type Target = CStr; fn deref(&self) -> &CStr { @@ -522,6 +522,37 @@ impl ToOwned for CStr { } } +#[stable(feature = "cstring_asref", since = "1.7.0")] +impl<'a> From<&'a CStr> for CString { + fn from(s: &'a CStr) -> CString { + s.to_owned() + } +} + +#[stable(feature = "cstring_asref", since = "1.7.0")] +impl ops::Index<ops::RangeFull> for CString { + type Output = CStr; + + #[inline] + fn index(&self, _index: ops::RangeFull) -> &CStr { + self + } +} + +#[stable(feature = "cstring_asref", since = "1.7.0")] +impl AsRef<CStr> for CStr { + fn as_ref(&self) -> &CStr { + self + } +} + +#[stable(feature = "cstring_asref", since = "1.7.0")] +impl AsRef<CStr> for CString { + fn as_ref(&self) -> &CStr { + self + } +} + #[cfg(test)] mod tests { use prelude::v1::*; diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 90b108e6770..eb5ddecbd05 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -8,27 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A type that can represent all platform-native strings, but is cheaply -//! interconvertable with Rust strings. -//! -//! The need for this type arises from the fact that: -//! -//! * On Unix systems, strings are often arbitrary sequences of non-zero -//! bytes, in many cases interpreted as UTF-8. -//! -//! * On Windows, strings are often arbitrary sequences of non-zero 16-bit -//! values, interpreted as UTF-16 when it is valid to do so. -//! -//! * In Rust, strings are always valid UTF-8, but may contain zeros. -//! -//! The types in this module bridge this gap by simultaneously representing Rust -//! and platform-native string values, and in particular allowing a Rust string -//! to be converted into an "OS" string with no cost. -//! -//! **Note**: At the moment, these types are extremely bare-bones, usable only -//! for conversion to/from various other string types. Eventually these types -//! will offer a full-fledged string API. - use borrow::{Borrow, Cow, ToOwned}; use ffi::CString; use fmt::{self, Debug}; @@ -42,14 +21,29 @@ use vec::Vec; use sys::os_str::{Buf, Slice}; use sys_common::{AsInner, IntoInner, FromInner}; -/// Owned, mutable OS strings. +/// A type that can represent owned, mutable platform-native strings, but is +/// cheaply interconvertable with Rust strings. +/// +/// The need for this type arises from the fact that: +/// +/// * On Unix systems, strings are often arbitrary sequences of non-zero +/// bytes, in many cases interpreted as UTF-8. +/// +/// * On Windows, strings are often arbitrary sequences of non-zero 16-bit +/// values, interpreted as UTF-16 when it is valid to do so. +/// +/// * In Rust, strings are always valid UTF-8, but may contain zeros. +/// +/// `OsString` and `OsStr` bridge this gap by simultaneously representing Rust +/// and platform-native string values, and in particular allowing a Rust string +/// to be converted into an "OS" string with no cost. #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct OsString { inner: Buf } -/// Slices into OS strings. +/// Slices into OS strings (see `OsString`). #[stable(feature = "rust1", since = "1.0.0")] pub struct OsStr { inner: Slice diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 715749f50d4..635ed91f35d 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -715,7 +715,7 @@ impl DirEntry { /// This function will not traverse symlinks if this entry points at a /// symlink. /// - /// # Platform behavior + /// # Platform-specific behavior /// /// On Windows this function is cheap to call (no extra system calls /// needed), but on Unix platforms this function is the equivalent of @@ -730,7 +730,7 @@ impl DirEntry { /// This function will not traverse symlinks if this entry points at a /// symlink. /// - /// # Platform behavior + /// # Platform-specific behavior /// /// On Windows and most Unix platforms this function is free (no extra /// system calls needed), but some Unix platforms may require the equivalent @@ -758,11 +758,20 @@ impl AsInner<fs_imp::DirEntry> for DirEntry { /// guarantee that the file is immediately deleted (e.g. depending on /// platform, other open file descriptors may prevent immediate removal). /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `unlink` function on Unix +/// and the `DeleteFile` function on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// /// # Errors /// -/// This function will return an error if `path` points to a directory, if the -/// user lacks permissions to remove the file, or if some other filesystem-level -/// error occurs. +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * `path` points to a directory. +/// * The user lacks permissions to remove the file. /// /// # Examples /// @@ -785,6 +794,21 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> { /// This function will traverse symbolic links to query information about the /// destination file. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `stat` function on Unix +/// and the `GetFileAttributesEx` function on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// +/// # Errors +/// +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * The user lacks permissions to perform `metadata` call on `path`. +/// * `path` does not exist. +/// /// # Examples /// /// ```rust @@ -796,12 +820,6 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> { /// # Ok(()) /// # } /// ``` -/// -/// # Errors -/// -/// This function will return an error if the user lacks the requisite -/// permissions to perform a `metadata` call on the given `path` or if there -/// is no entry in the filesystem at the provided path. #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> { fs_imp::stat(path.as_ref()).map(Metadata) @@ -809,6 +827,21 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> { /// Query the metadata about a file without following symlinks. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `lstat` function on Unix +/// and the `GetFileAttributesEx` function on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// +/// # Errors +/// +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * The user lacks permissions to perform `metadata` call on `path`. +/// * `path` does not exist. +/// /// # Examples /// /// ```rust @@ -829,12 +862,21 @@ pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> { /// /// This will not work if the new name is on a different mount point. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `rename` function on Unix +/// and the `MoveFileEx` function with the `MOVEFILE_REPLACE_EXISTING` flag on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// /// # Errors /// -/// This function will return an error if the provided `from` doesn't exist, if -/// the process lacks permissions to view the contents, if `from` and `to` -/// reside on separate filesystems, or if some other intermittent I/O error -/// occurs. +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * `from` does not exist. +/// * The user lacks permissions to view contents. +/// * `from` and `to` are on separate filesystems. /// /// # Examples /// @@ -842,7 +884,7 @@ pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> { /// use std::fs; /// /// # fn foo() -> std::io::Result<()> { -/// try!(fs::rename("a.txt", "b.txt")); +/// try!(fs::rename("a.txt", "b.txt")); // Rename a.txt to b.txt /// # Ok(()) /// # } /// ``` @@ -861,15 +903,24 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> /// /// On success, the total number of bytes copied is returned. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `open` function in Unix +/// with `O_RDONLY` for `from` and `O_WRONLY`, `O_CREAT`, and `O_TRUNC` for `to`. +/// `O_CLOEXEC` is set for returned file descriptors. +/// On Windows, this function currently corresponds to `CopyFileEx`. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// /// # Errors /// /// This function will return an error in the following situations, but is not /// limited to just these cases: /// -/// * The `from` path is not a file -/// * The `from` file does not exist +/// * The `from` path is not a file. +/// * The `from` file does not exist. /// * The current process does not have the permission rights to access -/// `from` or write `to` +/// `from` or write `to`. /// /// # Examples /// @@ -877,7 +928,7 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> /// use std::fs; /// /// # fn foo() -> std::io::Result<()> { -/// try!(fs::copy("foo.txt", "bar.txt")); +/// try!(fs::copy("foo.txt", "bar.txt")); // Copy foo.txt to bar.txt /// # Ok(()) } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -890,13 +941,27 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> { /// The `dst` path will be a link pointing to the `src` path. Note that systems /// often require these two paths to both be located on the same filesystem. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `link` function on Unix +/// and the `CreateHardLink` function on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// +/// # Errors +/// +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * The `src` path is not a file or doesn't exist. +/// /// # Examples /// /// ``` /// use std::fs; /// /// # fn foo() -> std::io::Result<()> { -/// try!(fs::hard_link("a.txt", "b.txt")); +/// try!(fs::hard_link("a.txt", "b.txt")); // Hard link a.txt to b.txt /// # Ok(()) /// # } /// ``` @@ -933,11 +998,21 @@ pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<( /// Reads a symbolic link, returning the file that the link points to. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `readlink` function on Unix +/// and the `CreateFile` function with `FILE_FLAG_OPEN_REPARSE_POINT` and +/// `FILE_FLAG_BACKUP_SEMANTICS` flags on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// /// # Errors /// -/// This function will return an error on failure. Failure conditions include -/// reading a file that does not exist or reading a file that is not a symbolic -/// link. +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * `path` is not a symbolic link. +/// * `path` does not exist. /// /// # Examples /// @@ -957,8 +1032,20 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> { /// Returns the canonical form of a path with all intermediate components /// normalized and symbolic links resolved. /// -/// This function may return an error in situations like where the path does not -/// exist, a component in the path is not a directory, or an I/O error happens. +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `realpath` function on Unix +/// and the `CreateFile` and `GetFinalPathNameByHandle` functions on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// +/// # Errors +/// +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * `path` does not exist. +/// * A component in path is not a directory. /// /// # Examples /// @@ -977,10 +1064,20 @@ pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> { /// Creates a new, empty directory at the provided path /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `mkdir` function on Unix +/// and the `CreateDirectory` function on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// /// # Errors /// -/// This function will return an error if the user lacks permissions to make a -/// new directory at the provided `path`, or if the directory already exists. +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * User lacks permissions to create directory at `path`. +/// * `path` already exists. /// /// # Examples /// @@ -1000,9 +1097,19 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { /// Recursively create a directory and all of its parent components if they /// are missing. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `mkdir` function on Unix +/// and the `CreateDirectory` function on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// /// # Errors /// -/// This function will fail if any directory in the path specified by `path` +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * If any directory in the path specified by `path` /// does not already exist and it could not be created otherwise. The specific /// error conditions for when a directory is being created (after it is /// determined to not exist) are outlined by `fs::create_dir`. @@ -1024,10 +1131,20 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> { /// Removes an existing, empty directory. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `rmdir` function on Unix +/// and the `RemoveDirectory` function on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// /// # Errors /// -/// This function will return an error if the user lacks permissions to remove -/// the directory at the provided `path`, or if the directory isn't empty. +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * The user lacks permissions to remove the directory at the provided `path`. +/// * The directory isn't empty. /// /// # Examples /// @@ -1050,6 +1167,14 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { /// This function does **not** follow symbolic links and it will simply remove the /// symbolic link itself. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to `opendir`, `lstat`, `rm` and `rmdir` functions on Unix +/// and the `FindFirstFile`, `GetFileAttributesEx`, `DeleteFile`, and `RemoveDirectory` functions +/// on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// /// # Errors /// /// See `file::remove_file` and `fs::remove_dir`. @@ -1087,6 +1212,22 @@ fn _remove_dir_all(path: &Path) -> io::Result<()> { /// The iterator will yield instances of `io::Result<DirEntry>`. New errors may /// be encountered after an iterator is initially constructed. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `opendir` function on Unix +/// and the `FindFirstFile` function on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// +/// # Errors +/// +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * The provided `path` doesn't exist. +/// * The process lacks permissions to view the contents. +/// * The `path` points at a non-directory file. +/// /// # Examples /// /// ``` @@ -1109,12 +1250,6 @@ fn _remove_dir_all(path: &Path) -> io::Result<()> { /// Ok(()) /// } /// ``` -/// -/// # Errors -/// -/// This function will return an error if the provided `path` doesn't exist, if -/// the process lacks permissions to view the contents or if the `path` points -/// at a non-directory file #[stable(feature = "rust1", since = "1.0.0")] pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> { fs_imp::readdir(path.as_ref()).map(ReadDir) @@ -1180,6 +1315,21 @@ impl Iterator for WalkDir { /// Changes the permissions found on a file or a directory. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `chmod` function on Unix +/// and the `SetFileAttributes` function on Windows. +/// Note that, this [may change in the future][changes]. +/// [changes]: ../io/index.html#platform-specific-behavior +/// +/// # Errors +/// +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * `path` does not exist. +/// * The user lacks the permission to change attributes of the file. +/// /// # Examples /// /// ``` @@ -1192,12 +1342,6 @@ impl Iterator for WalkDir { /// # Ok(()) /// # } /// ``` -/// -/// # Errors -/// -/// This function will return an error if the provided `path` doesn't exist, if -/// the process lacks permissions to change the attributes of the file, or if -/// some other I/O error is encountered. #[stable(feature = "set_permissions", since = "1.1.0")] pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> { @@ -1281,7 +1425,6 @@ mod tests { use io::{ErrorKind, SeekFrom}; use path::PathBuf; use path::Path as Path2; - use os; use rand::{self, StdRng, Rng}; use str; @@ -1410,8 +1553,8 @@ mod tests { let message = "ten-four"; let mut read_mem = [0; 4]; let set_cursor = 4 as u64; - let mut tell_pos_pre_read; - let mut tell_pos_post_read; + let tell_pos_pre_read; + let tell_pos_post_read; let tmpdir = tmpdir(); let filename = &tmpdir.join("file_rt_io_file_test_seeking.txt"); { diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 79eedbeda2c..a9a79fe2c77 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -772,26 +772,11 @@ impl<W: Write> fmt::Debug for LineWriter<W> where W: fmt::Debug { } } -struct InternalBufWriter<W: Write>(BufWriter<W>); - -impl<W: Read + Write> InternalBufWriter<W> { - fn get_mut(&mut self) -> &mut BufWriter<W> { - let InternalBufWriter(ref mut w) = *self; - return w; - } -} - -impl<W: Read + Write> Read for InternalBufWriter<W> { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - self.get_mut().inner.as_mut().unwrap().read(buf) - } -} - #[cfg(test)] mod tests { use prelude::v1::*; use io::prelude::*; - use io::{self, BufReader, BufWriter, Cursor, LineWriter, SeekFrom}; + use io::{self, BufReader, BufWriter, LineWriter, SeekFrom}; use test; /// A dummy reader intended at testing short-reads propagation. diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index 1dd96f5ddfc..e3f17c839f1 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -377,7 +377,7 @@ mod test { struct TestError; impl fmt::Display for TestError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { Ok(()) } } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index cc3f8097a88..abb47b69418 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -112,7 +112,7 @@ //! ``` //! //! `BufWriter` doesn't add any new ways of writing; it just buffers every call -//! to [`write()`][write]: +//! to [`write()`][write()]: //! //! ``` //! use std::io; @@ -134,7 +134,7 @@ //! # } //! ``` //! -//! [write]: trait.Write.html#tymethod.write +//! [write()]: trait.Write.html#tymethod.write //! //! ## Standard input and output //! @@ -237,7 +237,16 @@ //! to read the line and print it, so we use `()`. //! //! [result]: type.Result.html -//! [try]: macro.try!.html +//! [try]: ../macro.try!.html +//! +//! ## Platform-specific behavior +//! +//! Many I/O functions throughout the standard library are documented to indicate +//! what various library or syscalls they are delegated to. This is done to help +//! applications both understand what's happening under the hood as well as investigate +//! any possibly unclear semantics. Note, however, that this is informative, not a binding +//! contract. The implementation of many of these functions are subject to change over +//! time and may call fewer or more syscalls/library functions. #![stable(feature = "rust1", since = "1.0.0")] @@ -390,7 +399,7 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> /// /// [`File`][file]s implement `Read`: /// -/// [file]: ../std/fs/struct.File.html +/// [file]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -450,7 +459,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: ../std/fs/struct.File.html + /// [file]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -492,7 +501,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: ../std/fs/struct.File.html + /// [file]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -531,7 +540,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: ../std/fs/struct.File.html + /// [file]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -591,7 +600,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: ../std/fs/struct.File.html + /// [file]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -634,7 +643,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: ../std/fs/struct.File.html + /// [file]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -673,7 +682,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: ../std/fs/struct.File.html + /// [file]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -709,7 +718,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: ../std/fs/struct.File.html + /// [file]: ../fs/struct.File.html /// /// ``` /// #![feature(io)] @@ -744,7 +753,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: ../std/fs/struct.File.html + /// [file]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -780,7 +789,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: ../std/fs/struct.File.html + /// [file]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -814,7 +823,7 @@ pub trait Read { /// /// [`File`][file]s implement `Read`: /// - /// [file]: ../std/fs/struct.File.html + /// [file]: ../fs/struct.File.html /// /// ``` /// #![feature(io)] @@ -992,8 +1001,8 @@ pub trait Write { /// explicitly be called. The [`write!`][write] macro should be favored to /// invoke this method instead. /// - /// [formatargs]: ../std/macro.format_args!.html - /// [write]: ../std/macro.write!.html + /// [formatargs]: ../macro.format_args!.html + /// [write]: ../macro.write!.html /// /// This function internally uses the [`write_all`][writeall] method on /// this trait and hence will continuously write data so long as no errors @@ -1126,7 +1135,7 @@ pub trait Write { /// /// [`File`][file]s implement `Seek`: /// -/// [file]: ../std/fs/struct.File.html +/// [file]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -1166,23 +1175,23 @@ pub trait Seek { pub enum SeekFrom { /// Set the offset to the provided number of bytes. #[stable(feature = "rust1", since = "1.0.0")] - Start(u64), + Start(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] u64), /// Set the offset to the size of this object plus the specified number of /// bytes. /// - /// It is possible to seek beyond the end of an object, but is an error to + /// It is possible to seek beyond the end of an object, but it's an error to /// seek before byte 0. #[stable(feature = "rust1", since = "1.0.0")] - End(i64), + End(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] i64), /// Set the offset to the current position plus the specified number of /// bytes. /// - /// It is possible to seek beyond the end of an object, but is an error to + /// It is possible to seek beyond the end of an object, but it's an error to /// seek before byte 0. #[stable(feature = "rust1", since = "1.0.0")] - Current(i64), + Current(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] i64), } fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) @@ -1983,7 +1992,7 @@ mod tests { b.iter(|| { let mut lr = repeat(1).take(10000000); let mut vec = Vec::with_capacity(1024); - super::read_to_end(&mut lr, &mut vec); + super::read_to_end(&mut lr, &mut vec) }); } } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 985dbdd895f..79091fd3d6b 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -133,14 +133,17 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> { /// A handle to the standard input stream of a process. /// /// Each handle is a shared reference to a global buffer of input data to this -/// process. A handle can be `lock`'d to gain full access to `BufRead` methods +/// process. A handle can be `lock`'d to gain full access to [`BufRead`] methods /// (e.g. `.lines()`). Writes to this handle are otherwise locked with respect /// to other writes. /// /// This handle implements the `Read` trait, but beware that concurrent reads /// of `Stdin` must be executed with care. /// -/// Created by the function `io::stdin()`. +/// Created by the [`io::stdin`] method. +/// +/// [`io::stdin`]: fn.stdin.html +/// [`BufRead`]: trait.BufRead.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Stdin { inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>, @@ -148,8 +151,12 @@ pub struct Stdin { /// A locked reference to the `Stdin` handle. /// -/// This handle implements both the `Read` and `BufRead` traits and is -/// constructed via the `lock` method on `Stdin`. +/// This handle implements both the [`Read`] and [`BufRead`] traits, and +/// is constructed via the [`Stdin::lock`] method. +/// +/// [`Read`]: trait.Read.html +/// [`BufRead`]: trait.BufRead.html +/// [`Stdin::lock`]: struct.Stdin.html#method.lock #[stable(feature = "rust1", since = "1.0.0")] pub struct StdinLock<'a> { inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>, @@ -159,7 +166,7 @@ pub struct StdinLock<'a> { /// /// Each handle returned is a reference to a shared global buffer whose access /// is synchronized via a mutex. If you need more explicit control over -/// locking, see the [lock() method][lock]. +/// locking, see the [`lock() method`][lock]. /// /// [lock]: struct.Stdin.html#method.lock /// @@ -221,8 +228,11 @@ impl Stdin { /// guard. /// /// The lock is released when the returned lock goes out of scope. The - /// returned guard also implements the `Read` and `BufRead` traits for + /// returned guard also implements the [`Read`] and [`BufRead`] traits for /// accessing the underlying data. + /// + /// [`Read`]: trait.Read.html + /// [`BufRead`]: trait.BufRead.html #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdinLock { StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } @@ -231,7 +241,9 @@ impl Stdin { /// Locks this handle and reads a line of input into the specified buffer. /// /// For detailed semantics of this method, see the documentation on - /// `BufRead::read_line`. + /// [`BufRead::read_line`]. + /// + /// [`BufRead::read_line`]: trait.BufRead.html#method.read_line /// /// # Examples /// @@ -252,7 +264,7 @@ impl Stdin { /// /// - Pipe some text to it, e.g. `printf foo | path/to/executable` /// - Give it text interactively by running the executable directly, - // in which case it will wait for the Enter key to be pressed before + /// in which case it will wait for the Enter key to be pressed before /// continuing #[stable(feature = "rust1", since = "1.0.0")] pub fn read_line(&self, buf: &mut String) -> io::Result<usize> { @@ -314,7 +326,9 @@ const OUT_MAX: usize = ::usize::MAX; /// output stream. Access is also synchronized via a lock and explicit control /// over locking is available via the `lock` method. /// -/// Created by the function `io::stdout()`. +/// Created by the [`io::stdout`] method. +/// +/// [`io::stdout`]: fn.stdout.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Stdout { // FIXME: this should be LineWriter or BufWriter depending on the state of @@ -325,8 +339,11 @@ pub struct Stdout { /// A locked reference to the `Stdout` handle. /// -/// This handle implements the `Write` trait and is constructed via the `lock` -/// method on `Stdout`. +/// This handle implements the [`Write`] trait, and is constructed via +/// the [`Stdout::lock`] method. +/// +/// [`Write`]: trait.Write.html +/// [`Stdout::lock`]: struct.Stdout.html#method.lock #[stable(feature = "rust1", since = "1.0.0")] pub struct StdoutLock<'a> { inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>, @@ -336,9 +353,9 @@ pub struct StdoutLock<'a> { /// /// Each handle returned is a reference to a shared global buffer whose access /// is synchronized via a mutex. If you need more explicit control over -/// locking, see the [lock() method][lock]. +/// locking, see the [Stdout::lock] method. /// -/// [lock]: struct.Stdout.html#method.lock +/// [Stdout::lock]: struct.Stdout.html#method.lock /// /// # Examples /// @@ -424,7 +441,9 @@ impl<'a> Write for StdoutLock<'a> { /// A handle to the standard error stream of a process. /// -/// For more information, see `stderr` +/// For more information, see the [`io::stderr`] method. +/// +/// [`io::stderr`]: fn.stderr.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Stderr { inner: Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>>, @@ -432,8 +451,10 @@ pub struct Stderr { /// A locked reference to the `Stderr` handle. /// -/// This handle implements the `Write` trait and is constructed via the `lock` -/// method on `Stderr`. +/// This handle implements the `Write` trait and is constructed via +/// the [`Stderr::lock`] method. +/// +/// [`Stderr::lock`]: struct.Stderr.html#method.lock #[stable(feature = "rust1", since = "1.0.0")] pub struct StderrLock<'a> { inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>, diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 07a9548224a..e05a0d577ff 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -199,6 +199,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn tee() { let mut buf = [0; 10]; { @@ -209,6 +210,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn broadcast() { let mut buf1 = [0; 10]; let mut buf2 = [0; 10]; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index e66cc49290a..824acda522f 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -76,7 +76,7 @@ //! `i32`](primitive.i32.html) that lists all the methods that can be called on //! 32-bit integers (very useful), and there is a [page for the module //! `std::i32`](i32/index.html) that documents the constant values [`MIN`] and -//! [`MAX`] (rarely useful). +//! [`MAX`](i32/constant.MAX.html) (rarely useful). //! //! Note the documentation for the primitives [`str`] and [`[T]`][slice] (also //! called 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually @@ -153,7 +153,6 @@ //! //! [I/O]: io/index.html //! [`MIN`]: i32/constant.MIN.html -//! [`MAX`]: i32/constant.MAX.html //! [TCP]: net/struct.TcpStream.html //! [The Rust Prelude]: prelude/index.html //! [UDP]: net/struct.UdpSocket.html @@ -255,6 +254,7 @@ #![feature(slice_concat_ext)] #![feature(slice_patterns)] #![feature(staged_api)] +#![feature(stmt_expr_attributes)] #![feature(str_char)] #![feature(str_internals)] #![feature(str_utf16)] diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 9c4e2b1a54c..7ae389615ac 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -32,10 +32,10 @@ use vec; pub enum SocketAddr { /// An IPv4 socket address which is a (ip, port) combination. #[stable(feature = "rust1", since = "1.0.0")] - V4(SocketAddrV4), + V4(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] SocketAddrV4), /// An IPv6 socket address #[stable(feature = "rust1", since = "1.0.0")] - V6(SocketAddrV6), + V6(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] SocketAddrV6), } /// An IPv4 socket address which is a (ip, port) combination. @@ -468,9 +468,7 @@ impl<'a, T: ToSocketAddrs + ?Sized> ToSocketAddrs for &'a T { #[cfg(test)] mod tests { use prelude::v1::*; - use io; use net::*; - use net::Ipv6MulticastScope::*; use net::test::{tsa, sa6, sa4}; #[test] diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 00be17f7383..808cf5cc031 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -527,7 +527,6 @@ impl FromInner<c::in6_addr> for Ipv6Addr { #[cfg(test)] mod tests { use prelude::v1::*; - use io; use net::*; use net::Ipv6MulticastScope::*; use net::test::{tsa, sa6, sa4}; diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index f54d4f80480..f9c38c38458 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -319,7 +319,7 @@ mod tests { use net::test::{next_test_ip4, next_test_ip6}; use sync::mpsc::channel; use sys_common::AsInner; - use time::Duration; + use time::{Instant, Duration}; use thread; fn each_ip(f: &mut FnMut(SocketAddr)) { @@ -929,6 +929,7 @@ mod tests { t!(stream.set_write_timeout(None)); assert_eq!(None, t!(stream.write_timeout())); + drop(listener); } #[test] @@ -940,11 +941,11 @@ mod tests { t!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); let mut buf = [0; 10]; - let wait = Duration::span(|| { - let kind = stream.read(&mut buf).err().expect("expected error").kind(); - assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut); - }); - assert!(wait > Duration::from_millis(400)); + let start = Instant::now(); + let kind = stream.read(&mut buf).err().expect("expected error").kind(); + assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut); + assert!(start.elapsed() > Duration::from_millis(400)); + drop(listener); } #[test] @@ -962,10 +963,10 @@ mod tests { t!(stream.read(&mut buf)); assert_eq!(b"hello world", &buf[..]); - let wait = Duration::span(|| { - let kind = stream.read(&mut buf).err().expect("expected error").kind(); - assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut); - }); - assert!(wait > Duration::from_millis(400)); + let start = Instant::now(); + let kind = stream.read(&mut buf).err().expect("expected error").kind(); + assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut); + assert!(start.elapsed() > Duration::from_millis(400)); + drop(listener); } } diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index b212d4d32aa..29ac991a547 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -27,18 +27,19 @@ use time::Duration; /// use std::net::UdpSocket; /// /// # fn foo() -> std::io::Result<()> { -/// let mut socket = try!(UdpSocket::bind("127.0.0.1:34254")); +/// { +/// let mut socket = try!(UdpSocket::bind("127.0.0.1:34254")); /// -/// let mut buf = [0; 10]; -/// let (amt, src) = try!(socket.recv_from(&mut buf)); +/// // read from the socket +/// let mut buf = [0; 10]; +/// let (amt, src) = try!(socket.recv_from(&mut buf)); /// -/// // Send a reply to the socket we received data from -/// let buf = &mut buf[..amt]; -/// buf.reverse(); -/// try!(socket.send_to(buf, &src)); -/// -/// drop(socket); // close the socket -/// # Ok(()) +/// // send a reply to the socket we received data from +/// let buf = &mut buf[..amt]; +/// buf.reverse(); +/// try!(socket.send_to(buf, &src)); +/// # Ok(()) +/// } // the socket is closed here /// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -169,7 +170,7 @@ mod tests { use net::test::{next_test_ip4, next_test_ip6}; use sync::mpsc::channel; use sys_common::AsInner; - use time::Duration; + use time::{Instant, Duration}; use thread; fn each_ip(f: &mut FnMut(SocketAddr, SocketAddr)) { @@ -370,22 +371,22 @@ mod tests { fn test_read_timeout() { let addr = next_test_ip4(); - let mut stream = t!(UdpSocket::bind(&addr)); + let stream = t!(UdpSocket::bind(&addr)); t!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); let mut buf = [0; 10]; - let wait = Duration::span(|| { - let kind = stream.recv_from(&mut buf).err().expect("expected error").kind(); - assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut); - }); - assert!(wait > Duration::from_millis(400)); + + let start = Instant::now(); + let kind = stream.recv_from(&mut buf).err().expect("expected error").kind(); + assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut); + assert!(start.elapsed() > Duration::from_millis(400)); } #[test] fn test_read_with_timeout() { let addr = next_test_ip4(); - let mut stream = t!(UdpSocket::bind(&addr)); + let stream = t!(UdpSocket::bind(&addr)); t!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); t!(stream.send_to(b"hello world", &addr)); @@ -394,10 +395,9 @@ mod tests { t!(stream.recv_from(&mut buf)); assert_eq!(b"hello world", &buf[..]); - let wait = Duration::span(|| { - let kind = stream.recv_from(&mut buf).err().expect("expected error").kind(); - assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut); - }); - assert!(wait > Duration::from_millis(400)); + let start = Instant::now(); + let kind = stream.recv_from(&mut buf).err().expect("expected error").kind(); + assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut); + assert!(start.elapsed() > Duration::from_millis(400)); } } diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 30bee80fbf6..7f57d6dc650 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -15,11 +15,16 @@ #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] +#[cfg(not(test))] use core::num; +#[cfg(not(test))] use intrinsics; +#[cfg(not(test))] use libc::c_int; +#[cfg(not(test))] use num::FpCategory; + #[stable(feature = "rust1", since = "1.0.0")] pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON}; #[stable(feature = "rust1", since = "1.0.0")] @@ -57,7 +62,7 @@ mod cmath { pub fn hypotf(x: c_float, y: c_float) -> c_float; } - // See the comments in `core::float::Float::floor` for why MSVC is special + // See the comments in the `floor` function for why MSVC is special // here. #[cfg(not(target_env = "msvc"))] extern { @@ -79,44 +84,54 @@ mod cmath { mod shims { use libc::{c_float, c_int}; + #[inline] pub unsafe fn acosf(n: c_float) -> c_float { f64::acos(n as f64) as c_float } + #[inline] pub unsafe fn asinf(n: c_float) -> c_float { f64::asin(n as f64) as c_float } + #[inline] pub unsafe fn atan2f(n: c_float, b: c_float) -> c_float { f64::atan2(n as f64, b as f64) as c_float } + #[inline] pub unsafe fn atanf(n: c_float) -> c_float { f64::atan(n as f64) as c_float } + #[inline] pub unsafe fn coshf(n: c_float) -> c_float { f64::cosh(n as f64) as c_float } + #[inline] pub unsafe fn frexpf(x: c_float, value: &mut c_int) -> c_float { let (a, b) = f64::frexp(x as f64); *value = b as c_int; a as c_float } + #[inline] pub unsafe fn ldexpf(x: c_float, n: c_int) -> c_float { f64::ldexp(x as f64, n as isize) as c_float } + #[inline] pub unsafe fn sinhf(n: c_float) -> c_float { f64::sinh(n as f64) as c_float } + #[inline] pub unsafe fn tanf(n: c_float) -> c_float { f64::tan(n as f64) as c_float } + #[inline] pub unsafe fn tanhf(n: c_float) -> c_float { f64::tanh(n as f64) as c_float } @@ -267,8 +282,6 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn floor(self) -> f32 { - return floorf(self); - // On MSVC LLVM will lower many math intrinsics to a call to the // corresponding function. On MSVC, however, many of these functions // aren't actually available as symbols to call, but rather they are all @@ -283,9 +296,9 @@ impl f32 { // redirect to this comment, so `floorf` is just one case of a missing // function on MSVC, but there are many others elsewhere. #[cfg(target_env = "msvc")] - fn floorf(f: f32) -> f32 { (f as f64).floor() as f32 } + return (self as f64).floor() as f32; #[cfg(not(target_env = "msvc"))] - fn floorf(f: f32) -> f32 { unsafe { intrinsics::floorf32(f) } } + return unsafe { intrinsics::floorf32(self) }; } /// Returns the smallest integer greater than or equal to a number. @@ -300,13 +313,11 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ceil(self) -> f32 { - return ceilf(self); - // see notes above in `floor` #[cfg(target_env = "msvc")] - fn ceilf(f: f32) -> f32 { (f as f64).ceil() as f32 } + return (self as f64).ceil() as f32; #[cfg(not(target_env = "msvc"))] - fn ceilf(f: f32) -> f32 { unsafe { intrinsics::ceilf32(f) } } + return unsafe { intrinsics::ceilf32(self) }; } /// Returns the nearest integer to a number. Round half-way cases away from @@ -501,13 +512,11 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn powf(self, n: f32) -> f32 { - return powf(self, n); - // see notes above in `floor` #[cfg(target_env = "msvc")] - fn powf(f: f32, n: f32) -> f32 { (f as f64).powf(n as f64) as f32 } + return (self as f64).powf(n as f64) as f32; #[cfg(not(target_env = "msvc"))] - fn powf(f: f32, n: f32) -> f32 { unsafe { intrinsics::powf32(f, n) } } + return unsafe { intrinsics::powf32(self, n) }; } /// Takes the square root of a number. @@ -552,13 +561,11 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp(self) -> f32 { - return expf(self); - // see notes above in `floor` #[cfg(target_env = "msvc")] - fn expf(f: f32) -> f32 { (f as f64).exp() as f32 } + return (self as f64).exp() as f32; #[cfg(not(target_env = "msvc"))] - fn expf(f: f32) -> f32 { unsafe { intrinsics::expf32(f) } } + return unsafe { intrinsics::expf32(self) }; } /// Returns `2^(self)`. @@ -596,13 +603,11 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln(self) -> f32 { - return logf(self); - // see notes above in `floor` #[cfg(target_env = "msvc")] - fn logf(f: f32) -> f32 { (f as f64).ln() as f32 } + return (self as f64).ln() as f32; #[cfg(not(target_env = "msvc"))] - fn logf(f: f32) -> f32 { unsafe { intrinsics::logf32(f) } } + return unsafe { intrinsics::logf32(self) }; } /// Returns the logarithm of the number with respect to an arbitrary base. @@ -659,20 +664,16 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log10(self) -> f32 { - return log10f(self); - // see notes above in `floor` #[cfg(target_env = "msvc")] - fn log10f(f: f32) -> f32 { (f as f64).log10() as f32 } + return (self as f64).log10() as f32; #[cfg(not(target_env = "msvc"))] - fn log10f(f: f32) -> f32 { unsafe { intrinsics::log10f32(f) } } + return unsafe { intrinsics::log10f32(self) }; } /// Converts radians to degrees. /// /// ``` - /// #![feature(float_extras)] - /// /// use std::f32::{self, consts}; /// /// let angle = consts::PI; @@ -681,16 +682,13 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[unstable(feature = "float_extras", reason = "desirability is unclear", - issue = "27752")] + #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")] #[inline] pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) } /// Converts degrees to radians. /// /// ``` - /// #![feature(float_extras)] - /// /// use std::f32::{self, consts}; /// /// let angle = 180.0f32; @@ -699,8 +697,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[unstable(feature = "float_extras", reason = "desirability is unclear", - issue = "27752")] + #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")] #[inline] pub fn to_radians(self) -> f32 { num::Float::to_radians(self) } @@ -885,13 +882,11 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin(self) -> f32 { - return sinf(self); - // see notes in `core::f32::Float::floor` #[cfg(target_env = "msvc")] - fn sinf(f: f32) -> f32 { (f as f64).sin() as f32 } + return (self as f64).sin() as f32; #[cfg(not(target_env = "msvc"))] - fn sinf(f: f32) -> f32 { unsafe { intrinsics::sinf32(f) } } + return unsafe { intrinsics::sinf32(self) }; } /// Computes the cosine of a number (in radians). @@ -908,13 +903,11 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cos(self) -> f32 { - return cosf(self); - // see notes in `core::f32::Float::floor` #[cfg(target_env = "msvc")] - fn cosf(f: f32) -> f32 { (f as f64).cos() as f32 } + return (self as f64).cos() as f32; #[cfg(not(target_env = "msvc"))] - fn cosf(f: f32) -> f32 { unsafe { intrinsics::cosf32(f) } } + return unsafe { intrinsics::cosf32(self) }; } /// Computes the tangent of a number (in radians). diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index d444b259445..b6a85ee0e9f 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -15,9 +15,13 @@ #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] +#[cfg(not(test))] use core::num; +#[cfg(not(test))] use intrinsics; +#[cfg(not(test))] use libc::c_int; +#[cfg(not(test))] use num::FpCategory; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 8e207f5e6cf..faaff494cab 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -47,11 +47,6 @@ pub fn test_num<T>(ten: T, two: T) where #[cfg(test)] mod tests { use super::*; - use i8; - use i16; - use i32; - use i64; - use isize; use u8; use u16; use u32; diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs index f44199f311b..953d0917141 100644 --- a/src/libstd/os/linux/raw.rs +++ b/src/libstd/os/linux/raw.rs @@ -205,7 +205,8 @@ mod arch { } } -#[cfg(target_arch = "x86_64")] +#[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "powerpc64le"))] mod arch { use super::{dev_t, mode_t}; use os::raw::{c_long, c_int}; diff --git a/src/libstd/os/openbsd/raw.rs b/src/libstd/os/openbsd/raw.rs index 209546c4e4f..b4d49395303 100644 --- a/src/libstd/os/openbsd/raw.rs +++ b/src/libstd/os/openbsd/raw.rs @@ -16,7 +16,7 @@ use os::raw::c_long; use os::unix::raw::{uid_t, gid_t}; #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = i64; -#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u32; +#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = i32; #[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = i32; #[stable(feature = "raw_ext", since = "1.1.0")] pub type fflags_t = u32; #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64; diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs index 17d6b2605c6..62080fee48e 100644 --- a/src/libstd/os/raw.rs +++ b/src/libstd/os/raw.rs @@ -14,11 +14,17 @@ #[cfg(any(target_os = "android", all(target_os = "linux", any(target_arch = "aarch64", - target_arch = "arm"))))] + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "powerpc64le"))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; #[cfg(not(any(target_os = "android", all(target_os = "linux", any(target_arch = "aarch64", - target_arch = "arm")))))] + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "powerpc64le")))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8; #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8; @@ -88,7 +94,8 @@ mod tests { c_longlong c_ulonglong c_float c_double); } - #[cfg(unix)] + #[cfg(all(unix, not(target_os = "android")))] + #[test] fn unix() { { use os::unix::raw; @@ -101,6 +108,7 @@ mod tests { } #[cfg(windows)] + #[test] fn windows() { use os::windows::raw; } diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 6e4ba337b08..8c0a785a102 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -13,6 +13,8 @@ #![unstable(feature = "std_panic", reason = "awaiting feedback", issue = "27719")] +use any::Any; +use boxed::Box; use cell::UnsafeCell; use ops::{Deref, DerefMut}; use ptr::{Unique, Shared}; @@ -21,6 +23,8 @@ use sync::{Arc, Mutex, RwLock}; use sys_common::unwind; use thread::Result; +pub use panicking::{take_handler, set_handler, PanicInfo, Location}; + /// A marker trait which represents "panic safe" types in Rust. /// /// This trait is implemented by default for many types and behaves similarly in @@ -39,15 +43,15 @@ use thread::Result; /// panics. /// 2. This broken invariant is then later observed. /// -/// Typically in Rust it is difficult to perform step (2) because catching a +/// Typically in Rust, it is difficult to perform step (2) because catching a /// panic involves either spawning a thread (which in turns makes it difficult /// to later witness broken invariants) or using the `recover` function in this -/// module. Additionally, even if an invariant is witness, it typically isn't a +/// module. Additionally, even if an invariant is witnessed, it typically isn't a /// problem in Rust because there's no uninitialized values (like in C or C++). /// /// It is possible, however, for **logical** invariants to be broken in Rust, /// which can end up causing behavioral bugs. Another key aspect of panic safety -/// in Rust is that in the absence of `unsafe` code, a panic cannot lead to +/// in Rust is that, in the absence of `unsafe` code, a panic cannot lead to /// memory unsafety. /// /// That was a bit of a whirlwind tour of panic safety, but for more information @@ -58,12 +62,12 @@ use thread::Result; /// ## What is `RecoverSafe`? /// /// Now that we've got an idea of what panic safety is in Rust, it's also -/// important to understand that this trait represents. As mentioned above, one +/// important to understand what this trait represents. As mentioned above, one /// way to witness broken invariants is through the `recover` function in this /// module as it allows catching a panic and then re-using the environment of /// the closure. /// -/// Simply but, a type `T` implements `RecoverSafe` if it cannot easily allow +/// Simply put, a type `T` implements `RecoverSafe` if it cannot easily allow /// witnessing a broken invariant through the use of `recover` (catching a /// panic). This trait is a marker trait, so it is automatically implemented for /// many types, and it is also structurally composed (e.g. a struct is recover @@ -99,8 +103,11 @@ use thread::Result; across a recover boundary"] pub trait RecoverSafe {} -/// A marker trait representing types which do not contain an `UnsafeCell` by -/// value internally. +/// A marker trait representing types where a shared reference is considered +/// recover safe. +/// +/// This trait is namely not implemented by `UnsafeCell`, the root of all +/// interior mutability. /// /// This is a "helper marker trait" used to provide impl blocks for the /// `RecoverSafe` trait, for more information see that documentation. @@ -108,7 +115,7 @@ pub trait RecoverSafe {} #[rustc_on_unimplemented = "the type {Self} contains interior mutability \ and a reference may not be safely transferrable \ across a recover boundary"] -pub trait NoUnsafeCell {} +pub trait RefRecoverSafe {} /// A simple wrapper around a type to assert that it is panic safe. /// @@ -157,11 +164,11 @@ pub struct AssertRecoverSafe<T>(T); // * Our custom AssertRecoverSafe wrapper is indeed recover safe impl RecoverSafe for .. {} impl<'a, T: ?Sized> !RecoverSafe for &'a mut T {} -impl<'a, T: NoUnsafeCell + ?Sized> RecoverSafe for &'a T {} -impl<T: NoUnsafeCell + ?Sized> RecoverSafe for *const T {} -impl<T: NoUnsafeCell + ?Sized> RecoverSafe for *mut T {} +impl<'a, T: RefRecoverSafe + ?Sized> RecoverSafe for &'a T {} +impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *const T {} +impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *mut T {} impl<T: RecoverSafe> RecoverSafe for Unique<T> {} -impl<T: NoUnsafeCell + ?Sized> RecoverSafe for Shared<T> {} +impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Shared<T> {} impl<T: ?Sized> RecoverSafe for Mutex<T> {} impl<T: ?Sized> RecoverSafe for RwLock<T> {} impl<T> RecoverSafe for AssertRecoverSafe<T> {} @@ -169,15 +176,16 @@ impl<T> RecoverSafe for AssertRecoverSafe<T> {} // not covered via the Shared impl above b/c the inner contents use // Cell/AtomicUsize, but the usage here is recover safe so we can lift the // impl up one level to Arc/Rc itself -impl<T: NoUnsafeCell + ?Sized> RecoverSafe for Rc<T> {} -impl<T: NoUnsafeCell + ?Sized> RecoverSafe for Arc<T> {} +impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Rc<T> {} +impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Arc<T> {} -// Pretty simple implementations for the `NoUnsafeCell` marker trait, basically -// just saying that this is a marker trait and `UnsafeCell` is the only thing -// which doesn't implement it (which then transitively applies to everything -// else. -impl NoUnsafeCell for .. {} -impl<T: ?Sized> !NoUnsafeCell for UnsafeCell<T> {} +// Pretty simple implementations for the `RefRecoverSafe` marker trait, +// basically just saying that this is a marker trait and `UnsafeCell` is the +// only thing which doesn't implement it (which then transitively applies to +// everything else). +impl RefRecoverSafe for .. {} +impl<T: ?Sized> !RefRecoverSafe for UnsafeCell<T> {} +impl<T> RefRecoverSafe for AssertRecoverSafe<T> {} impl<T> AssertRecoverSafe<T> { /// Creates a new `AssertRecoverSafe` wrapper around the provided type. @@ -253,3 +261,28 @@ pub fn recover<F: FnOnce() -> R + RecoverSafe, R>(f: F) -> Result<R> { } Ok(result.unwrap()) } + +/// Triggers a panic without invoking the panic handler. +/// +/// This is designed to be used in conjunction with `recover` to, for example, +/// carry a panic across a layer of C code. +/// +/// # Examples +/// +/// ```should_panic +/// #![feature(std_panic, recover, panic_propagate)] +/// +/// use std::panic; +/// +/// let result = panic::recover(|| { +/// panic!("oh no!"); +/// }); +/// +/// if let Err(err) = result { +/// panic::propagate(err); +/// } +/// ``` +#[unstable(feature = "panic_propagate", reason = "awaiting feedback", issue = "30752")] +pub fn propagate(payload: Box<Any + Send>) -> ! { + unwind::rust_panic(payload) +} diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 2b2af350c99..8561ecd9c4c 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -15,10 +15,12 @@ use any::Any; use cell::Cell; use cell::RefCell; use intrinsics; +use sync::StaticRwLock; use sys::stdio::Stderr; use sys_common::backtrace; use sys_common::thread_info; use sys_common::util; +use thread; thread_local! { pub static PANIC_COUNT: Cell<usize> = Cell::new(0) } @@ -28,11 +30,138 @@ thread_local! { } } -fn log_panic(obj: &(Any+Send), file: &'static str, line: u32, - log_backtrace: bool) { - let msg = match obj.downcast_ref::<&'static str>() { +#[derive(Copy, Clone)] +enum Handler { + Default, + Custom(*mut (Fn(&PanicInfo) + 'static + Sync + Send)), +} + +static HANDLER_LOCK: StaticRwLock = StaticRwLock::new(); +static mut HANDLER: Handler = Handler::Default; + +/// Registers a custom panic handler, replacing any that was previously +/// registered. +/// +/// The panic handler is invoked when a thread panics, but before it begins +/// unwinding the stack. The default handler prints a message to standard error +/// and generates a backtrace if requested, but this behavior can be customized +/// with the `set_handler` and `take_handler` functions. +/// +/// The handler is provided with a `PanicInfo` struct which contains information +/// about the origin of the panic, including the payload passed to `panic!` and +/// the source code location from which the panic originated. +/// +/// The panic handler is a global resource. +/// +/// # Panics +/// +/// Panics if called from a panicking thread. +#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")] +pub fn set_handler<F>(handler: F) where F: Fn(&PanicInfo) + 'static + Sync + Send { + if thread::panicking() { + panic!("cannot modify the panic handler from a panicking thread"); + } + + let handler = Box::new(handler); + unsafe { + let lock = HANDLER_LOCK.write(); + let old_handler = HANDLER; + HANDLER = Handler::Custom(Box::into_raw(handler)); + drop(lock); + + if let Handler::Custom(ptr) = old_handler { + Box::from_raw(ptr); + } + } +} + +/// Unregisters the current panic handler, returning it. +/// +/// If no custom handler is registered, the default handler will be returned. +/// +/// # Panics +/// +/// Panics if called from a panicking thread. +#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")] +pub fn take_handler() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> { + if thread::panicking() { + panic!("cannot modify the panic handler from a panicking thread"); + } + + unsafe { + let lock = HANDLER_LOCK.write(); + let handler = HANDLER; + HANDLER = Handler::Default; + drop(lock); + + match handler { + Handler::Default => Box::new(default_handler), + Handler::Custom(ptr) => {Box::from_raw(ptr)} // FIXME #30530 + } + } +} + +/// A struct providing information about a panic. +#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")] +pub struct PanicInfo<'a> { + payload: &'a (Any + Send), + location: Location<'a>, +} + +impl<'a> PanicInfo<'a> { + /// Returns the payload associated with the panic. + /// + /// This will commonly, but not always, be a `&'static str` or `String`. + #[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")] + pub fn payload(&self) -> &(Any + Send) { + self.payload + } + + /// Returns information about the location from which the panic originated, + /// if available. + /// + /// This method will currently always return `Some`, but this may change + /// in future versions. + #[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")] + pub fn location(&self) -> Option<&Location> { + Some(&self.location) + } +} + +/// A struct containing information about the location of a panic. +#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")] +pub struct Location<'a> { + file: &'a str, + line: u32, +} + +impl<'a> Location<'a> { + /// Returns the name of the source file from which the panic originated. + #[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")] + pub fn file(&self) -> &str { + self.file + } + + /// Returns the line number from which the panic originated. + #[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")] + pub fn line(&self) -> u32 { + self.line + } +} + +fn default_handler(info: &PanicInfo) { + let panics = PANIC_COUNT.with(|s| s.get()); + + // If this is a double panic, make sure that we print a backtrace + // for this panic. Otherwise only print it if logging is enabled. + let log_backtrace = panics >= 2 || backtrace::log_enabled(); + + let file = info.location.file; + let line = info.location.line; + + let msg = match info.payload.downcast_ref::<&'static str>() { Some(s) => *s, - None => match obj.downcast_ref::<String>() { + None => match info.payload.downcast_ref::<String>() { Some(s) => &s[..], None => "Box<Any>", } @@ -77,14 +206,25 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) { // debugger provides a useable stacktrace. if panics >= 3 { util::dumb_print(format_args!("thread panicked while processing \ - panic. aborting.")); + panic. aborting.\n")); unsafe { intrinsics::abort() } } - // If this is a double panic, make sure that we print a backtrace - // for this panic. Otherwise only print it if logging is enabled. - let log_backtrace = panics >= 2 || backtrace::log_enabled(); - log_panic(obj, file, line, log_backtrace); + let info = PanicInfo { + payload: obj, + location: Location { + file: file, + line: line, + }, + }; + + unsafe { + let _lock = HANDLER_LOCK.read(); + match HANDLER { + Handler::Default => default_handler(&info), + Handler::Custom(ptr) => (*ptr)(&info), + } + } if panics >= 2 { // If a thread panics while it's already unwinding then we @@ -92,7 +232,7 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) { // just abort. In the future we may consider resuming // unwinding or otherwise exiting the thread cleanly. util::dumb_print(format_args!("thread panicked while panicking. \ - aborting.")); + aborting.\n")); unsafe { intrinsics::abort() } } } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index d0b9cc4c460..3956f948eb9 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -266,27 +266,33 @@ mod platform { pub enum Prefix<'a> { /// Prefix `\\?\`, together with the given component immediately following it. #[stable(feature = "rust1", since = "1.0.0")] - Verbatim(&'a OsStr), + Verbatim(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr), /// Prefix `\\?\UNC\`, with the "server" and "share" components following it. #[stable(feature = "rust1", since = "1.0.0")] - VerbatimUNC(&'a OsStr, &'a OsStr), + VerbatimUNC( + #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr, + #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr, + ), /// Prefix like `\\?\C:\`, for the given drive letter #[stable(feature = "rust1", since = "1.0.0")] - VerbatimDisk(u8), + VerbatimDisk(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] u8), /// Prefix `\\.\`, together with the given component immediately following it. #[stable(feature = "rust1", since = "1.0.0")] - DeviceNS(&'a OsStr), + DeviceNS(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr), /// Prefix `\\server\share`, with the given "server" and "share" components. #[stable(feature = "rust1", since = "1.0.0")] - UNC(&'a OsStr, &'a OsStr), + UNC( + #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr, + #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr, + ), /// Prefix `C:` for the given disk drive. #[stable(feature = "rust1", since = "1.0.0")] - Disk(u8), + Disk(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] u8), } impl<'a> Prefix<'a> { @@ -528,7 +534,9 @@ pub enum Component<'a> { /// /// Does not occur on Unix. #[stable(feature = "rust1", since = "1.0.0")] - Prefix(PrefixComponent<'a>), + Prefix( + #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] PrefixComponent<'a> + ), /// The root directory component, appears after any prefix and before anything else #[stable(feature = "rust1", since = "1.0.0")] @@ -544,7 +552,7 @@ pub enum Component<'a> { /// A normal component, i.e. `a` and `b` in `a/b` #[stable(feature = "rust1", since = "1.0.0")] - Normal(&'a OsStr), + Normal(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr), } impl<'a> Component<'a> { diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index c7cb10a4707..619f100f1a1 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -30,23 +30,24 @@ mod imp { target_arch = "x86", target_arch = "arm", target_arch = "aarch64", - target_arch = "powerpc")))] + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "powerpc64le")))] fn getrandom(buf: &mut [u8]) -> libc::c_long { - extern "C" { - fn syscall(number: libc::c_long, ...) -> libc::c_long; - } - #[cfg(target_arch = "x86_64")] const NR_GETRANDOM: libc::c_long = 318; #[cfg(target_arch = "x86")] const NR_GETRANDOM: libc::c_long = 355; - #[cfg(any(target_arch = "arm", target_arch = "powerpc"))] + #[cfg(target_arch = "arm")] const NR_GETRANDOM: libc::c_long = 384; + #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64", + target_arch = "powerpc64le"))] + const NR_GETRANDOM: libc::c_long = 359; #[cfg(target_arch = "aarch64")] const NR_GETRANDOM: libc::c_long = 278; unsafe { - syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0) + libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0) } } @@ -55,7 +56,9 @@ mod imp { target_arch = "x86", target_arch = "arm", target_arch = "aarch64", - target_arch = "powerpc"))))] + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "powerpc64le"))))] fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 } fn getrandom_fill_bytes(v: &mut [u8]) { @@ -92,7 +95,9 @@ mod imp { target_arch = "x86", target_arch = "arm", target_arch = "aarch64", - target_arch = "powerpc")))] + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "powerpc64le")))] fn is_getrandom_available() -> bool { use sync::atomic::{AtomicBool, Ordering}; use sync::Once; @@ -120,7 +125,9 @@ mod imp { target_arch = "x86", target_arch = "arm", target_arch = "aarch64", - target_arch = "powerpc"))))] + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "powerpc64le"))))] fn is_getrandom_available() -> bool { false } /// A random number generator that retrieves randomness straight from @@ -226,7 +233,7 @@ mod imp { // getentropy(2) permits a maximum buffer size of 256 bytes for s in v.chunks_mut(256) { let ret = unsafe { - libc::syscall(libc::NR_GETENTROPY, s.as_mut_ptr(), s.len()) + libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len()) }; if ret == -1 { panic!("unexpected getentropy error: {}", errno()); @@ -381,8 +388,6 @@ mod imp { #[cfg(test)] mod tests { - use prelude::v1::*; - use sync::mpsc::channel; use rand::Rng; use super::OsRng; diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs index 36adf44cd3a..08bc809ed4d 100644 --- a/src/libstd/rand/reader.rs +++ b/src/libstd/rand/reader.rs @@ -63,8 +63,6 @@ impl<R: Read> Rng for ReaderRng<R> { #[cfg(test)] mod tests { - use prelude::v1::*; - use super::ReaderRng; use rand::Rng; diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 63fb9b561ff..fcd827e2a8b 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -22,13 +22,7 @@ issue = "0")] #![doc(hidden)] -use borrow::ToOwned; -use mem; -use panic; -use sys; -use sys_common::thread_info::{self, NewThread}; -use sys_common; -use thread::Thread; + // Reexport some of our utilities which are expected by other crates. pub use sys_common::unwind::{begin_unwind, begin_unwind_fmt}; @@ -41,6 +35,14 @@ pub use sys_common::unwind::imp::eh_frame_registry::*; #[cfg(not(test))] #[lang = "start"] fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { + use borrow::ToOwned; + use mem; + use panic; + use sys; + use sys_common; + use sys_common::thread_info::{self, NewThread}; + use thread::Thread; + sys::init(); let failed = unsafe { diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index d817a261f7c..1f7fe820bf8 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -510,15 +510,15 @@ mod tests { static M: StaticMutex = StaticMutex::new(); let g = M.lock().unwrap(); - let (g, _no_timeout) = C.wait_timeout_ms(g, 1).unwrap(); + let (g, _no_timeout) = C.wait_timeout(g, Duration::from_millis(1)).unwrap(); // spurious wakeups mean this isn't necessarily true // assert!(!no_timeout); let _t = thread::spawn(move || { let _g = M.lock().unwrap(); C.notify_one(); }); - let (g, no_timeout) = C.wait_timeout_ms(g, u32::MAX).unwrap(); - assert!(no_timeout); + let (g, timeout_res) = C.wait_timeout(g, Duration::from_millis(u32::MAX as u64)).unwrap(); + assert!(!timeout_res.timed_out()); drop(g); unsafe { C.destroy(); M.destroy(); } } diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index e87ae19c583..3eb5db09bc0 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -385,12 +385,12 @@ pub enum TrySendError<T> { /// this is not a buffered channel, then there is no receiver available to /// acquire the data. #[stable(feature = "rust1", since = "1.0.0")] - Full(T), + Full(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] T), /// This channel's receiving half has disconnected, so the data could not be /// sent. The data is returned back to the callee in this case. #[stable(feature = "rust1", since = "1.0.0")] - Disconnected(T), + Disconnected(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] T), } enum Flavor<T> { diff --git a/src/libstd/sys/common/io.rs b/src/libstd/sys/common/io.rs index 151d853fc9f..9f2f0df3a64 100644 --- a/src/libstd/sys/common/io.rs +++ b/src/libstd/sys/common/io.rs @@ -133,7 +133,7 @@ mod tests { b.iter(|| { let mut lr = repeat(1).take(10000000); let mut vec = Vec::with_capacity(1024); - unsafe { read_to_end_uninitialized(&mut lr, &mut vec) }; + unsafe { read_to_end_uninitialized(&mut lr, &mut vec) } }); } } diff --git a/src/libstd/sys/common/libunwind.rs b/src/libstd/sys/common/libunwind.rs index feb05c7b560..77d1eed9623 100644 --- a/src/libstd/sys/common/libunwind.rs +++ b/src/libstd/sys/common/libunwind.rs @@ -83,7 +83,8 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(any(target_arch = "mips", target_arch = "mipsel"))] pub const unwinder_private_data_size: usize = 2; -#[cfg(target_arch = "powerpc")] +#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64", + target_arch = "powerpc64le"))] pub const unwinder_private_data_size: usize = 2; #[repr(C)] diff --git a/src/libstd/sys/common/poison.rs b/src/libstd/sys/common/poison.rs index 446a4445b2d..2cfa04c843b 100644 --- a/src/libstd/sys/common/poison.rs +++ b/src/libstd/sys/common/poison.rs @@ -71,7 +71,7 @@ pub enum TryLockError<T> { /// The lock could not be acquired because another thread failed while holding /// the lock. #[stable(feature = "rust1", since = "1.0.0")] - Poisoned(PoisonError<T>), + Poisoned(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] PoisonError<T>), /// The lock could not be acquired at this time because the operation would /// otherwise block. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/common/remutex.rs b/src/libstd/sys/common/remutex.rs index f3f21e47a14..31caa68c4b7 100644 --- a/src/libstd/sys/common/remutex.rs +++ b/src/libstd/sys/common/remutex.rs @@ -167,7 +167,6 @@ mod tests { use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; use cell::RefCell; use sync::Arc; - use boxed; use thread; #[test] @@ -208,13 +207,13 @@ mod tests { fn trylock_works() { let m = Arc::new(ReentrantMutex::new(())); let m2 = m.clone(); - let lock = m.try_lock().unwrap(); - let lock2 = m.try_lock().unwrap(); + let _lock = m.try_lock().unwrap(); + let _lock2 = m.try_lock().unwrap(); thread::spawn(move || { let lock = m2.try_lock(); assert!(lock.is_err()); }).join().unwrap(); - let lock3 = m.try_lock().unwrap(); + let _lock3 = m.try_lock().unwrap(); } pub struct Answer<'a>(pub ReentrantMutexGuard<'a, RefCell<u32>>); @@ -233,9 +232,8 @@ mod tests { *lock.borrow_mut() = 1; let lock2 = mc.lock().unwrap(); *lock.borrow_mut() = 2; - let answer = Answer(lock2); + let _answer = Answer(lock2); panic!("What the answer to my lifetimes dilemma is?"); - drop(answer); }).join(); assert!(result.is_err()); let r = m.lock().err().unwrap().into_inner(); diff --git a/src/libstd/sys/common/unwind/mod.rs b/src/libstd/sys/common/unwind/mod.rs index 0f10e727461..666b2ed72ad 100644 --- a/src/libstd/sys/common/unwind/mod.rs +++ b/src/libstd/sys/common/unwind/mod.rs @@ -172,7 +172,7 @@ pub fn panicking() -> bool { #[inline(never)] #[no_mangle] #[allow(private_no_mangle_fns)] -fn rust_panic(cause: Box<Any + Send + 'static>) -> ! { +pub fn rust_panic(cause: Box<Any + Send + 'static>) -> ! { unsafe { imp::panic(cause) } diff --git a/src/libstd/sys/common/util.rs b/src/libstd/sys/common/util.rs index 979f1f48669..b7a6b7650d5 100644 --- a/src/libstd/sys/common/util.rs +++ b/src/libstd/sys/common/util.rs @@ -35,12 +35,12 @@ pub fn dumb_print(args: fmt::Arguments) { } pub fn abort(args: fmt::Arguments) -> ! { - dumb_print(format_args!("fatal runtime error: {}", args)); + dumb_print(format_args!("fatal runtime error: {}\n", args)); unsafe { intrinsics::abort(); } } #[allow(dead_code)] // stack overflow detection not enabled on all platforms pub unsafe fn report_overflow() { - dumb_print(format_args!("\nthread '{}' has overflowed its stack", + dumb_print(format_args!("\nthread '{}' has overflowed its stack\n", thread::current().name().unwrap_or("<unknown>"))); } diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index 2e092d5f770..bc997af3a27 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -1067,7 +1067,7 @@ mod tests { #[test] fn wtf8buf_show_str() { let text = "a\té 💩\r"; - let mut string = Wtf8Buf::from_str(text); + let string = Wtf8Buf::from_str(text); assert_eq!(format!("{:?}", text), format!("{:?}", string)); } diff --git a/src/libstd/sys/unix/ext/io.rs b/src/libstd/sys/unix/ext/io.rs index 52ac37c6e33..4163ede46af 100644 --- a/src/libstd/sys/unix/ext/io.rs +++ b/src/libstd/sys/unix/ext/io.rs @@ -33,7 +33,7 @@ pub trait AsRawFd { /// Extracts 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 + /// to the caller. The descriptor is only guaranteed 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; diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index e8575a6c21c..10fda3fcd7f 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -204,7 +204,8 @@ impl DirEntry { #[cfg(any(target_os = "macos", target_os = "ios", - target_os = "netbsd"))] + target_os = "netbsd", + target_os = "openbsd"))] fn name_bytes(&self) -> &[u8] { unsafe { ::slice::from_raw_parts(self.entry.d_name.as_ptr() as *const u8, @@ -213,8 +214,7 @@ impl DirEntry { } #[cfg(any(target_os = "freebsd", target_os = "dragonfly", - target_os = "bitrig", - target_os = "openbsd"))] + target_os = "bitrig"))] fn name_bytes(&self) -> &[u8] { unsafe { ::slice::from_raw_parts(self.entry.d_name.as_ptr() as *const u8, diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 68b0c3d6b0e..9771b057d8d 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -15,6 +15,7 @@ use io::{self, ErrorKind}; use libc; use num::One; use ops::Neg; +use alloc::oom; #[cfg(target_os = "android")] pub use os::android as platform; #[cfg(target_os = "bitrig")] pub use os::bitrig as platform; @@ -45,7 +46,23 @@ pub mod thread_local; pub mod time; pub mod stdio; -#[cfg(not(target_os = "nacl"))] +// A nicer handler for out-of-memory situations than the default one. This one +// prints a message to stderr before aborting. It is critical that this code +// does not allocate any memory since we are in an OOM situation. Any errors are +// ignored while printing since there's nothing we can do about them and we are +// about to exit anyways. +fn oom_handler() -> ! { + use intrinsics; + let msg = "fatal runtime error: out of memory\n"; + unsafe { + libc::write(libc::STDERR_FILENO, + msg.as_ptr() as *const libc::c_void, + msg.len() as libc::size_t); + intrinsics::abort(); + } +} + +#[cfg(not(any(target_os = "nacl", test)))] pub fn init() { use libc::signal; // By default, some platforms will send a *signal* when an EPIPE error @@ -58,9 +75,14 @@ pub fn init() { unsafe { assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0); } + + oom::set_oom_handler(oom_handler); +} + +#[cfg(all(target_os = "nacl", not(test)))] +pub fn init() { + oom::set_oom_handler(oom_handler); } -#[cfg(target_os = "nacl")] -pub fn init() { } pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno as libc::c_int { diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 407fcb0a1b8..bb9d37f93ab 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -288,6 +288,32 @@ impl Process { unsafe { libc::_exit(1) } } + // Make sure that the source descriptors are not an stdio descriptor, + // otherwise the order which we set the child's descriptors may blow + // away a descriptor which we are hoping to save. For example, + // suppose we want the child's stderr to be the parent's stdout, and + // the child's stdout to be the parent's stderr. No matter which we + // dup first, the second will get overwritten prematurely. + let maybe_migrate = |src: Stdio, output: &mut AnonPipe| { + match src { + Stdio::Raw(fd @ libc::STDIN_FILENO) | + Stdio::Raw(fd @ libc::STDOUT_FILENO) | + Stdio::Raw(fd @ libc::STDERR_FILENO) => { + let fd = match cvt_r(|| libc::dup(fd)) { + Ok(fd) => fd, + Err(_) => fail(output), + }; + let fd = FileDesc::new(fd); + fd.set_cloexec(); + Stdio::Raw(fd.into_raw()) + }, + + s @ Stdio::None | + s @ Stdio::Inherit | + s @ Stdio::Raw(_) => s, + } + }; + let setup = |src: Stdio, dst: c_int| { match src { Stdio::Inherit => true, @@ -313,6 +339,12 @@ impl Process { } }; + // Make sure we migrate all source descriptors before + // we start overwriting them + let in_fd = maybe_migrate(in_fd, &mut output); + let out_fd = maybe_migrate(out_fd, &mut output); + let err_fd = maybe_migrate(err_fd, &mut output); + if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) } if !setup(out_fd, libc::STDOUT_FILENO) { fail(&mut output) } if !setup(err_fd, libc::STDERR_FILENO) { fail(&mut output) } @@ -462,8 +494,7 @@ mod tests { use mem; use ptr; use libc; - use slice; - use sys::{self, cvt, pipe}; + use sys::{self, cvt}; macro_rules! t { ($e:expr) => { @@ -482,6 +513,8 @@ mod tests { #[cfg(target_os = "android")] unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int { + use slice; + let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<libc::sigset_t>()); let bit = (signum - 1) as usize; raw[bit / 8] |= 1 << (bit % 8); diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 9a7f98d24cd..fc49f4257be 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -7,11 +7,13 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. +#![cfg_attr(test, allow(dead_code))] use libc; use self::imp::{make_handler, drop_handler}; -pub use self::imp::{init, cleanup}; +pub use self::imp::cleanup; +pub use self::imp::init; pub struct Handler { _data: *mut libc::c_void @@ -40,12 +42,11 @@ impl Drop for Handler { target_os = "openbsd"))] mod imp { use super::Handler; - use sys_common::util::report_overflow; use mem; use ptr; + use libc::{sigaltstack, SIGSTKSZ}; use libc::{sigaction, SIGBUS, SIG_DFL, - SA_SIGINFO, SA_ONSTACK, sigaltstack, - SIGSTKSZ, sighandler_t}; + SA_SIGINFO, SA_ONSTACK, sighandler_t}; use libc; use libc::{mmap, munmap}; use libc::{SIGSEGV, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON}; @@ -58,19 +59,19 @@ mod imp { static mut PAGE_SIZE: usize = 0; #[cfg(any(target_os = "linux", target_os = "android"))] - unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> *mut libc::c_void { + unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { #[repr(C)] struct siginfo_t { a: [libc::c_int; 3], // si_signo, si_code, si_errno, si_addr: *mut libc::c_void, } - (*(info as *const siginfo_t)).si_addr + (*(info as *const siginfo_t)).si_addr as usize } #[cfg(not(any(target_os = "linux", target_os = "android")))] - unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> *mut libc::c_void { - (*info).si_addr + unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { + (*info).si_addr as usize } // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages @@ -94,8 +95,10 @@ mod imp { unsafe extern fn signal_handler(signum: libc::c_int, info: *mut libc::siginfo_t, _data: *mut libc::c_void) { + use sys_common::util::report_overflow; + let guard = thread_info::stack_guard().unwrap_or(0); - let addr = siginfo_si_addr(info) as usize; + let addr = siginfo_si_addr(info); // If the faulting address is within the guard page, then we print a // message saying so. diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 7e5342a3fd4..16c4ae8257c 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -20,6 +20,7 @@ use num::Zero; use os::windows::ffi::{OsStrExt, OsStringExt}; use path::PathBuf; use time::Duration; +use alloc::oom; #[macro_use] pub mod compat; @@ -42,7 +43,26 @@ pub mod thread_local; pub mod time; pub mod stdio; -pub fn init() {} +// See comment in sys/unix/mod.rs +fn oom_handler() -> ! { + use intrinsics; + use ptr; + let msg = "fatal runtime error: out of memory\n"; + unsafe { + // WriteFile silently fails if it is passed an invalid handle, so there + // is no need to check the result of GetStdHandle. + c::WriteFile(c::GetStdHandle(c::STD_ERROR_HANDLE), + msg.as_ptr() as c::LPVOID, + msg.len() as c::DWORD, + ptr::null_mut(), + ptr::null_mut()); + intrinsics::abort(); + } +} + +pub fn init() { + oom::set_oom_handler(oom_handler); +} pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno as c::DWORD { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 0e525f39421..116cd5da2ce 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -830,14 +830,14 @@ mod tests { fn test_park_timeout_unpark_before() { for _ in 0..10 { thread::current().unpark(); - thread::park_timeout_ms(u32::MAX); + thread::park_timeout(Duration::from_millis(u32::MAX as u64)); } } #[test] fn test_park_timeout_unpark_not_called() { for _ in 0..10 { - thread::park_timeout_ms(10); + thread::park_timeout(Duration::from_millis(10)); } } @@ -847,17 +847,17 @@ mod tests { let th = thread::current(); let _guard = thread::spawn(move || { - super::sleep_ms(50); + super::sleep(Duration::from_millis(50)); th.unpark(); }); - thread::park_timeout_ms(u32::MAX); + thread::park_timeout(Duration::from_millis(u32::MAX as u64)); } } #[test] fn sleep_ms_smoke() { - thread::sleep_ms(2); + thread::sleep(Duration::from_millis(2)); } // NOTE: the corresponding test for stderr is in run-pass/thread-stderr, due diff --git a/src/libstd/thread/scoped_tls.rs b/src/libstd/thread/scoped_tls.rs index 2c92bc504c8..dc0bc6dfe02 100644 --- a/src/libstd/thread/scoped_tls.rs +++ b/src/libstd/thread/scoped_tls.rs @@ -87,32 +87,9 @@ macro_rules! scoped_thread_local { issue = "0")] #[macro_export] #[allow_internal_unstable] -#[cfg(no_elf_tls)] macro_rules! __scoped_thread_local_inner { ($t:ty) => {{ - static _KEY: $crate::thread::__ScopedKeyInner<$t> = - $crate::thread::__ScopedKeyInner::new(); - fn _getit() -> &'static $crate::thread::__ScopedKeyInner<$t> { &_KEY } - $crate::thread::ScopedKey::new(_getit) - }} -} - -#[doc(hidden)] -#[unstable(feature = "thread_local_internals", - reason = "should not be necessary", - issue = "0")] -#[macro_export] -#[allow_internal_unstable] -#[cfg(not(no_elf_tls))] -macro_rules! __scoped_thread_local_inner { - ($t:ty) => {{ - #[cfg_attr(not(any(windows, - target_os = "android", - target_os = "ios", - target_os = "netbsd", - target_os = "openbsd", - target_arch = "aarch64")), - thread_local)] + #[cfg_attr(target_thread_local, thread_local)] static _KEY: $crate::thread::__ScopedKeyInner<$t> = $crate::thread::__ScopedKeyInner::new(); fn _getit() -> &'static $crate::thread::__ScopedKeyInner<$t> { &_KEY } @@ -221,13 +198,7 @@ impl<T> ScopedKey<T> { } } -#[cfg(not(any(windows, - target_os = "android", - target_os = "ios", - target_os = "netbsd", - target_os = "openbsd", - target_arch = "aarch64", - no_elf_tls)))] +#[cfg(target_thread_local)] #[doc(hidden)] mod imp { use cell::Cell; @@ -246,13 +217,7 @@ mod imp { } } -#[cfg(any(windows, - target_os = "android", - target_os = "ios", - target_os = "netbsd", - target_os = "openbsd", - target_arch = "aarch64", - no_elf_tls))] +#[cfg(not(target_thread_local))] #[doc(hidden)] mod imp { use cell::Cell; diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index 0981a8c4a5b..7ecb3920cc8 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -40,7 +40,7 @@ const MILLIS_PER_SEC: u64 = 1_000; /// let ten_millis = Duration::from_millis(10); /// ``` #[stable(feature = "duration", since = "1.3.0")] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Duration { secs: u64, nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC @@ -173,7 +173,6 @@ impl Div<u32> for Duration { #[cfg(test)] mod tests { - use prelude::v1::*; use super::Duration; #[test] diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs index e3ce8e0de4b..f885733c2d1 100644 --- a/src/libstd/time/mod.rs +++ b/src/libstd/time/mod.rs @@ -23,6 +23,7 @@ pub use self::duration::Duration; mod duration; /// A measurement of a monotonically increasing clock. +/// Opaque and useful only with `Duration`. /// /// Instants are always guaranteed to be greater than any previously measured /// instant when created, and are often useful for tasks such as measuring @@ -42,8 +43,8 @@ mod duration; #[unstable(feature = "time2", reason = "recently added", issue = "29866")] pub struct Instant(time::Instant); -/// A measurement of the system clock appropriate for timestamps such as those -/// on files on the filesystem. +/// A measurement of the system clock, useful for talking to +/// external entities like the file system or other processes. /// /// Distinct from the `Instant` type, this time measurement **is not /// monotonic**. This means that you can save a file to the file system, then |
