From 133e91da627a42218721caf2083c3f309e1b0dcc Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Tue, 7 Jul 2020 20:48:15 -0400 Subject: [PATCH 01/13] libstd/libcore: fix various typos --- src/libcore/convert/mod.rs | 2 +- src/libcore/hash/sip.rs | 2 +- src/libcore/intrinsics.rs | 8 ++++---- src/libcore/iter/traits/iterator.rs | 2 +- src/libcore/macros/mod.rs | 2 +- src/libcore/mem/mod.rs | 8 ++++---- src/libcore/num/f64.rs | 4 ++-- src/libcore/pin.rs | 2 +- src/libcore/ptr/const_ptr.rs | 6 +++--- src/libcore/ptr/mut_ptr.rs | 6 +++--- src/libcore/ptr/non_null.rs | 2 +- src/libstd/f32.rs | 2 +- src/libstd/f64.rs | 2 +- src/libstd/os/linux/fs.rs | 2 +- src/libstd/os/redox/fs.rs | 2 +- src/libstd/sys/sgx/fd.rs | 2 +- src/libstd/sys/unix/ext/fs.rs | 4 ++-- src/libstd/sys/vxworks/fd.rs | 2 +- src/libstd/sys/wasi/fs.rs | 8 ++++---- 19 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/libcore/convert/mod.rs b/src/libcore/convert/mod.rs index 8ff1ced53b071..d2023b402c1c6 100644 --- a/src/libcore/convert/mod.rs +++ b/src/libcore/convert/mod.rs @@ -674,7 +674,7 @@ impl AsRef for str { /// /// /// However there is one case where `!` syntax can be used -/// before `!` is stabilized as a full-fleged type: in the position of a function’s return type. +/// before `!` is stabilized as a full-fledged type: in the position of a function’s return type. /// Specifically, it is possible implementations for two different function pointer types: /// /// ``` diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index f2bbf646f3272..a9882d54de4f1 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -43,7 +43,7 @@ struct SipHasher24 { /// /// SipHash is a general-purpose hashing function: it runs at a good /// speed (competitive with Spooky and City) and permits strong _keyed_ -/// hashing. This lets you key your hashtables from a strong RNG, such as +/// hashing. This lets you key your hash tables from a strong RNG, such as /// [`rand::os::OsRng`](https://doc.rust-lang.org/rand/rand/os/struct.OsRng.html). /// /// Although the SipHash algorithm is considered to be generally strong, diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index b3e43cd799405..f1a7fab313d97 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -15,7 +15,7 @@ //! //! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute, //! the intrinsic's attribute must be `rustc_const_stable`, too. Such a change should not be done -//! without T-lang consulation, because it bakes a feature into the language that cannot be +//! without T-lang consultation, because it bakes a feature into the language that cannot be //! replicated in user code without compiler support. //! //! # Volatiles @@ -993,7 +993,7 @@ extern "rust-intrinsic" { /// [`std::mem::align_of`](../../std/mem/fn.align_of.html). #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")] pub fn min_align_of() -> usize; - /// The prefered alignment of a type. + /// The preferred alignment of a type. /// /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_pref_align_of", issue = "none")] @@ -1245,14 +1245,14 @@ extern "rust-intrinsic" { /// assert!(mid <= len); /// unsafe { /// let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice); - /// // first: transmute is not typesafe; all it checks is that T and + /// // first: transmute is not type safe; all it checks is that T and /// // U are of the same size. Second, right here, you have two /// // mutable references pointing to the same memory. /// (&mut slice[0..mid], &mut slice2[mid..len]) /// } /// } /// - /// // This gets rid of the typesafety problems; `&mut *` will *only* give + /// // This gets rid of the type safety problems; `&mut *` will *only* give /// // you an `&mut T` from an `&mut T` or `*mut T`. /// fn split_at_mut_casts(slice: &mut [T], mid: usize) /// -> (&mut [T], &mut [T]) { diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index ce4be973140e5..6ea5965cf8ccf 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -1082,7 +1082,7 @@ pub trait Iterator { /// let vec = iter.collect::>(); /// /// // We have more elements which could fit in u32 (4, 5), but `map_while` returned `None` for `-3` - /// // (as the `predicate` returned `None`) and `collect` stops at the first `None` entcountered. + /// // (as the `predicate` returned `None`) and `collect` stops at the first `None` encountered. /// assert_eq!(vec, vec![0, 1, 2]); /// ``` /// diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs index 17f7349bac233..7a74485a78b89 100644 --- a/src/libcore/macros/mod.rs +++ b/src/libcore/macros/mod.rs @@ -1044,7 +1044,7 @@ pub(crate) mod builtin { }; } - /// Includes a utf8-encoded file as a string. + /// Includes a UTF-8 encoded file as a string. /// /// The file is located relative to the current file (similarly to how /// modules are found). The provided path is interpreted in a platform-specific diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 0a976a4ca00c9..db2b3eeca5281 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -348,11 +348,11 @@ pub fn size_of_val(val: &T) -> usize { /// /// - If `T` is `Sized`, this function is always safe to call. /// - If the unsized tail of `T` is: -/// - a [slice], then the length of the slice tail must be an intialized +/// - a [slice], then the length of the slice tail must be an initialized /// integer, and the size of the *entire value* /// (dynamic tail length + statically sized prefix) must fit in `isize`. /// - a [trait object], then the vtable part of the pointer must point -/// to a valid vtable acquired by an unsizing coersion, and the size +/// to a valid vtable acquired by an unsizing coercion, and the size /// of the *entire value* (dynamic tail length + statically sized prefix) /// must fit in `isize`. /// - an (unstable) [extern type], then this function is always safe to @@ -483,11 +483,11 @@ pub fn align_of_val(val: &T) -> usize { /// /// - If `T` is `Sized`, this function is always safe to call. /// - If the unsized tail of `T` is: -/// - a [slice], then the length of the slice tail must be an intialized +/// - a [slice], then the length of the slice tail must be an initialized /// integer, and the size of the *entire value* /// (dynamic tail length + statically sized prefix) must fit in `isize`. /// - a [trait object], then the vtable part of the pointer must point -/// to a valid vtable acquired by an unsizing coersion, and the size +/// to a valid vtable acquired by an unsizing coercion, and the size /// of the *entire value* (dynamic tail length + statically sized prefix) /// must fit in `isize`. /// - an (unstable) [extern type], then this function is always safe to diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index b0df4d64f6ee1..ad9a576d15cd6 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -687,7 +687,7 @@ impl f64 { /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. /// /// Rather than trying to preserve signaling-ness cross-platform, this - /// implementation favours preserving the exact bits. This means that + /// implementation favors preserving the exact bits. This means that /// any payloads encoded in NaNs will be preserved even if the result of /// this method is sent over the network from an x86 machine to a MIPS one. /// @@ -696,7 +696,7 @@ impl f64 { /// /// If the input isn't NaN, then there is no portability concern. /// - /// If you don't care about signalingness (very likely), then there is no + /// If you don't care about signaling-ness (very likely), then there is no /// portability concern. /// /// Note that this function is distinct from `as` casting, which attempts to diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index da299f026f8f1..9bcacd8ddcf77 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -128,7 +128,7 @@ //! //! Crucially, we have to be able to rely on [`drop`] being called. If an element //! could be deallocated or otherwise invalidated without calling [`drop`], the pointers into it -//! from its neighbouring elements would become invalid, which would break the data structure. +//! from its neighboring elements would become invalid, which would break the data structure. //! //! Therefore, pinning also comes with a [`drop`]-related guarantee. //! diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index d1d7a71523822..afaf371d9588f 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -331,13 +331,13 @@ impl *const T { intrinsics::ptr_guaranteed_eq(self, other) } - /// Returns whether two pointers are guaranteed to be inequal. + /// Returns whether two pointers are guaranteed to be unequal. /// /// At runtime this function behaves like `self != other`. /// However, in some contexts (e.g., compile-time evaluation), /// it is not always possible to determine the inequality of two pointers, so this function may - /// spuriously return `false` for pointers that later actually turn out to be inequal. - /// But when it returns `true`, the pointers are guaranteed to be inequal. + /// spuriously return `false` for pointers that later actually turn out to be unequal. + /// But when it returns `true`, the pointers are guaranteed to be unequal. /// /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer /// comparisons for which both functions return `false`. diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 7d4b6339b511f..180bad73b342b 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -312,13 +312,13 @@ impl *mut T { intrinsics::ptr_guaranteed_eq(self as *const _, other as *const _) } - /// Returns whether two pointers are guaranteed to be inequal. + /// Returns whether two pointers are guaranteed to be unequal. /// /// At runtime this function behaves like `self != other`. /// However, in some contexts (e.g., compile-time evaluation), /// it is not always possible to determine the inequality of two pointers, so this function may - /// spuriously return `false` for pointers that later actually turn out to be inequal. - /// But when it returns `true`, the pointers are guaranteed to be inequal. + /// spuriously return `false` for pointers that later actually turn out to be unequal. + /// But when it returns `true`, the pointers are guaranteed to be unequal. /// /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer /// comparisons for which both functions return `false`. diff --git a/src/libcore/ptr/non_null.rs b/src/libcore/ptr/non_null.rs index c2d31bfb6a4ee..47f4c1595b154 100644 --- a/src/libcore/ptr/non_null.rs +++ b/src/libcore/ptr/non_null.rs @@ -171,7 +171,7 @@ impl NonNull<[T]> { /// assert_eq!(unsafe { slice.as_ref()[2] }, 7); /// ``` /// - /// (Note that this example artifically demonstrates a use of this method, + /// (Note that this example artificially demonstrates a use of this method, /// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.) #[unstable(feature = "nonnull_slice_from_raw_parts", issue = "71941")] #[rustc_const_unstable(feature = "const_nonnull_slice_from_raw_parts", issue = "71941")] diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index b392d6e7226d2..c905bcf5e3db4 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -1500,7 +1500,7 @@ mod tests { assert_approx_eq!(f32::from_bits(0x44a72000), 1337.0); assert_approx_eq!(f32::from_bits(0xc1640000), -14.25); - // Check that NaNs roundtrip their bits regardless of signalingness + // Check that NaNs roundtrip their bits regardless of signaling-ness // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits let masked_nan1 = f32::NAN.to_bits() ^ 0x002A_AAAA; let masked_nan2 = f32::NAN.to_bits() ^ 0x0055_5555; diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 72268d2cc2f98..f09fc8d790b28 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -1523,7 +1523,7 @@ mod tests { assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0); assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25); - // Check that NaNs roundtrip their bits regardless of signalingness + // Check that NaNs roundtrip their bits regardless of signaling-ness // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits let masked_nan1 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA; let masked_nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs index d22b44a066662..657737394ab82 100644 --- a/src/libstd/os/linux/fs.rs +++ b/src/libstd/os/linux/fs.rs @@ -285,7 +285,7 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_ctime_nsec(&self) -> i64; - /// Returns the "preferred" blocksize for efficient filesystem I/O. + /// Returns the "preferred" block size for efficient filesystem I/O. /// /// # Examples /// diff --git a/src/libstd/os/redox/fs.rs b/src/libstd/os/redox/fs.rs index 6c87df534bdc6..61b5bff380518 100644 --- a/src/libstd/os/redox/fs.rs +++ b/src/libstd/os/redox/fs.rs @@ -289,7 +289,7 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_ctime_nsec(&self) -> i64; - /// Returns the "preferred" blocksize for efficient filesystem I/O. + /// Returns the "preferred" block size for efficient filesystem I/O. /// /// # Examples /// diff --git a/src/libstd/sys/sgx/fd.rs b/src/libstd/sys/sgx/fd.rs index 90158030c7fbe..e5dc5b5adaa93 100644 --- a/src/libstd/sys/sgx/fd.rs +++ b/src/libstd/sys/sgx/fd.rs @@ -19,7 +19,7 @@ impl FileDesc { self.fd } - /// Extracts the actual filedescriptor without closing it. + /// Extracts the actual file descriptor without closing it. pub fn into_raw(self) -> Fd { let fd = self.fd; mem::forget(self); diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 2b2bbc6e9d6ae..f174a59b49a6b 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -624,7 +624,7 @@ pub trait MetadataExt { /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime_nsec(&self) -> i64; - /// Returns the blocksize for filesystem I/O. + /// Returns the block size for filesystem I/O. /// /// # Examples /// @@ -635,7 +635,7 @@ pub trait MetadataExt { /// /// fn main() -> io::Result<()> { /// let meta = fs::metadata("some_file")?; - /// let blocksize = meta.blksize(); + /// let block_size = meta.blksize(); /// Ok(()) /// } /// ``` diff --git a/src/libstd/sys/vxworks/fd.rs b/src/libstd/sys/vxworks/fd.rs index 7fa86f0db043f..7384cbae3a14c 100644 --- a/src/libstd/sys/vxworks/fd.rs +++ b/src/libstd/sys/vxworks/fd.rs @@ -29,7 +29,7 @@ impl FileDesc { self.fd } - /// Extracts the actual filedescriptor without closing it. + /// Extracts the actual file descriptor without closing it. pub fn into_raw(self) -> c_int { let fd = self.fd; mem::forget(self); diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs index 793daea43c215..2eed9e436a956 100644 --- a/src/libstd/sys/wasi/fs.rs +++ b/src/libstd/sys/wasi/fs.rs @@ -597,14 +597,14 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result { /// /// WASI has no fundamental capability to do this. All syscalls and operations /// are relative to already-open file descriptors. The C library, however, -/// manages a map of preopened file descriptors to their path, and then the C +/// manages a map of pre-opened file descriptors to their path, and then the C /// library provides an API to look at this. In other words, when you want to /// open a path `p`, you have to find a previously opened file descriptor in a /// global table and then see if `p` is relative to that file descriptor. /// /// This function, if successful, will return two items: /// -/// * The first is a `ManuallyDrop`. This represents a preopened file +/// * The first is a `ManuallyDrop`. This represents a pre-opened file /// descriptor which we don't have ownership of, but we can use. You shouldn't /// actually drop the `fd`. /// @@ -619,7 +619,7 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result { /// appropriate rights for performing `rights` actions. /// /// Note that this can fail if `p` doesn't look like it can be opened relative -/// to any preopened file descriptor. +/// to any pre-opened file descriptor. fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { let p = CString::new(p.as_os_str().as_bytes())?; unsafe { @@ -627,7 +627,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { let fd = __wasilibc_find_relpath(p.as_ptr(), &mut ret); if fd == -1 { let msg = format!( - "failed to find a preopened file descriptor \ + "failed to find a pre-opened file descriptor \ through which {:?} could be opened", p ); From 8561b67b6f263b6647f02d36e0824b6c54544bf0 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Sat, 18 Jul 2020 15:51:44 -0700 Subject: [PATCH 02/13] add a Backtrace::disabled function --- src/libstd/backtrace.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index e65775c1ced67..28acec79de084 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -291,6 +291,12 @@ impl Backtrace { Backtrace::create(Backtrace::force_capture as usize) } + /// Forcibly captures a disabled backtrace, regardless of environment + /// variable configuration. + pub fn disabled() -> Backtrace { + Backtrace { inner: Inner::Disabled }; + } + // Capture a backtrace which start just before the function addressed by // `ip` fn create(ip: usize) -> Backtrace { From 397c82bae15031f97bf12f0114834af1ba844b4f Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Sat, 18 Jul 2020 15:57:57 -0700 Subject: [PATCH 03/13] remove trailing semi --- src/libstd/backtrace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index 28acec79de084..b22d8164b36ab 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -294,7 +294,7 @@ impl Backtrace { /// Forcibly captures a disabled backtrace, regardless of environment /// variable configuration. pub fn disabled() -> Backtrace { - Backtrace { inner: Inner::Disabled }; + Backtrace { inner: Inner::Disabled } } // Capture a backtrace which start just before the function addressed by From 37dd7a023b8cef226c73bb9e17b37e379b4ffb48 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 21 Jul 2020 14:32:36 -0700 Subject: [PATCH 04/13] Remove Linux workarounds for missing CLOEXEC support Now that #74163 updated the minimum Linux kernel to 2.6.32, we can assume the availability of APIs that open file descriptors that are already set to close on exec, including the flags `O_CLOEXEC`, `SOCK_CLOEXEC`, and `F_DUPFD_CLOEXEC`. --- src/libstd/sys/unix/fd.rs | 48 ++--------------- src/libstd/sys/unix/fs.rs | 51 +----------------- src/libstd/sys/unix/net.rs | 103 +++++++++++++++--------------------- src/libstd/sys/unix/pipe.rs | 43 +++++---------- 4 files changed, 58 insertions(+), 187 deletions(-) diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index c481ca8961f86..451ebd97c3f0b 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -3,7 +3,6 @@ use crate::cmp; use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read}; use crate::mem; -use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::cvt; use crate::sys_common::AsInner; @@ -223,50 +222,9 @@ impl FileDesc { pub fn duplicate(&self) -> io::Result { // We want to atomically duplicate this file descriptor and set the // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This - // flag, however, isn't supported on older Linux kernels (earlier than - // 2.6.24). - // - // To detect this and ensure that CLOEXEC is still set, we - // follow a strategy similar to musl [1] where if passing - // F_DUPFD_CLOEXEC causes `fcntl` to return EINVAL it means it's not - // supported (the third parameter, 0, is always valid), so we stop - // trying that. - // - // Also note that Android doesn't have F_DUPFD_CLOEXEC, but get it to - // resolve so we at least compile this. - // - // [1]: http://comments.gmane.org/gmane.linux.lib.musl.general/2963 - #[cfg(any(target_os = "android", target_os = "haiku"))] - use libc::F_DUPFD as F_DUPFD_CLOEXEC; - #[cfg(not(any(target_os = "android", target_os = "haiku")))] - use libc::F_DUPFD_CLOEXEC; - - let make_filedesc = |fd| { - let fd = FileDesc::new(fd); - fd.set_cloexec()?; - Ok(fd) - }; - static TRY_CLOEXEC: AtomicBool = AtomicBool::new(!cfg!(target_os = "android")); - let fd = self.raw(); - if TRY_CLOEXEC.load(Ordering::Relaxed) { - match cvt(unsafe { libc::fcntl(fd, F_DUPFD_CLOEXEC, 0) }) { - // We *still* call the `set_cloexec` method as apparently some - // linux kernel at some point stopped setting CLOEXEC even - // though it reported doing so on F_DUPFD_CLOEXEC. - Ok(fd) => { - return Ok(if cfg!(target_os = "linux") { - make_filedesc(fd)? - } else { - FileDesc::new(fd) - }); - } - Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => { - TRY_CLOEXEC.store(false, Ordering::Relaxed); - } - Err(e) => return Err(e), - } - } - cvt(unsafe { libc::fcntl(fd, libc::F_DUPFD, 0) }).and_then(make_filedesc) + // is a POSIX flag that was added to Linux in 2.6.24. + let fd = cvt(unsafe { libc::fcntl(self.raw(), libc::F_DUPFD_CLOEXEC, 0) })?; + Ok(FileDesc::new(fd)) } } diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 29cdbf05354fb..acb18e6d064e6 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -708,56 +708,7 @@ impl File { // However, since this is a variadic function, C integer promotion rules mean that on // the ABI level, this still gets passed as `c_int` (aka `u32` on Unix platforms). let fd = cvt_r(|| unsafe { open64(path.as_ptr(), flags, opts.mode as c_int) })?; - let fd = FileDesc::new(fd); - - // Currently the standard library supports Linux 2.6.18 which did not - // have the O_CLOEXEC flag (passed above). If we're running on an older - // Linux kernel then the flag is just ignored by the OS. After we open - // the first file, we check whether it has CLOEXEC set. If it doesn't, - // we will explicitly ask for a CLOEXEC fd for every further file we - // open, if it does, we will skip that step. - // - // The CLOEXEC flag, however, is supported on versions of macOS/BSD/etc - // that we support, so we only do this on Linux currently. - #[cfg(target_os = "linux")] - fn ensure_cloexec(fd: &FileDesc) -> io::Result<()> { - use crate::sync::atomic::{AtomicUsize, Ordering}; - - const OPEN_CLOEXEC_UNKNOWN: usize = 0; - const OPEN_CLOEXEC_SUPPORTED: usize = 1; - const OPEN_CLOEXEC_NOTSUPPORTED: usize = 2; - static OPEN_CLOEXEC: AtomicUsize = AtomicUsize::new(OPEN_CLOEXEC_UNKNOWN); - - let need_to_set; - match OPEN_CLOEXEC.load(Ordering::Relaxed) { - OPEN_CLOEXEC_UNKNOWN => { - need_to_set = !fd.get_cloexec()?; - OPEN_CLOEXEC.store( - if need_to_set { - OPEN_CLOEXEC_NOTSUPPORTED - } else { - OPEN_CLOEXEC_SUPPORTED - }, - Ordering::Relaxed, - ); - } - OPEN_CLOEXEC_SUPPORTED => need_to_set = false, - OPEN_CLOEXEC_NOTSUPPORTED => need_to_set = true, - _ => unreachable!(), - } - if need_to_set { - fd.set_cloexec()?; - } - Ok(()) - } - - #[cfg(not(target_os = "linux"))] - fn ensure_cloexec(_: &FileDesc) -> io::Result<()> { - Ok(()) - } - - ensure_cloexec(&fd)?; - Ok(File(fd)) + Ok(File(FileDesc::new(fd))) } pub fn file_attr(&self) -> io::Result { diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 3717c660b575d..011325fddc5b9 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -54,31 +54,26 @@ impl Socket { pub fn new_raw(fam: c_int, ty: c_int) -> io::Result { unsafe { - // On linux we first attempt to pass the SOCK_CLOEXEC flag to - // atomically create the socket and set it as CLOEXEC. Support for - // this option, however, was added in 2.6.27, and we still support - // 2.6.18 as a kernel, so if the returned error is EINVAL we - // fallthrough to the fallback. - #[cfg(target_os = "linux")] - { - match cvt(libc::socket(fam, ty | libc::SOCK_CLOEXEC, 0)) { - Ok(fd) => return Ok(Socket(FileDesc::new(fd))), - Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {} - Err(e) => return Err(e), - } - } - - let fd = cvt(libc::socket(fam, ty, 0))?; - let fd = FileDesc::new(fd); - fd.set_cloexec()?; - let socket = Socket(fd); + cfg_if::cfg_if! { + if #[cfg(target_os = "linux")] { + // On Linux we pass the SOCK_CLOEXEC flag to atomically create + // the socket and set it as CLOEXEC, added in 2.6.27. + let fd = cvt(libc::socket(fam, ty | libc::SOCK_CLOEXEC, 0))?; + Ok(Socket(FileDesc::new(fd))) + } else { + let fd = cvt(libc::socket(fam, ty, 0))?; + let fd = FileDesc::new(fd); + fd.set_cloexec()?; + let socket = Socket(fd); - // macOS and iOS use `SO_NOSIGPIPE` as a `setsockopt` - // flag to disable `SIGPIPE` emission on socket. - #[cfg(target_vendor = "apple")] - setsockopt(&socket, libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1)?; + // macOS and iOS use `SO_NOSIGPIPE` as a `setsockopt` + // flag to disable `SIGPIPE` emission on socket. + #[cfg(target_vendor = "apple")] + setsockopt(&socket, libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1)?; - Ok(socket) + Ok(socket) + } + } } } @@ -86,24 +81,20 @@ impl Socket { unsafe { let mut fds = [0, 0]; - // Like above, see if we can set cloexec atomically - #[cfg(target_os = "linux")] - { - match cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr())) { - Ok(_) => { - return Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1])))); - } - Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {} - Err(e) => return Err(e), + cfg_if::cfg_if! { + if #[cfg(target_os = "linux")] { + // Like above, set cloexec atomically + cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr()))?; + Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1])))) + } else { + cvt(libc::socketpair(fam, ty, 0, fds.as_mut_ptr()))?; + let a = FileDesc::new(fds[0]); + let b = FileDesc::new(fds[1]); + a.set_cloexec()?; + b.set_cloexec()?; + Ok((Socket(a), Socket(b))) } } - - cvt(libc::socketpair(fam, ty, 0, fds.as_mut_ptr()))?; - let a = FileDesc::new(fds[0]); - let b = FileDesc::new(fds[1]); - a.set_cloexec()?; - b.set_cloexec()?; - Ok((Socket(a), Socket(b))) } } @@ -177,30 +168,20 @@ impl Socket { pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t) -> io::Result { // Unfortunately the only known way right now to accept a socket and // atomically set the CLOEXEC flag is to use the `accept4` syscall on - // Linux. This was added in 2.6.28, however, and because we support - // 2.6.18 we must detect this support dynamically. - #[cfg(target_os = "linux")] - { - syscall! { - fn accept4( - fd: c_int, - addr: *mut sockaddr, - addr_len: *mut socklen_t, - flags: c_int - ) -> c_int - } - let res = cvt_r(|| unsafe { accept4(self.0.raw(), storage, len, libc::SOCK_CLOEXEC) }); - match res { - Ok(fd) => return Ok(Socket(FileDesc::new(fd))), - Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {} - Err(e) => return Err(e), + // Linux. This was added in 2.6.28, glibc 2.10 and musl 0.9.5. + cfg_if::cfg_if! { + if #[cfg(target_os = "linux")] { + let fd = cvt_r(|| unsafe { + libc::accept4(self.0.raw(), storage, len, libc::SOCK_CLOEXEC) + })?; + Ok(Socket(FileDesc::new(fd))) + } else { + let fd = cvt_r(|| unsafe { libc::accept(self.0.raw(), storage, len) })?; + let fd = FileDesc::new(fd); + fd.set_cloexec()?; + Ok(Socket(fd)) } } - - let fd = cvt_r(|| unsafe { libc::accept(self.0.raw(), storage, len) })?; - let fd = FileDesc::new(fd); - fd.set_cloexec()?; - Ok(Socket(fd)) } pub fn duplicate(&self) -> io::Result { diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index f2a2eabef9132..02a43923708a8 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -1,11 +1,8 @@ use crate::io::{self, IoSlice, IoSliceMut}; use crate::mem; -use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::fd::FileDesc; use crate::sys::{cvt, cvt_r}; -use libc::c_int; - //////////////////////////////////////////////////////////////////////////////// // Anonymous pipes //////////////////////////////////////////////////////////////////////////////// @@ -13,15 +10,11 @@ use libc::c_int; pub struct AnonPipe(FileDesc); pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { - syscall! { fn pipe2(fds: *mut c_int, flags: c_int) -> c_int } - static INVALID: AtomicBool = AtomicBool::new(false); - let mut fds = [0; 2]; // Unfortunately the only known way right now to create atomically set the // CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in - // 2.6.27, however, and because we support 2.6.18 we must detect this - // support dynamically. + // 2.6.27, glibc 2.9 and musl 0.9.3. if cfg!(any( target_os = "dragonfly", target_os = "freebsd", @@ -29,30 +22,18 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { target_os = "netbsd", target_os = "openbsd", target_os = "redox" - )) && !INVALID.load(Ordering::SeqCst) - { - // Note that despite calling a glibc function here we may still - // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to - // emulate on older kernels, so if you happen to be running on - // an older kernel you may see `pipe2` as a symbol but still not - // see the syscall. - match cvt(unsafe { pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) }) { - Ok(_) => { - return Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1])))); - } - Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => { - INVALID.store(true, Ordering::SeqCst); - } - Err(e) => return Err(e), - } + )) { + cvt(unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) })?; + Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1])))) + } else { + cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?; + + let fd0 = FileDesc::new(fds[0]); + let fd1 = FileDesc::new(fds[1]); + fd0.set_cloexec()?; + fd1.set_cloexec()?; + Ok((AnonPipe(fd0), AnonPipe(fd1))) } - cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?; - - let fd0 = FileDesc::new(fds[0]); - let fd1 = FileDesc::new(fds[1]); - fd0.set_cloexec()?; - fd1.set_cloexec()?; - Ok((AnonPipe(fd0), AnonPipe(fd1))) } impl AnonPipe { From a95e6bb91673e250e35886ff09a2ba023e536ff6 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 22 Jul 2020 22:58:54 +0200 Subject: [PATCH 05/13] require type defaults to be after const generic parameters as if this is currently possible. HA! --- src/librustc_ast_passes/ast_validation.rs | 25 ++++++++++++++----- .../ui/const-generics/defaults/wrong-order.rs | 8 ++++++ .../defaults/wrong-order.stderr | 19 ++++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/wrong-order.rs create mode 100644 src/test/ui/const-generics/defaults/wrong-order.stderr diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 975881d9a0ac0..f25f5d563ebc8 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -1118,13 +1118,26 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_generics(&mut self, generics: &'a Generics) { let mut prev_ty_default = None; for param in &generics.params { - if let GenericParamKind::Type { ref default, .. } = param.kind { - if default.is_some() { + match param.kind { + GenericParamKind::Lifetime => (), + GenericParamKind::Type { default: Some(_), .. } => { prev_ty_default = Some(param.ident.span); - } else if let Some(span) = prev_ty_default { - self.err_handler() - .span_err(span, "type parameters with a default must be trailing"); - break; + } + GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { + if let Some(span) = prev_ty_default { + let mut err = self.err_handler().struct_span_err( + span, + "type parameters with a default must be trailing", + ); + if matches!(param.kind, GenericParamKind::Const { .. }) { + err.note( + "using type defaults and const parameters \ + in the same parameter listing is currently not possible", + ); + } + err.emit(); + break; + } } } } diff --git a/src/test/ui/const-generics/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs new file mode 100644 index 0000000000000..7f17c6358b7b6 --- /dev/null +++ b/src/test/ui/const-generics/defaults/wrong-order.rs @@ -0,0 +1,8 @@ +#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete + +struct A { + //~^ ERROR type parameters with a default must be trailing + arg: T, +} + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/wrong-order.stderr b/src/test/ui/const-generics/defaults/wrong-order.stderr new file mode 100644 index 0000000000000..7d7cd0fa36f4f --- /dev/null +++ b/src/test/ui/const-generics/defaults/wrong-order.stderr @@ -0,0 +1,19 @@ +error: type parameters with a default must be trailing + --> $DIR/wrong-order.rs:3:10 + | +LL | struct A { + | ^ + | + = note: using type defaults and const parameters in the same parameter listing is currently not possible + +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/wrong-order.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information + +error: aborting due to previous error; 1 warning emitted + From 618aeec51f61fb6d80cd4fde9e5fc3b9714ca72b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 22 Jul 2020 14:51:12 -0700 Subject: [PATCH 06/13] Improve codegen for unchecked float casts on wasm This commit improves codegen for unchecked casts on WebAssembly targets to use the singluar `iNN.trunc_fMM_{u,s}` instructions. Previously rustc would codegen a bare `fptosi` and `fptoui` for float casts but for WebAssembly targets the codegen for these instructions is quite large. This large codegen is due to the fact that LLVM can speculate these instructions so the trapping behavior of WebAssembly needs to be protected against in case they're speculated. The change here is to update the codegen for the unchecked cast intrinsics to have a wasm-specific case where they call the appropriate LLVM intrinsic to generate the right wasm instruction. The intrinsic is explicitly opting-in to undefined behavior so a trap here for out-of-bounds inputs on wasm should be acceptable. cc #73591 --- src/librustc_codegen_llvm/context.rs | 8 +++ src/librustc_codegen_llvm/intrinsic.rs | 75 +++++++++++++++++------ src/test/codegen/unchecked-float-casts.rs | 1 + src/test/codegen/wasm_casts_trapping.rs | 28 +++------ 4 files changed, 74 insertions(+), 38 deletions(-) diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index a07f6c64edcb1..33a3cdbfa9b44 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -510,6 +510,14 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.wasm.trunc.saturate.signed.i32.f64", fn(t_f64) -> t_i32); ifn!("llvm.wasm.trunc.saturate.signed.i64.f32", fn(t_f32) -> t_i64); ifn!("llvm.wasm.trunc.saturate.signed.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.wasm.trunc.unsigned.i32.f32", fn(t_f32) -> t_i32); + ifn!("llvm.wasm.trunc.unsigned.i32.f64", fn(t_f64) -> t_i32); + ifn!("llvm.wasm.trunc.unsigned.i64.f32", fn(t_f32) -> t_i64); + ifn!("llvm.wasm.trunc.unsigned.i64.f64", fn(t_f64) -> t_i64); + ifn!("llvm.wasm.trunc.signed.i32.f32", fn(t_f32) -> t_i32); + ifn!("llvm.wasm.trunc.signed.i32.f64", fn(t_f64) -> t_i32); + ifn!("llvm.wasm.trunc.signed.i64.f32", fn(t_f32) -> t_i64); + ifn!("llvm.wasm.trunc.signed.i64.f64", fn(t_f64) -> t_i64); ifn!("llvm.trap", fn() -> void); ifn!("llvm.debugtrap", fn() -> void); diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 2e5929a433de0..11b1c95c58b3e 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -629,27 +629,24 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } sym::float_to_int_unchecked => { - if float_type_width(arg_tys[0]).is_none() { - span_invalid_monomorphization_error( - tcx.sess, - span, - &format!( - "invalid monomorphization of `float_to_int_unchecked` \ + let float_width = match float_type_width(arg_tys[0]) { + Some(width) => width, + None => { + span_invalid_monomorphization_error( + tcx.sess, + span, + &format!( + "invalid monomorphization of `float_to_int_unchecked` \ intrinsic: expected basic float type, \ found `{}`", - arg_tys[0] - ), - ); - return; - } - match int_type_width_signed(ret_ty, self.cx) { - Some((width, signed)) => { - if signed { - self.fptosi(args[0].immediate(), self.cx.type_ix(width)) - } else { - self.fptoui(args[0].immediate(), self.cx.type_ix(width)) - } + arg_tys[0] + ), + ); + return; } + }; + let (width, signed) = match int_type_width_signed(ret_ty, self.cx) { + Some(pair) => pair, None => { span_invalid_monomorphization_error( tcx.sess, @@ -663,7 +660,49 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { ); return; } + }; + + // The LLVM backend can reorder and speculate `fptosi` and + // `fptoui`, so on WebAssembly the codegen for this instruction + // is quite heavyweight. To avoid this heavyweight codegen we + // instead use the raw wasm intrinsics which will lower to one + // instruction in WebAssembly (`iNN.trunc_fMM_{s,u}`). This one + // instruction will trap if the operand is out of bounds, but + // that's ok since this intrinsic is UB if the operands are out + // of bounds, so the behavior can be different on WebAssembly + // than other targets. + // + // Note, however, that when the `nontrapping-fptoint` feature is + // enabled in LLVM then LLVM will lower `fptosi` to + // `iNN.trunc_sat_fMM_{s,u}`, so if that's the case we don't + // bother with intrinsics. + let mut result = None; + if self.sess().target.target.arch == "wasm32" + && !self.sess().target_features.contains(&sym::nontrapping_dash_fptoint) + { + let name = match (width, float_width, signed) { + (32, 32, true) => Some("llvm.wasm.trunc.signed.i32.f32"), + (32, 64, true) => Some("llvm.wasm.trunc.signed.i32.f64"), + (64, 32, true) => Some("llvm.wasm.trunc.signed.i64.f32"), + (64, 64, true) => Some("llvm.wasm.trunc.signed.i64.f64"), + (32, 32, false) => Some("llvm.wasm.trunc.unsigned.i32.f32"), + (32, 64, false) => Some("llvm.wasm.trunc.unsigned.i32.f64"), + (64, 32, false) => Some("llvm.wasm.trunc.unsigned.i64.f32"), + (64, 64, false) => Some("llvm.wasm.trunc.unsigned.i64.f64"), + _ => None, + }; + if let Some(name) = name { + let intrinsic = self.get_intrinsic(name); + result = Some(self.call(intrinsic, &[args[0].immediate()], None)); + } } + result.unwrap_or_else(|| { + if signed { + self.fptosi(args[0].immediate(), self.cx.type_ix(width)) + } else { + self.fptoui(args[0].immediate(), self.cx.type_ix(width)) + } + }) } sym::discriminant_value => { diff --git a/src/test/codegen/unchecked-float-casts.rs b/src/test/codegen/unchecked-float-casts.rs index 789feea12d6d7..4e3bfcd439744 100644 --- a/src/test/codegen/unchecked-float-casts.rs +++ b/src/test/codegen/unchecked-float-casts.rs @@ -2,6 +2,7 @@ // unchecked intrinsics. // compile-flags: -C opt-level=3 +// ignore-wasm32 the wasm target is tested in `wasm_casts_*` #![crate_type = "lib"] diff --git a/src/test/codegen/wasm_casts_trapping.rs b/src/test/codegen/wasm_casts_trapping.rs index 45b905190493a..b7f8522fdfb03 100644 --- a/src/test/codegen/wasm_casts_trapping.rs +++ b/src/test/codegen/wasm_casts_trapping.rs @@ -38,7 +38,6 @@ pub fn cast_f32_i32(a: f32) -> i32 { a as _ } - // CHECK-LABEL: @cast_f64_u64 #[no_mangle] pub fn cast_f64_u64(a: f64) -> u64 { @@ -84,13 +83,10 @@ pub fn cast_f32_u8(a: f32) -> u8 { a as _ } - - // CHECK-LABEL: @cast_unchecked_f64_i64 #[no_mangle] pub unsafe fn cast_unchecked_f64_i64(a: f64) -> i64 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptosi double {{.*}} to i64 + // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}} // CHECK-NEXT: ret i64 {{.*}} a.to_int_unchecked() } @@ -98,8 +94,7 @@ pub unsafe fn cast_unchecked_f64_i64(a: f64) -> i64 { // CHECK-LABEL: @cast_unchecked_f64_i32 #[no_mangle] pub unsafe fn cast_unchecked_f64_i32(a: f64) -> i32 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptosi double {{.*}} to i32 + // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}} // CHECK-NEXT: ret i32 {{.*}} a.to_int_unchecked() } @@ -107,8 +102,7 @@ pub unsafe fn cast_unchecked_f64_i32(a: f64) -> i32 { // CHECK-LABEL: @cast_unchecked_f32_i64 #[no_mangle] pub unsafe fn cast_unchecked_f32_i64(a: f32) -> i64 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptosi float {{.*}} to i64 + // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}} // CHECK-NEXT: ret i64 {{.*}} a.to_int_unchecked() } @@ -116,18 +110,15 @@ pub unsafe fn cast_unchecked_f32_i64(a: f32) -> i64 { // CHECK-LABEL: @cast_unchecked_f32_i32 #[no_mangle] pub unsafe fn cast_unchecked_f32_i32(a: f32) -> i32 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptosi float {{.*}} to i32 + // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}} // CHECK-NEXT: ret i32 {{.*}} a.to_int_unchecked() } - // CHECK-LABEL: @cast_unchecked_f64_u64 #[no_mangle] pub unsafe fn cast_unchecked_f64_u64(a: f64) -> u64 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptoui double {{.*}} to i64 + // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}} // CHECK-NEXT: ret i64 {{.*}} a.to_int_unchecked() } @@ -135,8 +126,7 @@ pub unsafe fn cast_unchecked_f64_u64(a: f64) -> u64 { // CHECK-LABEL: @cast_unchecked_f64_u32 #[no_mangle] pub unsafe fn cast_unchecked_f64_u32(a: f64) -> u32 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptoui double {{.*}} to i32 + // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}} // CHECK-NEXT: ret i32 {{.*}} a.to_int_unchecked() } @@ -144,8 +134,7 @@ pub unsafe fn cast_unchecked_f64_u32(a: f64) -> u32 { // CHECK-LABEL: @cast_unchecked_f32_u64 #[no_mangle] pub unsafe fn cast_unchecked_f32_u64(a: f32) -> u64 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptoui float {{.*}} to i64 + // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}} // CHECK-NEXT: ret i64 {{.*}} a.to_int_unchecked() } @@ -153,8 +142,7 @@ pub unsafe fn cast_unchecked_f32_u64(a: f32) -> u64 { // CHECK-LABEL: @cast_unchecked_f32_u32 #[no_mangle] pub unsafe fn cast_unchecked_f32_u32(a: f32) -> u32 { - // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}} - // CHECK: fptoui float {{.*}} to i32 + // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}} // CHECK-NEXT: ret i32 {{.*}} a.to_int_unchecked() } From ae06e13b8de23722d8bf2fb0143581df07848aa8 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 22 Jul 2020 16:38:58 -0700 Subject: [PATCH 07/13] Move the pipe2 call behind a hard target `#[cfg]` --- src/libstd/sys/unix/os.rs | 1 + src/libstd/sys/unix/pipe.rs | 44 +++++++++++++++++++------------------ src/libstd/sys/unix/weak.rs | 5 +++++ 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index a9cd5094997bd..2fcb5b9c4e66e 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -71,6 +71,7 @@ pub fn errno() -> i32 { /// Sets the platform-specific value of errno #[cfg(all(not(target_os = "linux"), not(target_os = "dragonfly")))] // needed for readdir and syscall! +#[allow(dead_code)] // but not all target cfgs actually end up using it pub fn set_errno(e: i32) { unsafe { *errno_location() = e as c_int } } diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 02a43923708a8..7ae37bdda70bd 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -12,27 +12,29 @@ pub struct AnonPipe(FileDesc); pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { let mut fds = [0; 2]; - // Unfortunately the only known way right now to create atomically set the - // CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in - // 2.6.27, glibc 2.9 and musl 0.9.3. - if cfg!(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", - target_os = "redox" - )) { - cvt(unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) })?; - Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1])))) - } else { - cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?; - - let fd0 = FileDesc::new(fds[0]); - let fd1 = FileDesc::new(fds[1]); - fd0.set_cloexec()?; - fd1.set_cloexec()?; - Ok((AnonPipe(fd0), AnonPipe(fd1))) + // The only known way right now to create atomically set the CLOEXEC flag is + // to use the `pipe2` syscall. This was added to Linux in 2.6.27, glibc 2.9 + // and musl 0.9.3, and some other targets also have it. + cfg_if::cfg_if! { + if #[cfg(any( + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_os = "openbsd", + target_os = "redox" + ))] { + cvt(unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) })?; + Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1])))) + } else { + cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?; + + let fd0 = FileDesc::new(fds[0]); + let fd1 = FileDesc::new(fds[1]); + fd0.set_cloexec()?; + fd1.set_cloexec()?; + Ok((AnonPipe(fd0), AnonPipe(fd1))) + } } } diff --git a/src/libstd/sys/unix/weak.rs b/src/libstd/sys/unix/weak.rs index 08cbe59617465..f4b33a00f7c85 100644 --- a/src/libstd/sys/unix/weak.rs +++ b/src/libstd/sys/unix/weak.rs @@ -16,6 +16,11 @@ //! symbol, but that caused Debian to detect an unnecessarily strict versioned //! dependency on libc6 (#23628). +// There are a variety of `#[cfg]`s controlling which targets are involved in +// each instance of `weak!` and `syscall!`. Rather than trying to unify all of +// that, we'll just allow that some unix targets don't use this module at all. +#![allow(dead_code, unused_macros)] + use crate::ffi::CStr; use crate::marker; use crate::mem; From 83094ea11a4c1dca34fd5602c8c56e8829bf51ee Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Mon, 20 Jul 2020 12:25:12 +0200 Subject: [PATCH 08/13] one more Path::with_extension example, to demonstrate behavior --- src/libstd/path.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index f14a9ff72f62f..392c815ef2803 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -2244,6 +2244,9 @@ impl Path { /// /// let path = Path::new("foo.rs"); /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt")); + /// + /// let path = Path::new("foo.tar.gz"); + /// assert_eq!(path.with_extension(""), PathBuf::from("foo.tar")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_extension>(&self, extension: S) -> PathBuf { From 50347b84dd0c08ff23bd010dc567a7c27944d029 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Wed, 22 Jul 2020 17:19:02 -0700 Subject: [PATCH 09/13] Update src/libstd/backtrace.rs Co-authored-by: David Tolnay --- src/libstd/backtrace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index b22d8164b36ab..09f83ea5fca81 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -293,7 +293,7 @@ impl Backtrace { /// Forcibly captures a disabled backtrace, regardless of environment /// variable configuration. - pub fn disabled() -> Backtrace { + pub const fn disabled() -> Backtrace { Backtrace { inner: Inner::Disabled } } From 47d0d2ff63f11f651e704b2d4d0471a6b2af4b7d Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 22 Jul 2020 15:17:50 +0000 Subject: [PATCH 10/13] Make str point to primitive page --- src/liballoc/string.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 15f10df9a45cc..a7123e0dd7d5d 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -268,7 +268,8 @@ use crate::vec::Vec; /// /// Here, there's no need to allocate more memory inside the loop. /// -/// [`&str`]: str +/// [`str`]: ../../std/primitive.str.html +/// [`&str`]: ../../std/primitive.str.html /// [`Deref`]: core::ops::Deref /// [`as_str()`]: String::as_str #[derive(PartialOrd, Eq, Ord)] From d19b12df4157dc0a4220e7b1da023ddeeb6dd503 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 23 Jul 2020 02:42:37 +0000 Subject: [PATCH 11/13] Prefer type@str --- src/liballoc/string.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index a7123e0dd7d5d..f41c8c5a55910 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -65,7 +65,7 @@ use crate::vec::Vec; /// /// # Examples /// -/// You can create a `String` from [a literal string][str] with [`String::from`]: +/// You can create a `String` from [a literal string][`str`] with [`String::from`]: /// /// [`String::from`]: From::from /// @@ -268,8 +268,8 @@ use crate::vec::Vec; /// /// Here, there's no need to allocate more memory inside the loop. /// -/// [`str`]: ../../std/primitive.str.html -/// [`&str`]: ../../std/primitive.str.html +/// [`str`]: type@str +/// [`&str`]: type@str /// [`Deref`]: core::ops::Deref /// [`as_str()`]: String::as_str #[derive(PartialOrd, Eq, Ord)] From 0de7fade1053f553f83ac603079602d50ab14e19 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 23 Jul 2020 02:49:40 +0000 Subject: [PATCH 12/13] Prefer constant over function --- src/libstd/sys/unix/fd.rs | 33 +++++++++++++++++---------------- src/libstd/sys/vxworks/fd.rs | 20 +++++++++----------- src/libstd/sys/vxworks/time.rs | 2 +- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index c481ca8961f86..b746b0feb623b 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -7,24 +7,25 @@ use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::cvt; use crate::sys_common::AsInner; -use libc::{c_int, c_void, ssize_t}; +use libc::{c_int, c_void}; #[derive(Debug)] pub struct FileDesc { fd: c_int, } -fn max_len() -> usize { - // The maximum read limit on most posix-like systems is `SSIZE_MAX`, - // with the man page quoting that if the count of bytes to read is - // greater than `SSIZE_MAX` the result is "unspecified". - // - // On macOS, however, apparently the 64-bit libc is either buggy or - // intentionally showing odd behavior by rejecting any read with a size - // larger than or equal to INT_MAX. To handle both of these the read - // size is capped on both platforms. - if cfg!(target_os = "macos") { ::MAX as usize - 1 } else { ::MAX as usize } -} +// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`, +// with the man page quoting that if the count of bytes to read is +// greater than `SSIZE_MAX` the result is "unspecified". +// +// On macOS, however, apparently the 64-bit libc is either buggy or +// intentionally showing odd behavior by rejecting any read with a size +// larger than or equal to INT_MAX. To handle both of these the read +// size is capped on both platforms. +#[cfg(target_os = "macos")] +const READ_LIMIT: usize = c_int::MAX as usize - 1; +#[cfg(not(target_os = "macos"))] +const READ_LIMIT: usize = libc::ssize_t::MAX as usize; impl FileDesc { pub fn new(fd: c_int) -> FileDesc { @@ -44,7 +45,7 @@ impl FileDesc { pub fn read(&self, buf: &mut [u8]) -> io::Result { let ret = cvt(unsafe { - libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), max_len())) + libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT)) })?; Ok(ret as usize) } @@ -92,7 +93,7 @@ impl FileDesc { cvt_pread64( self.fd, buf.as_mut_ptr() as *mut c_void, - cmp::min(buf.len(), max_len()), + cmp::min(buf.len(), READ_LIMIT), offset as i64, ) .map(|n| n as usize) @@ -101,7 +102,7 @@ impl FileDesc { pub fn write(&self, buf: &[u8]) -> io::Result { let ret = cvt(unsafe { - libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), max_len())) + libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT)) })?; Ok(ret as usize) } @@ -144,7 +145,7 @@ impl FileDesc { cvt_pwrite64( self.fd, buf.as_ptr() as *const c_void, - cmp::min(buf.len(), max_len()), + cmp::min(buf.len(), READ_LIMIT), offset as i64, ) .map(|n| n as usize) diff --git a/src/libstd/sys/vxworks/fd.rs b/src/libstd/sys/vxworks/fd.rs index 7fa86f0db043f..ea186846929be 100644 --- a/src/libstd/sys/vxworks/fd.rs +++ b/src/libstd/sys/vxworks/fd.rs @@ -13,12 +13,10 @@ pub struct FileDesc { fd: c_int, } -fn max_len() -> usize { - // The maximum read limit on most posix-like systems is `SSIZE_MAX`, - // with the man page quoting that if the count of bytes to read is - // greater than `SSIZE_MAX` the result is "unspecified". - ::MAX as usize -} +// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`, +// with the man page quoting that if the count of bytes to read is +// greater than `SSIZE_MAX` the result is "unspecified". +const READ_LIMIT: usize = ssize_t::MAX as usize; impl FileDesc { pub fn new(fd: c_int) -> FileDesc { @@ -29,7 +27,7 @@ impl FileDesc { self.fd } - /// Extracts the actual filedescriptor without closing it. + /// Extracts the actual file descriptor without closing it. pub fn into_raw(self) -> c_int { let fd = self.fd; mem::forget(self); @@ -38,7 +36,7 @@ impl FileDesc { pub fn read(&self, buf: &mut [u8]) -> io::Result { let ret = cvt(unsafe { - libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), max_len())) + libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT)) })?; Ok(ret as usize) } @@ -79,7 +77,7 @@ impl FileDesc { cvt_pread( self.fd, buf.as_mut_ptr() as *mut c_void, - cmp::min(buf.len(), max_len()), + cmp::min(buf.len(), READ_LIMIT), offset as i64, ) .map(|n| n as usize) @@ -88,7 +86,7 @@ impl FileDesc { pub fn write(&self, buf: &[u8]) -> io::Result { let ret = cvt(unsafe { - libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), max_len())) + libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT)) })?; Ok(ret as usize) } @@ -124,7 +122,7 @@ impl FileDesc { cvt_pwrite( self.fd, buf.as_ptr() as *const c_void, - cmp::min(buf.len(), max_len()), + cmp::min(buf.len(), READ_LIMIT), offset as i64, ) .map(|n| n as usize) diff --git a/src/libstd/sys/vxworks/time.rs b/src/libstd/sys/vxworks/time.rs index 8365c9ee9c995..8f46f4d284f0b 100644 --- a/src/libstd/sys/vxworks/time.rs +++ b/src/libstd/sys/vxworks/time.rs @@ -1,6 +1,6 @@ use crate::cmp::Ordering; use crate::time::Duration; -use ::core::hash::{Hash, Hasher}; +use core::hash::{Hash, Hasher}; pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; use crate::convert::TryInto; From 2f565967b056335659ff1dfc2108c746f4ac8af3 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 23 Jul 2020 08:06:42 +0200 Subject: [PATCH 13/13] tweak wording Co-authored-by: varkor --- src/librustc_ast_passes/ast_validation.rs | 2 +- src/test/ui/const-generics/defaults/wrong-order.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index f25f5d563ebc8..daf3e23d6a123 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -1132,7 +1132,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if matches!(param.kind, GenericParamKind::Const { .. }) { err.note( "using type defaults and const parameters \ - in the same parameter listing is currently not possible", + in the same parameter list is currently not permitted", ); } err.emit(); diff --git a/src/test/ui/const-generics/defaults/wrong-order.stderr b/src/test/ui/const-generics/defaults/wrong-order.stderr index 7d7cd0fa36f4f..283f6656121c3 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.stderr @@ -4,7 +4,7 @@ error: type parameters with a default must be trailing LL | struct A { | ^ | - = note: using type defaults and const parameters in the same parameter listing is currently not possible + = note: using type defaults and const parameters in the same parameter list is currently not permitted warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/wrong-order.rs:1:12