From 8b8091d370fa31844d6ed55f4ccdd32e5dbd20f9 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie <ecstaticmorse@gmail.com> Date: Fri, 6 Apr 2018 00:34:45 -0700 Subject: [PATCH 01/19] Rewrite docs for `std::ptr` - Add links to the GNU libc docs for `memmove`, `memcpy`, and `memset`, as well as internally linking to other functions in `std::ptr` - List sources of UB for all functions. - Add example to `ptr::drop_in_place` and compares it to `ptr::read`. - Add examples which more closely mirror real world uses for the functions in `std::ptr`. Also, move the reimplementation of `mem::swap` to the examples of `ptr::read` and use a more interesting example for `copy_nonoverlapping`. - Change module level description --- src/libcore/intrinsics.rs | 177 +++++++++++++--- src/libcore/ptr.rs | 421 +++++++++++++++++++++++++++++++------- 2 files changed, 496 insertions(+), 102 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 83274682250b0..d6bd2b868554c 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -959,59 +959,134 @@ extern "rust-intrinsic" { /// value is not necessarily valid to be used to actually access memory. pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T; - /// Copies `count * size_of<T>` bytes from `src` to `dst`. The source - /// and destination may *not* overlap. + /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source + /// and destination must *not* overlap. /// - /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`. + /// For regions of memory which might overlap, use [`copy`] instead. + /// + /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`]. + /// + /// [`copy`]: ./fn.copy.html + /// [`memcpy`]: https://www.gnu.org/software/libc/manual/html_node/Copying-Strings-and-Arrays.html#index-memcpy /// /// # Safety /// - /// Beyond requiring that the program must be allowed to access both regions - /// of memory, it is Undefined Behavior for source and destination to - /// overlap. Care must also be taken with the ownership of `src` and - /// `dst`. This method semantically moves the values of `src` into `dst`. - /// However it does not drop the contents of `dst`, or prevent the contents - /// of `src` from being dropped or used. + /// `copy_nonoverlapping` is unsafe because it dereferences a raw pointer. + /// The caller must ensure that `src` points to a valid sequence of type + /// `T`. + /// + /// # [Undefined Behavior] + /// + /// Behavior is undefined if any of the following conditions are violated: + /// + /// * The region of memory which begins at `src` and has a length of + /// `count * size_of::<T>()` bytes must be *both* valid and initialized. + /// + /// * The region of memory which begins at `dst` and has a length of + /// `count * size_of::<T>()` bytes must be valid (but may or may not be + /// initialized). + /// + /// * `src` must be properly aligned. + /// + /// * `dst` must be properly aligned. + /// + /// * The two regions of memory must *not* overlap. + /// + /// Additionally, if `T` is not [`Copy`](../marker/trait.Copy), only the region at `src` *or* the + /// region at `dst` can be used or dropped after calling + /// `copy_nonoverlapping`. `copy_nonoverlapping` creates bitwise copies of + /// `T`, regardless of whether `T: Copy`, which can result in undefined + /// behavior if both copies are used. + /// + /// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// - /// A safe swap function: + /// Manually implement [`Vec::append`]: /// /// ``` - /// use std::mem; /// use std::ptr; /// - /// # #[allow(dead_code)] - /// fn swap<T>(x: &mut T, y: &mut T) { + /// /// Moves all the elements of `src` into `dst`, leaving `src` empty. + /// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) { + /// let src_len = src.len(); + /// let dst_len = dst.len(); + /// + /// // Ensure that `dst` has enough capacity to hold all of `src`. + /// dst.reserve(src_len); + /// /// unsafe { - /// // Give ourselves some scratch space to work with - /// let mut t: T = mem::uninitialized(); + /// // The call to offset is always safe because `Vec` will never + /// // allocate more than `isize::MAX` bytes. + /// let dst = dst.as_mut_ptr().offset(dst_len as isize); + /// let src = src.as_ptr(); + /// + /// // The two regions cannot overlap becuase mutable references do + /// // not alias, and two different vectors cannot own the same + /// // memory. + /// ptr::copy_nonoverlapping(src, dst, src_len); + /// } /// - /// // Perform the swap, `&mut` pointers never alias - /// ptr::copy_nonoverlapping(x, &mut t, 1); - /// ptr::copy_nonoverlapping(y, x, 1); - /// ptr::copy_nonoverlapping(&t, y, 1); + /// unsafe { + /// // Truncate `src` without dropping its contents. + /// src.set_len(0); /// - /// // y and t now point to the same thing, but we need to completely forget `t` - /// // because it's no longer relevant. - /// mem::forget(t); + /// // Notify `dst` that it now holds the contents of `src`. + /// dst.set_len(dst_len + src_len); /// } /// } + /// + /// let mut a = vec!['r']; + /// let mut b = vec!['u', 's', 't']; + /// + /// append(&mut a, &mut b); + /// + /// assert_eq!(a, &['r', 'u', 's', 't']); + /// assert!(b.is_empty()); /// ``` + /// + /// [`Vec::append()`]: ../vec/struct.Vec.html#method.append #[stable(feature = "rust1", since = "1.0.0")] pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); - /// Copies `count * size_of<T>` bytes from `src` to `dst`. The source + /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source /// and destination may overlap. /// - /// `copy` is semantically equivalent to C's `memmove`. + /// If the source and destination will *never* overlap, + /// [`copy_nonoverlapping`] can be used instead. + /// + /// `copy` is semantically equivalent to C's [`memmove`]. + /// + /// [`copy_nonoverlapping`]: ./fn.copy_nonoverlapping.html + /// [`memmove`]: https://www.gnu.org/software/libc/manual/html_node/Copying-Strings-and-Arrays.html#index-memmove /// /// # Safety /// - /// Care must be taken with the ownership of `src` and `dst`. - /// This method semantically moves the values of `src` into `dst`. - /// However it does not drop the contents of `dst`, or prevent the contents of `src` - /// from being dropped or used. + /// `copy` is unsafe because it dereferences a raw pointer. The caller must + /// ensure that `src` points to a valid sequence of type `T`. + /// + /// # [Undefined Behavior] + /// + /// Behavior is undefined if any of the following conditions are violated: + /// + /// * The region of memory which begins at `src` and has a length of + /// `count * size_of::<T>()` bytes must be *both* valid and initialized. + /// + /// * The region of memory which begins at `dst` and has a length of + /// `count * size_of::<T>()` bytes must be valid (but may or may not be + /// initialized). + /// + /// * `src` must be properly aligned. + /// + /// * `dst` must be properly aligned. + /// + /// Additionally, if `T` is not [`Copy`], only the region at `src` *or* the + /// region at `dst` can be used or dropped after calling `copy`. `copy` + /// creates bitwise copies of `T`, regardless of whether `T: Copy`, which + /// can result in undefined behavior if both copies are used. + /// + /// [`Copy`]: ../marker/trait.Copy.html + /// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// @@ -1028,15 +1103,39 @@ extern "rust-intrinsic" { /// dst /// } /// ``` - /// #[stable(feature = "rust1", since = "1.0.0")] pub fn copy<T>(src: *const T, dst: *mut T, count: usize); - /// Invokes memset on the specified pointer, setting `count * size_of::<T>()` - /// bytes of memory starting at `dst` to `val`. + /// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to + /// `val`. + /// + /// `write_bytes` is semantically equivalent to C's [`memset`]. + /// + /// [`memset`]: https://www.gnu.org/software/libc/manual/html_node/Copying-Strings-and-Arrays.html#index-memset + /// + /// # Safety + /// + /// `write_bytes` is unsafe because it dereferences a raw pointer. The + /// caller must ensure that the poiinter points to a valid value of type `T`. + /// + /// # [Undefined Behavior] + /// + /// Behavior is undefined if any of the following conditions are violated: + /// + /// * The region of memory which begins at `dst` and has a length of + /// `count` bytes must be valid. + /// + /// * `dst` must be properly aligned. + /// + /// Additionally, the caller must ensure that writing `count` bytes to the + /// given region of memory results in a valid value of `T`. Creating an + /// invalid value of `T` can result in undefined behavior. An example is + /// provided below. /// /// # Examples /// + /// Basic usage: + /// /// ``` /// use std::ptr; /// @@ -1047,6 +1146,22 @@ extern "rust-intrinsic" { /// } /// assert_eq!(vec, [b'a', b'a', 0, 0]); /// ``` + /// + /// Creating an invalid value: + /// + /// ```ignore + /// use std::{mem, ptr}; + /// + /// let mut v = Box::new(0i32); + /// + /// unsafe { + /// // Leaks the previously held value by overwriting the `Box<T>` with + /// // a null pointer. + /// ptr::write_bytes(&mut v, 0, mem::size_of::<Box<i32>>()); + /// } + /// + /// // At this point, using or dropping `v` results in undefined behavior. + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize); diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 5a54de06b5ef2..98d5030477b51 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -10,7 +10,7 @@ // FIXME: talk about offset, copy_memory, copy_nonoverlapping_memory -//! Raw, unsafe pointers, `*const T`, and `*mut T`. +//! Manually manage memory through raw, unsafe pointers. //! //! *[See also the pointer primitive types](../../std/primitive.pointer.html).* @@ -38,21 +38,68 @@ pub use intrinsics::write_bytes; /// Executes the destructor (if any) of the pointed-to value. /// -/// This has two use cases: +/// This is semantically equivalent to calling [`ptr::read`] and discarding +/// the result, but has the following advantages: /// /// * It is *required* to use `drop_in_place` to drop unsized types like /// trait objects, because they can't be read out onto the stack and /// dropped normally. /// -/// * It is friendlier to the optimizer to do this over `ptr::read` when +/// * It is friendlier to the optimizer to do this over [`ptr::read`] when /// dropping manually allocated memory (e.g. when writing Box/Rc/Vec), /// as the compiler doesn't need to prove that it's sound to elide the /// copy. /// +/// [`ptr::read`]: ./fn.read.html +/// /// # Safety /// -/// This has all the same safety problems as `ptr::read` with respect to -/// invalid pointers, types, and double drops. +/// `drop_in_place` is unsafe because it dereferences a raw pointer. The caller +/// must ensure that the pointer points to a valid value of type `T`. +/// +/// # [Undefined Behavior] +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `to_drop` must point to valid memory. +/// +/// * `to_drop` must be properly aligned. +/// +/// Additionally, if `T` is not [`Copy`], using the pointed-to value after +/// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop = +/// foo` counts as a use because it will cause the the value to be dropped +/// again. [`write`] can be used to overwrite data without causing it to be +/// dropped. +/// +/// [`Copy`]: ../marker/trait.Copy.html +/// [`write`]: ./fn.write.html +/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html +/// +/// # Examples +/// +/// Manually remove the last item from a vector: +/// +/// ``` +/// use std::ptr; +/// use std::rc::Rc; +/// +/// let last = Rc::new(1); +/// let weak = Rc::downgrade(&last); +/// +/// let mut v = vec![Rc::new(0), last]; +/// +/// unsafe { +/// // Without a call `drop_in_place`, the last item would never be dropped, +/// // and the memory it manages would be leaked. +/// ptr::drop_in_place(&mut v[1]); +/// v.set_len(1); +/// } +/// +/// assert_eq!(v, &[0.into()]); +/// +/// // Ensure that the last item was dropped. +/// assert!(weak.upgrade().is_none()); +/// ``` #[stable(feature = "drop_in_place", since = "1.8.0")] #[lang = "drop_in_place"] #[allow(unconditional_recursion)] @@ -93,17 +140,32 @@ pub const fn null_mut<T>() -> *mut T { 0 as *mut T } /// Swaps the values at two mutable locations of the same type, without /// deinitializing either. /// -/// The values pointed at by `x` and `y` may overlap, unlike `mem::swap` which -/// is otherwise equivalent. If the values do overlap, then the overlapping -/// region of memory from `x` will be used. This is demonstrated in the -/// examples section below. +/// But for the following two exceptions, this function is semantically +/// equivalent to [`mem::swap`]: +/// +/// * It operates on raw pointers instead of references. When references are +/// available, [`mem::swap`] should be preferred. +/// +/// * The two pointed-to values may overlap. If the values do overlap, then the +/// overlapping region of memory from `x` will be used. This is demonstrated +/// in the examples below. +/// +/// [`mem::swap`]: ../mem/fn.swap.html /// /// # Safety /// -/// This function copies the memory through the raw pointers passed to it -/// as arguments. +/// `swap` is unsafe because it dereferences a raw pointer. The caller must +/// ensure that both pointers point to valid values of type `T`. +/// +/// # [Undefined Behavior] +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `x` and `y` must point to valid, initialized memory. /// -/// Ensure that these pointers are valid before calling `swap`. +/// * `x` and `y` must be properly aligned. +/// +/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// @@ -241,13 +303,46 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { } } -/// Replaces the value at `dest` with `src`, returning the old -/// value, without dropping either. +/// Replaces the value at `dest` with `src`, returning the old value, without +/// dropping either. +/// +/// This function is semantically equivalent to [`mem::replace`] except that it +/// operates on raw pointers instead of references. When references are +/// available, [`mem::replace`] should be preferred. /// /// # Safety /// -/// This is only unsafe because it accepts a raw pointer. -/// Otherwise, this operation is identical to `mem::replace`. +/// `replace` is unsafe because it dereferences a raw pointer. The caller +/// must ensure that the pointer points to a valid value of type `T`. +/// +/// [`mem::replace`]: ../mem/fn.replace.html +/// +/// # [Undefined Behavior] +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `dest` must point to valid, initialized memory. +/// +/// * `dest` must be properly aligned. +/// +/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html +/// +/// # Examples +/// +/// ``` +/// use std::ptr; +/// +/// let mut rust = vec!['b', 'u', 's', 't']; +/// +/// // `mem::replace` would have the same effect without requiring the unsafe +/// // block. +/// let b = unsafe { +/// ptr::replace(&mut a[0], 'r') +/// }; +/// +/// assert_eq!(b, 'b'); +/// assert_eq!(rust, &['r', 'u', 's', 't']); +/// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T { @@ -260,14 +355,29 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T { /// /// # Safety /// -/// Beyond accepting a raw pointer, this is unsafe because it semantically -/// moves the value out of `src` without preventing further usage of `src`. -/// If `T` is not `Copy`, then care must be taken to ensure that the value at -/// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use -/// because it will attempt to drop the value previously at `*src`. +/// `read` is unsafe because it dereferences a raw pointer. The caller +/// must ensure that the pointer points to a valid value of type `T`. +/// +/// # [Undefined Behavior] /// -/// The pointer must be aligned; use `read_unaligned` if that is not the case. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must point to valid, initialized memory. +/// +/// * `src` must be properly aligned. Use [`read_unaligned`] if this is not the +/// case. +/// +/// Additionally, if `T` is not [`Copy`], only the returned value *or* the +/// pointed-to value can be used or dropped after calling `read`. `read` creates +/// a bitwise copy of `T`, regardless of whether `T: Copy`, which can result +/// in undefined behavior if both copies are used. Note that `*src = foo` counts +/// as a use because it will attempt to drop the value previously at `*src`. +/// [`write`] can be used to overwrite data without causing it to be dropped. +/// +/// [`Copy`]: ../marker/trait.Copy.html +/// [`read_unaligned`]: ./fn.read_unaligned.html +/// [`write`]: ./fn.write.html +/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// @@ -281,6 +391,44 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T { /// assert_eq!(std::ptr::read(y), 12); /// } /// ``` +/// +/// Manually implement [`mem::swap`]: +/// +/// ``` +/// use std::ptr; +/// +/// fn swap<T>(a: &mut T, b: &mut T) { +/// unsafe { +/// // Create a bitwise copy of the value at `a` in `tmp`. +/// let tmp = ptr::read(a); +/// +/// // Exiting at this point (either by explicitly returning or by +/// // calling a function which panics) would cause the value in `tmp` to +/// // be dropped while the same value is still referenced by `a`. This +/// // could trigger undefined behavior if `T` is not `Copy`. +/// +/// // Create a bitwise copy of the value at `b` in `a`. +/// // This is safe because mutable references cannot alias. +/// ptr::copy_nonoverlapping(b, a, 1); +/// +/// // As above, exiting here could trigger undefined behavior because +/// // the same value is referenced by `a` and `b`. +/// +/// // Move `tmp` into `b`. +/// ptr::write(b, tmp); +/// } +/// } +/// +/// let mut foo = "foo".to_owned(); +/// let mut bar = "bar".to_owned(); +/// +/// swap(&mut foo, &mut bar); +/// +/// assert_eq!(foo, "bar"); +/// assert_eq!(bar, "foo"); +/// ``` +/// +/// [`mem::swap`]: ../mem/fn.swap.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn read<T>(src: *const T) -> T { @@ -292,28 +440,66 @@ pub unsafe fn read<T>(src: *const T) -> T { /// Reads the value from `src` without moving it. This leaves the /// memory in `src` unchanged. /// -/// Unlike `read`, the pointer may be unaligned. +/// Unlike [`read`], `read_unaligned` works with unaligned pointers. /// -/// # Safety +/// [`read`]: ./fn.read.html +/// +/// `read_unaligned` is unsafe because it dereferences a raw pointer. The caller +/// must ensure that the pointer points to a valid value of type `T`. +/// +/// # [Undefined Behavior] +/// +/// Behavior is undefined if any of the following conditions are violated: /// -/// Beyond accepting a raw pointer, this is unsafe because it semantically -/// moves the value out of `src` without preventing further usage of `src`. -/// If `T` is not `Copy`, then care must be taken to ensure that the value at -/// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use -/// because it will attempt to drop the value previously at `*src`. +/// * `src` must point to valid, initialized memory. +/// +/// Additionally, if `T` is not [`Copy`], only the returned value *or* the +/// pointed-to value can be used or dropped after calling `read_unaligned`. +/// `read_unaligned` creates a bitwise copy of `T`, regardless of whether `T: +/// Copy`, and this can result in undefined behavior if both copies are used. +/// Note that `*src = foo` counts as a use because it will attempt to drop the +/// value previously at `*src`. [`write_unaligned`] can be used to overwrite +/// data without causing it to be dropped. +/// +/// [`Copy`]: ../marker/trait.Copy.html +/// [`write_unaligned`]: ./fn.write_unaligned.html +/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// -/// Basic usage: +/// Access members of a packed struct by reference: /// /// ``` -/// let x = 12; -/// let y = &x as *const i32; +/// use std::ptr; /// -/// unsafe { -/// assert_eq!(std::ptr::read_unaligned(y), 12); +/// #[repr(packed, C)] +/// #[derive(Default)] +/// struct Packed { +/// _padding: u8, +/// unaligned: u32, /// } +/// +/// let x = Packed { +/// _padding: 0x00, +/// unaligned: 0x01020304, +/// }; +/// +/// let v = unsafe { +/// // Take a reference to a 32-bit integer which is not aligned. +/// let unaligned = &x.unaligned; +/// +/// // Dereferencing normally will emit an unaligned load instruction, +/// // causing undefined behavior. +/// // let v = *unaligned; // ERROR +/// +/// // Instead, use `read_unaligned` to read improperly aligned values. +/// let v = ptr::read_unaligned(unaligned); +/// +/// v +/// }; +/// +/// // Accessing unaligned values directly is safe. +/// assert!(x.unaligned == v); /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] @@ -328,11 +514,7 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T { /// Overwrites a memory location with the given value without reading or /// dropping the old value. /// -/// # Safety -/// -/// This operation is marked unsafe because it accepts a raw pointer. -/// -/// It does not drop the contents of `dst`. This is safe, but it could leak +/// `write` does not drop the contents of `dst`. This is safe, but it could leak /// allocations or resources, so care must be taken not to overwrite an object /// that should be dropped. /// @@ -340,9 +522,26 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T { /// location pointed to by `dst`. /// /// This is appropriate for initializing uninitialized memory, or overwriting -/// memory that has previously been `read` from. +/// memory that has previously been [`read`] from. +/// +/// [`read`]: ./fn.read.html +/// +/// # Safety +/// +/// `write` is unsafe because it dereferences a raw pointer. +/// +/// # [Undefined Behavior] +/// +/// `write` can trigger undefined behavior if any of the following conditions +/// are violated: /// -/// The pointer must be aligned; use `write_unaligned` if that is not the case. +/// * `dst` must point to valid memory. +/// +/// * `dst` must be properly aligned. Use [`write_unaligned`] if this is not the +/// case. +/// +/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html +/// [`write_unaligned`]: ./fn.write_unaligned.html /// /// # Examples /// @@ -358,6 +557,30 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T { /// assert_eq!(std::ptr::read(y), 12); /// } /// ``` +/// +/// Manually implement [`mem::swap`]: +/// +/// ``` +/// use std::ptr; +/// +/// fn swap<T>(a: &mut T, b: &mut T) { +/// unsafe { +/// let tmp = ptr::read(a); +/// ptr::copy_nonoverlapping(b, a, 1); +/// ptr::write(b, tmp); +/// } +/// } +/// +/// let mut foo = "foo".to_owned(); +/// let mut bar = "bar".to_owned(); +/// +/// swap(&mut foo, &mut bar); +/// +/// assert_eq!(foo, "bar"); +/// assert_eq!(bar, "foo"); +/// ``` +/// +/// [`mem::swap`]: ../mem/fn.swap.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn write<T>(dst: *mut T, src: T) { @@ -367,36 +590,65 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// Overwrites a memory location with the given value without reading or /// dropping the old value. /// -/// Unlike `write`, the pointer may be unaligned. +/// Unlike [`write`], the pointer may be unaligned. /// -/// # Safety -/// -/// This operation is marked unsafe because it accepts a raw pointer. -/// -/// It does not drop the contents of `dst`. This is safe, but it could leak -/// allocations or resources, so care must be taken not to overwrite an object -/// that should be dropped. +/// `write_unaligned` does not drop the contents of `dst`. This is safe, but it +/// could leak allocations or resources, so care must be taken not to overwrite +/// an object that should be dropped. /// /// Additionally, it does not drop `src`. Semantically, `src` is moved into the /// location pointed to by `dst`. /// /// This is appropriate for initializing uninitialized memory, or overwriting -/// memory that has previously been `read` from. +/// memory that has previously been [`read`] from. +/// +/// [`write`]: ./fn.write.html +/// [`read_unaligned`]: ./fn.read_unaligned.html +/// +/// # Safety +/// +/// `write_unaligned` is unsafe because it dereferences a raw pointer. +/// +/// # [Undefined Behavior] +/// +/// `write_unaligned` can trigger undefined behavior if any of the following +/// conditions are violated: +/// +/// * `dst` must point to valid memory. +/// +/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// -/// Basic usage: +/// Access fields in a packed struct: /// /// ``` -/// let mut x = 0; -/// let y = &mut x as *mut i32; -/// let z = 12; +/// use std::{mem, ptr}; +/// +/// #[repr(packed, C)] +/// #[derive(Default)] +/// struct Packed { +/// _padding: u8, +/// unaligned: u32, +/// } +/// +/// let v = 0x01020304; +/// let mut x: Packed = unsafe { mem::zeroed() }; /// /// unsafe { -/// std::ptr::write_unaligned(y, z); -/// assert_eq!(std::ptr::read_unaligned(y), 12); +/// // Take a reference to a 32-bit integer which is not aligned. +/// let unaligned = &mut x.unaligned; +/// +/// // Dereferencing normally will emit an unaligned store instruction, +/// // causing undefined behavior. +/// // *unaligned = v; // ERROR +/// +/// // Instead, use `write_unaligned` to write improperly aligned values. +/// ptr::write_unaligned(unaligned, v); /// } -/// ``` +/// +/// // Accessing unaligned values directly is safe. +/// assert!(x.unaligned == v); #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { @@ -429,12 +681,28 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { /// /// # Safety /// -/// Beyond accepting a raw pointer, this is unsafe because it semantically -/// moves the value out of `src` without preventing further usage of `src`. -/// If `T` is not `Copy`, then care must be taken to ensure that the value at -/// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use -/// because it will attempt to drop the value previously at `*src`. +/// `read_volatile` is unsafe because it dereferences a raw pointer. The caller +/// must ensure that the pointer points to a valid value of type `T`. +/// +/// # [Undefined Behavior] +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must point to valid, initialized memory. +/// +/// * `src` must be properly aligned. +/// +/// Additionally, if `T` is not [`Copy`], only the returned value *or* the +/// pointed-to value can be used or dropped after calling `read_volatile`. +/// `read_volatile` creates a bitwise copy of `T`, regardless of whether `T: +/// Copy`, which can result in undefined behavior if both copies are used. +/// Note that `*src = foo` counts as a use because it will attempt to drop the +/// value previously at `*src`. [`write_volatile`] can be used to overwrite +/// data without causing it to be dropped. +/// +/// [`Copy`]: ../marker/trait.Copy.html +/// [`write_volatile`]: ./fn.write_volatile.html +/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// @@ -461,6 +729,13 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T { /// to not be elided or reordered by the compiler across other volatile /// operations. /// +/// `write_volatile` does not drop the contents of `dst`. This is safe, but it +/// could leak allocations or resources, so care must be taken not to overwrite +/// an object that should be dropped. +/// +/// Additionally, it does not drop `src`. Semantically, `src` is moved into the +/// location pointed to by `dst`. +/// /// # Notes /// /// Rust does not currently have a rigorously and formally defined memory model, @@ -477,14 +752,18 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T { /// /// # Safety /// -/// This operation is marked unsafe because it accepts a raw pointer. +/// `write_volatile` is unsafe because it dereferences a raw pointer. /// -/// It does not drop the contents of `dst`. This is safe, but it could leak -/// allocations or resources, so care must be taken not to overwrite an object -/// that should be dropped. +/// # [Undefined Behavior] /// -/// This is appropriate for initializing uninitialized memory, or overwriting -/// memory that has previously been `read` from. +/// `write_volatile` can trigger undefined behavior if any of the following +/// conditions are violated: +/// +/// * `dst` must point to valid memory. +/// +/// * `dst` must be properly aligned. +/// +/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// From ee259e4dd340f9532511b7249e4eb961f111b63f Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie <ecstaticmorse@gmail.com> Date: Sat, 7 Apr 2018 15:51:25 -0700 Subject: [PATCH 02/19] Change `write_bytes` test causing UB to `no_run` This also fixes improper text wrapping. --- src/libcore/intrinsics.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index d6bd2b868554c..8e3180cd2a6f9 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -992,11 +992,11 @@ extern "rust-intrinsic" { /// /// * The two regions of memory must *not* overlap. /// - /// Additionally, if `T` is not [`Copy`](../marker/trait.Copy), only the region at `src` *or* the - /// region at `dst` can be used or dropped after calling - /// `copy_nonoverlapping`. `copy_nonoverlapping` creates bitwise copies of - /// `T`, regardless of whether `T: Copy`, which can result in undefined - /// behavior if both copies are used. + /// Additionally, if `T` is not [`Copy`](../marker/trait.Copy), only the + /// region at `src` *or* the region at `dst` can be used or dropped after + /// calling `copy_nonoverlapping`. `copy_nonoverlapping` creates bitwise + /// copies of `T`, regardless of whether `T: Copy`, which can result in + /// undefined behavior if both copies are used. /// /// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// @@ -1149,7 +1149,7 @@ extern "rust-intrinsic" { /// /// Creating an invalid value: /// - /// ```ignore + /// ```no_run /// use std::{mem, ptr}; /// /// let mut v = Box::new(0i32); @@ -1161,6 +1161,7 @@ extern "rust-intrinsic" { /// } /// /// // At this point, using or dropping `v` results in undefined behavior. + /// // v = Box::new(0i32); // ERROR /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize); From b564c4a0ee96acb0a68b8421b6cecac47e2a2e8b Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie <ecstaticmorse@gmail.com> Date: Sat, 7 Apr 2018 17:20:20 -0700 Subject: [PATCH 03/19] Fix example for `ptr::replace` --- src/libcore/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 98d5030477b51..9069feab06c84 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -337,7 +337,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { /// // `mem::replace` would have the same effect without requiring the unsafe /// // block. /// let b = unsafe { -/// ptr::replace(&mut a[0], 'r') +/// ptr::replace(&mut rust[0], 'r') /// }; /// /// assert_eq!(b, 'b'); From 6eceb94d09636d272f8448d0eb26e072b891cb45 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie <ecstaticmorse@gmail.com> Date: Sat, 7 Apr 2018 17:22:27 -0700 Subject: [PATCH 04/19] Don't link "Undefined Behavior" heading The rendered version does not make clear that this is a link to another page, and it breaks the anchor link. --- src/libcore/intrinsics.rs | 9 +++------ src/libcore/ptr.rs | 31 +++++++++---------------------- 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 8e3180cd2a6f9..daa43337fd79c 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -975,7 +975,7 @@ extern "rust-intrinsic" { /// The caller must ensure that `src` points to a valid sequence of type /// `T`. /// - /// # [Undefined Behavior] + /// # Undefined Behavior /// /// Behavior is undefined if any of the following conditions are violated: /// @@ -998,8 +998,6 @@ extern "rust-intrinsic" { /// copies of `T`, regardless of whether `T: Copy`, which can result in /// undefined behavior if both copies are used. /// - /// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html - /// /// # Examples /// /// Manually implement [`Vec::append`]: @@ -1065,7 +1063,7 @@ extern "rust-intrinsic" { /// `copy` is unsafe because it dereferences a raw pointer. The caller must /// ensure that `src` points to a valid sequence of type `T`. /// - /// # [Undefined Behavior] + /// # Undefined Behavior /// /// Behavior is undefined if any of the following conditions are violated: /// @@ -1086,7 +1084,6 @@ extern "rust-intrinsic" { /// can result in undefined behavior if both copies are used. /// /// [`Copy`]: ../marker/trait.Copy.html - /// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// @@ -1118,7 +1115,7 @@ extern "rust-intrinsic" { /// `write_bytes` is unsafe because it dereferences a raw pointer. The /// caller must ensure that the poiinter points to a valid value of type `T`. /// - /// # [Undefined Behavior] + /// # Undefined Behavior /// /// Behavior is undefined if any of the following conditions are violated: /// diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 9069feab06c84..4cb9c655441d9 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -57,7 +57,7 @@ pub use intrinsics::write_bytes; /// `drop_in_place` is unsafe because it dereferences a raw pointer. The caller /// must ensure that the pointer points to a valid value of type `T`. /// -/// # [Undefined Behavior] +/// # Undefined Behavior /// /// Behavior is undefined if any of the following conditions are violated: /// @@ -73,7 +73,6 @@ pub use intrinsics::write_bytes; /// /// [`Copy`]: ../marker/trait.Copy.html /// [`write`]: ./fn.write.html -/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// @@ -157,7 +156,7 @@ pub const fn null_mut<T>() -> *mut T { 0 as *mut T } /// `swap` is unsafe because it dereferences a raw pointer. The caller must /// ensure that both pointers point to valid values of type `T`. /// -/// # [Undefined Behavior] +/// # Undefined Behavior /// /// Behavior is undefined if any of the following conditions are violated: /// @@ -165,8 +164,6 @@ pub const fn null_mut<T>() -> *mut T { 0 as *mut T } /// /// * `x` and `y` must be properly aligned. /// -/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html -/// /// # Examples /// /// Swapping two non-overlapping regions: @@ -317,7 +314,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { /// /// [`mem::replace`]: ../mem/fn.replace.html /// -/// # [Undefined Behavior] +/// # Undefined Behavior /// /// Behavior is undefined if any of the following conditions are violated: /// @@ -325,8 +322,6 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { /// /// * `dest` must be properly aligned. /// -/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html -/// /// # Examples /// /// ``` @@ -358,7 +353,7 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T { /// `read` is unsafe because it dereferences a raw pointer. The caller /// must ensure that the pointer points to a valid value of type `T`. /// -/// # [Undefined Behavior] +/// # Undefined Behavior /// /// Behavior is undefined if any of the following conditions are violated: /// @@ -377,7 +372,6 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T { /// [`Copy`]: ../marker/trait.Copy.html /// [`read_unaligned`]: ./fn.read_unaligned.html /// [`write`]: ./fn.write.html -/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// @@ -447,7 +441,7 @@ pub unsafe fn read<T>(src: *const T) -> T { /// `read_unaligned` is unsafe because it dereferences a raw pointer. The caller /// must ensure that the pointer points to a valid value of type `T`. /// -/// # [Undefined Behavior] +/// # Undefined Behavior /// /// Behavior is undefined if any of the following conditions are violated: /// @@ -463,7 +457,6 @@ pub unsafe fn read<T>(src: *const T) -> T { /// /// [`Copy`]: ../marker/trait.Copy.html /// [`write_unaligned`]: ./fn.write_unaligned.html -/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// @@ -530,7 +523,7 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T { /// /// `write` is unsafe because it dereferences a raw pointer. /// -/// # [Undefined Behavior] +/// # Undefined Behavior /// /// `write` can trigger undefined behavior if any of the following conditions /// are violated: @@ -540,7 +533,6 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T { /// * `dst` must be properly aligned. Use [`write_unaligned`] if this is not the /// case. /// -/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// [`write_unaligned`]: ./fn.write_unaligned.html /// /// # Examples @@ -609,15 +601,13 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// /// `write_unaligned` is unsafe because it dereferences a raw pointer. /// -/// # [Undefined Behavior] +/// # Undefined Behavior /// /// `write_unaligned` can trigger undefined behavior if any of the following /// conditions are violated: /// /// * `dst` must point to valid memory. /// -/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html -/// /// # Examples /// /// Access fields in a packed struct: @@ -684,7 +674,7 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { /// `read_volatile` is unsafe because it dereferences a raw pointer. The caller /// must ensure that the pointer points to a valid value of type `T`. /// -/// # [Undefined Behavior] +/// # Undefined Behavior /// /// Behavior is undefined if any of the following conditions are violated: /// @@ -702,7 +692,6 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { /// /// [`Copy`]: ../marker/trait.Copy.html /// [`write_volatile`]: ./fn.write_volatile.html -/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// @@ -754,7 +743,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T { /// /// `write_volatile` is unsafe because it dereferences a raw pointer. /// -/// # [Undefined Behavior] +/// # Undefined Behavior /// /// `write_volatile` can trigger undefined behavior if any of the following /// conditions are violated: @@ -763,8 +752,6 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T { /// /// * `dst` must be properly aligned. /// -/// [Undefined Behavior]: ../../reference/behavior-considered-undefined.html -/// /// # Examples /// /// Basic usage: From 422b6164e505bc240948dc6e420a82c89ead0711 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie <ecstaticmorse@gmail.com> Date: Sat, 7 Apr 2018 17:28:10 -0700 Subject: [PATCH 05/19] Fix broken link in `write_unaligned` docs --- src/libcore/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 4cb9c655441d9..c679a1a2456b1 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -592,7 +592,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// location pointed to by `dst`. /// /// This is appropriate for initializing uninitialized memory, or overwriting -/// memory that has previously been [`read`] from. +/// memory that has previously been read with [`read_unaligned`]. /// /// [`write`]: ./fn.write.html /// [`read_unaligned`]: ./fn.read_unaligned.html From d7ce9a213c11f825b8b47f7d9fd970cfb97033bd Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie <ecstaticmorse@gmail.com> Date: Sat, 7 Apr 2018 20:45:16 -0700 Subject: [PATCH 06/19] Fix broken relative links --- src/libcore/intrinsics.rs | 12 ++++++------ src/libcore/ptr.rs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index daa43337fd79c..8c510842c2a91 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -992,11 +992,11 @@ extern "rust-intrinsic" { /// /// * The two regions of memory must *not* overlap. /// - /// Additionally, if `T` is not [`Copy`](../marker/trait.Copy), only the - /// region at `src` *or* the region at `dst` can be used or dropped after - /// calling `copy_nonoverlapping`. `copy_nonoverlapping` creates bitwise - /// copies of `T`, regardless of whether `T: Copy`, which can result in - /// undefined behavior if both copies are used. + /// Additionally, if `T` is not [`Copy`](../marker/trait.Copy.html), only + /// the region at `src` *or* the region at `dst` can be used or dropped + /// after calling `copy_nonoverlapping`. `copy_nonoverlapping` creates + /// bitwise copies of `T`, regardless of whether `T: Copy`, which can result + /// in undefined behavior if both copies are used. /// /// # Examples /// @@ -1043,7 +1043,7 @@ extern "rust-intrinsic" { /// assert!(b.is_empty()); /// ``` /// - /// [`Vec::append()`]: ../vec/struct.Vec.html#method.append + /// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append #[stable(feature = "rust1", since = "1.0.0")] pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index c679a1a2456b1..962fb0f31a407 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -50,7 +50,7 @@ pub use intrinsics::write_bytes; /// as the compiler doesn't need to prove that it's sound to elide the /// copy. /// -/// [`ptr::read`]: ./fn.read.html +/// [`ptr::read`]: ../ptr/fn.read.html /// /// # Safety /// @@ -72,7 +72,7 @@ pub use intrinsics::write_bytes; /// dropped. /// /// [`Copy`]: ../marker/trait.Copy.html -/// [`write`]: ./fn.write.html +/// [`write`]: ../ptr/fn.write.html /// /// # Examples /// From d7209d5babae4e1e428771287eaca6165e43972c Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie <ecstaticmorse@gmail.com> Date: Mon, 9 Apr 2018 14:23:08 -0700 Subject: [PATCH 07/19] Fix various nits from PR review - Remove redundant "unsafe" from module description. - Add a missing `Safety` heading to `read_unaligned`. - Remove weasel words in `Undefined Behavior` description for `write{,_unaligned,_bytes}`. --- src/libcore/ptr.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 962fb0f31a407..3d15e4b165893 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -10,7 +10,7 @@ // FIXME: talk about offset, copy_memory, copy_nonoverlapping_memory -//! Manually manage memory through raw, unsafe pointers. +//! Manually manage memory through raw pointers. //! //! *[See also the pointer primitive types](../../std/primitive.pointer.html).* @@ -438,6 +438,8 @@ pub unsafe fn read<T>(src: *const T) -> T { /// /// [`read`]: ./fn.read.html /// +/// # Safety +/// /// `read_unaligned` is unsafe because it dereferences a raw pointer. The caller /// must ensure that the pointer points to a valid value of type `T`. /// @@ -525,8 +527,7 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T { /// /// # Undefined Behavior /// -/// `write` can trigger undefined behavior if any of the following conditions -/// are violated: +/// Behavior is undefined if any of the following conditions are violated: /// /// * `dst` must point to valid memory. /// @@ -603,8 +604,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// /// # Undefined Behavior /// -/// `write_unaligned` can trigger undefined behavior if any of the following -/// conditions are violated: +/// Behavior is undefined if any of the following conditions are violated: /// /// * `dst` must point to valid memory. /// @@ -745,8 +745,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T { /// /// # Undefined Behavior /// -/// `write_volatile` can trigger undefined behavior if any of the following -/// conditions are violated: +/// Behavior is undefined if any of the following conditions are violated: /// /// * `dst` must point to valid memory. /// From 4f2cfb57f5afe503c554f13484c53482e38d7bba Mon Sep 17 00:00:00 2001 From: Philipp Hansch <dev@phansch.net> Date: Wed, 2 May 2018 08:11:18 +0200 Subject: [PATCH 08/19] Remove leftover tab in libtest outputs Closes #50362 --- src/libtest/formatters/pretty.rs | 4 ++-- src/libtest/formatters/terse.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs index 8e5fa00b5f27d..f94780682a0c0 100644 --- a/src/libtest/formatters/pretty.rs +++ b/src/libtest/formatters/pretty.rs @@ -101,7 +101,7 @@ impl<T: Write> PrettyFormatter<T> { for &(ref f, ref stdout) in &state.not_failures { successes.push(f.name.to_string()); if !stdout.is_empty() { - stdouts.push_str(&format!("---- {} stdout ----\n\t", f.name)); + stdouts.push_str(&format!("---- {} stdout ----\n", f.name)); let output = String::from_utf8_lossy(stdout); stdouts.push_str(&output); stdouts.push_str("\n"); @@ -127,7 +127,7 @@ impl<T: Write> PrettyFormatter<T> { for &(ref f, ref stdout) in &state.failures { failures.push(f.name.to_string()); if !stdout.is_empty() { - fail_out.push_str(&format!("---- {} stdout ----\n\t", f.name)); + fail_out.push_str(&format!("---- {} stdout ----\n", f.name)); let output = String::from_utf8_lossy(stdout); fail_out.push_str(&output); fail_out.push_str("\n"); diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs index 85286027d6921..22a06b9f605db 100644 --- a/src/libtest/formatters/terse.rs +++ b/src/libtest/formatters/terse.rs @@ -105,7 +105,7 @@ impl<T: Write> TerseFormatter<T> { for &(ref f, ref stdout) in &state.not_failures { successes.push(f.name.to_string()); if !stdout.is_empty() { - stdouts.push_str(&format!("---- {} stdout ----\n\t", f.name)); + stdouts.push_str(&format!("---- {} stdout ----\n", f.name)); let output = String::from_utf8_lossy(stdout); stdouts.push_str(&output); stdouts.push_str("\n"); @@ -131,7 +131,7 @@ impl<T: Write> TerseFormatter<T> { for &(ref f, ref stdout) in &state.failures { failures.push(f.name.to_string()); if !stdout.is_empty() { - fail_out.push_str(&format!("---- {} stdout ----\n\t", f.name)); + fail_out.push_str(&format!("---- {} stdout ----\n", f.name)); let output = String::from_utf8_lossy(stdout); fail_out.push_str(&output); fail_out.push_str("\n"); From e350ba48ed80c000fd2d2b5ac37e53a9efe1f587 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie <mackendy@localhost.localdomain> Date: Wed, 9 May 2018 14:14:43 -0700 Subject: [PATCH 09/19] Use the "Safety" heading instead of "Undefined Behavior" --- src/libcore/intrinsics.rs | 30 +++++++------------------- src/libcore/ptr.rs | 44 +-------------------------------------- 2 files changed, 9 insertions(+), 65 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 8c510842c2a91..df3f6c430311a 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -971,12 +971,6 @@ extern "rust-intrinsic" { /// /// # Safety /// - /// `copy_nonoverlapping` is unsafe because it dereferences a raw pointer. - /// The caller must ensure that `src` points to a valid sequence of type - /// `T`. - /// - /// # Undefined Behavior - /// /// Behavior is undefined if any of the following conditions are violated: /// /// * The region of memory which begins at `src` and has a length of @@ -986,17 +980,19 @@ extern "rust-intrinsic" { /// `count * size_of::<T>()` bytes must be valid (but may or may not be /// initialized). /// + /// * The two regions of memory must *not* overlap. + /// /// * `src` must be properly aligned. /// /// * `dst` must be properly aligned. /// - /// * The two regions of memory must *not* overlap. + /// Additionally, if `T` is not [`Copy`], only the region at `src` *or* the + /// region at `dst` can be used or dropped after calling + /// `copy_nonoverlapping`. `copy_nonoverlapping` creates bitwise copies of + /// `T`, regardless of whether `T: Copy`, which can result in undefined + /// behavior if both copies are used. /// - /// Additionally, if `T` is not [`Copy`](../marker/trait.Copy.html), only - /// the region at `src` *or* the region at `dst` can be used or dropped - /// after calling `copy_nonoverlapping`. `copy_nonoverlapping` creates - /// bitwise copies of `T`, regardless of whether `T: Copy`, which can result - /// in undefined behavior if both copies are used. + /// [`Copy`]: ../marker/trait.Copy.html /// /// # Examples /// @@ -1060,11 +1056,6 @@ extern "rust-intrinsic" { /// /// # Safety /// - /// `copy` is unsafe because it dereferences a raw pointer. The caller must - /// ensure that `src` points to a valid sequence of type `T`. - /// - /// # Undefined Behavior - /// /// Behavior is undefined if any of the following conditions are violated: /// /// * The region of memory which begins at `src` and has a length of @@ -1112,11 +1103,6 @@ extern "rust-intrinsic" { /// /// # Safety /// - /// `write_bytes` is unsafe because it dereferences a raw pointer. The - /// caller must ensure that the poiinter points to a valid value of type `T`. - /// - /// # Undefined Behavior - /// /// Behavior is undefined if any of the following conditions are violated: /// /// * The region of memory which begins at `dst` and has a length of diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 3d15e4b165893..50627ee464d39 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -54,11 +54,6 @@ pub use intrinsics::write_bytes; /// /// # Safety /// -/// `drop_in_place` is unsafe because it dereferences a raw pointer. The caller -/// must ensure that the pointer points to a valid value of type `T`. -/// -/// # Undefined Behavior -/// /// Behavior is undefined if any of the following conditions are violated: /// /// * `to_drop` must point to valid memory. @@ -153,11 +148,6 @@ pub const fn null_mut<T>() -> *mut T { 0 as *mut T } /// /// # Safety /// -/// `swap` is unsafe because it dereferences a raw pointer. The caller must -/// ensure that both pointers point to valid values of type `T`. -/// -/// # Undefined Behavior -/// /// Behavior is undefined if any of the following conditions are violated: /// /// * `x` and `y` must point to valid, initialized memory. @@ -307,14 +297,9 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { /// operates on raw pointers instead of references. When references are /// available, [`mem::replace`] should be preferred. /// -/// # Safety -/// -/// `replace` is unsafe because it dereferences a raw pointer. The caller -/// must ensure that the pointer points to a valid value of type `T`. -/// /// [`mem::replace`]: ../mem/fn.replace.html /// -/// # Undefined Behavior +/// # Safety /// /// Behavior is undefined if any of the following conditions are violated: /// @@ -350,11 +335,6 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T { /// /// # Safety /// -/// `read` is unsafe because it dereferences a raw pointer. The caller -/// must ensure that the pointer points to a valid value of type `T`. -/// -/// # Undefined Behavior -/// /// Behavior is undefined if any of the following conditions are violated: /// /// * `src` must point to valid, initialized memory. @@ -440,11 +420,6 @@ pub unsafe fn read<T>(src: *const T) -> T { /// /// # Safety /// -/// `read_unaligned` is unsafe because it dereferences a raw pointer. The caller -/// must ensure that the pointer points to a valid value of type `T`. -/// -/// # Undefined Behavior -/// /// Behavior is undefined if any of the following conditions are violated: /// /// * `src` must point to valid, initialized memory. @@ -523,10 +498,6 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T { /// /// # Safety /// -/// `write` is unsafe because it dereferences a raw pointer. -/// -/// # Undefined Behavior -/// /// Behavior is undefined if any of the following conditions are violated: /// /// * `dst` must point to valid memory. @@ -600,10 +571,6 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// /// # Safety /// -/// `write_unaligned` is unsafe because it dereferences a raw pointer. -/// -/// # Undefined Behavior -/// /// Behavior is undefined if any of the following conditions are violated: /// /// * `dst` must point to valid memory. @@ -671,11 +638,6 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { /// /// # Safety /// -/// `read_volatile` is unsafe because it dereferences a raw pointer. The caller -/// must ensure that the pointer points to a valid value of type `T`. -/// -/// # Undefined Behavior -/// /// Behavior is undefined if any of the following conditions are violated: /// /// * `src` must point to valid, initialized memory. @@ -741,10 +703,6 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T { /// /// # Safety /// -/// `write_volatile` is unsafe because it dereferences a raw pointer. -/// -/// # Undefined Behavior -/// /// Behavior is undefined if any of the following conditions are violated: /// /// * `dst` must point to valid memory. From 827251e92bef9bd613cf44e2dc074fa1dc71ea0f Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie <mackendy@localhost.localdomain> Date: Wed, 9 May 2018 15:52:16 -0700 Subject: [PATCH 10/19] Shorten ownership safety discussion in `read_volatile` Non-`Copy` types should not be in volatile memory. --- src/libcore/ptr.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 50627ee464d39..f3cf206876651 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -622,6 +622,11 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { /// to not be elided or reordered by the compiler across other volatile /// operations. /// +/// Memory read with `read_volatile` should almost always be written to using +/// [`write_volatile`]. +/// +/// [`write_volatile`]: ./fn.write_volatile.html +/// /// # Notes /// /// Rust does not currently have a rigorously and formally defined memory model, @@ -644,16 +649,13 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { /// /// * `src` must be properly aligned. /// -/// Additionally, if `T` is not [`Copy`], only the returned value *or* the -/// pointed-to value can be used or dropped after calling `read_volatile`. -/// `read_volatile` creates a bitwise copy of `T`, regardless of whether `T: -/// Copy`, which can result in undefined behavior if both copies are used. -/// Note that `*src = foo` counts as a use because it will attempt to drop the -/// value previously at `*src`. [`write_volatile`] can be used to overwrite -/// data without causing it to be dropped. +/// Like [`read`], `read_volatile` creates a bitwise copy of the pointed-to +/// object, regardless of whether `T` is [`Copy`]. Using both values can cause +/// undefined behavior. However, storing non-[`Copy`] data in I/O memory is +/// almost certainly incorrect. /// /// [`Copy`]: ../marker/trait.Copy.html -/// [`write_volatile`]: ./fn.write_volatile.html +/// [`read`]: ./fn.read.html /// /// # Examples /// @@ -680,6 +682,9 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T { /// to not be elided or reordered by the compiler across other volatile /// operations. /// +/// Memory written with `write_volatile` should almost always be read from using +/// [`read_volatile`]. +/// /// `write_volatile` does not drop the contents of `dst`. This is safe, but it /// could leak allocations or resources, so care must be taken not to overwrite /// an object that should be dropped. @@ -687,6 +692,8 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T { /// Additionally, it does not drop `src`. Semantically, `src` is moved into the /// location pointed to by `dst`. /// +/// [`read_volatile`]: ./fn.read_volatile.html +/// /// # Notes /// /// Rust does not currently have a rigorously and formally defined memory model, From 37783563edf74b6e3a4c816ec2ff3911fad30e8c Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon <sanxiyn@gmail.com> Date: Thu, 10 May 2018 12:11:47 +0900 Subject: [PATCH 11/19] Update the man page with additional --print options --- src/doc/man/rustc.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/man/rustc.1 b/src/doc/man/rustc.1 index 39d1053995945..8f611063dbe5d 100644 --- a/src/doc/man/rustc.1 +++ b/src/doc/man/rustc.1 @@ -55,7 +55,7 @@ Configure the output that \fBrustc\fR will produce. Each emission may also have an optional explicit output \fIPATH\fR specified for that particular emission kind. This path takes precedence over the \fB-o\fR option. .TP -\fB\-\-print\fR [crate\-name|file\-names|sysroot] +\fB\-\-print\fR [crate\-name|\:file\-names|\:sysroot|\:cfg|\:target\-list|\:target\-cpus|\:target\-features|\:relocation\-models|\:code\-models|\:tls\-models|\:target\-spec\-json|\:native\-static\-libs] Comma separated list of compiler information to print on stdout. .TP \fB\-g\fR From 3daded02facb956919c304ac46af7d69145ab8d2 Mon Sep 17 00:00:00 2001 From: Oliver Middleton <olliemail27@gmail.com> Date: Sat, 12 May 2018 18:25:09 +0100 Subject: [PATCH 12/19] rustdoc: Add support for pub(restricted) --- src/librustdoc/clean/mod.rs | 17 ++++++++++-- src/librustdoc/html/format.rs | 15 ++++++++-- src/test/rustdoc/pub-restricted.rs | 44 ++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 src/test/rustdoc/pub-restricted.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 007938e86ed9d..0d628d47766b3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -17,7 +17,7 @@ pub use self::ItemEnum::*; pub use self::TyParamBound::*; pub use self::SelfTy::*; pub use self::FunctionRetTy::*; -pub use self::Visibility::*; +pub use self::Visibility::{Public, Inherited}; use syntax; use rustc_target::spec::abi::Abi; @@ -2976,11 +2976,22 @@ impl<'tcx> Clean<Item> for ty::FieldDef { pub enum Visibility { Public, Inherited, + Crate, + Restricted(DefId, Path), } impl Clean<Option<Visibility>> for hir::Visibility { - fn clean(&self, _: &DocContext) -> Option<Visibility> { - Some(if *self == hir::Visibility::Public { Public } else { Inherited }) + fn clean(&self, cx: &DocContext) -> Option<Visibility> { + Some(match *self { + hir::Visibility::Public => Visibility::Public, + hir::Visibility::Inherited => Visibility::Inherited, + hir::Visibility::Crate => Visibility::Crate, + hir::Visibility::Restricted { ref path, .. } => { + let path = path.clean(cx); + let did = register_def(cx, path.def); + Visibility::Restricted(did, path) + } + }) } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index a9a4c5113747e..2db57c97dd466 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -927,8 +927,19 @@ impl<'a> fmt::Display for Method<'a> { impl<'a> fmt::Display for VisSpace<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self.get() { - Some(clean::Public) => write!(f, "pub "), - Some(clean::Inherited) | None => Ok(()) + Some(clean::Public) => f.write_str("pub "), + Some(clean::Inherited) | None => Ok(()), + Some(clean::Visibility::Crate) => write!(f, "pub(crate) "), + Some(clean::Visibility::Restricted(did, ref path)) => { + f.write_str("pub(")?; + if path.segments.len() != 1 + || (path.segments[0].name != "self" && path.segments[0].name != "super") + { + f.write_str("in ")?; + } + resolved_path(f, did, path, true, false)?; + f.write_str(") ") + } } } } diff --git a/src/test/rustdoc/pub-restricted.rs b/src/test/rustdoc/pub-restricted.rs new file mode 100644 index 0000000000000..cc8f628cad44b --- /dev/null +++ b/src/test/rustdoc/pub-restricted.rs @@ -0,0 +1,44 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <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. + +// ignore-tidy-linelength + +// compile-flags: --document-private-items + +#![feature(crate_visibility_modifier)] + +#![crate_name = "foo"] + +// @has 'foo/struct.FooPublic.html' '//pre' 'pub struct FooPublic' +pub struct FooPublic; +// @has 'foo/struct.FooJustCrate.html' '//pre' 'pub(crate) struct FooJustCrate' +crate struct FooJustCrate; +// @has 'foo/struct.FooPubCrate.html' '//pre' 'pub(crate) struct FooPubCrate' +pub(crate) struct FooPubCrate; +// @has 'foo/struct.FooSelf.html' '//pre' 'pub(self) struct FooSelf' +pub(self) struct FooSelf; +// @has 'foo/struct.FooInSelf.html' '//pre' 'pub(self) struct FooInSelf' +pub(in self) struct FooInSelf; +mod a { + // @has 'foo/a/struct.FooSuper.html' '//pre' 'pub(super) struct FooSuper' + pub(super) struct FooSuper; + // @has 'foo/a/struct.FooInSuper.html' '//pre' 'pub(super) struct FooInSuper' + pub(in super) struct FooInSuper; + // @has 'foo/a/struct.FooInA.html' '//pre' 'pub(in a) struct FooInA' + pub(in a) struct FooInA; + mod b { + // @has 'foo/a/b/struct.FooInSelfSuperB.html' '//pre' 'pub(in self::super::b) struct FooInSelfSuperB' + pub(in self::super::b) struct FooInSelfSuperB; + // @has 'foo/a/b/struct.FooInSuperSuper.html' '//pre' 'pub(in super::super) struct FooInSuperSuper' + pub(in super::super) struct FooInSuperSuper; + // @has 'foo/a/b/struct.FooInAB.html' '//pre' 'pub(in a::b) struct FooInAB' + pub(in a::b) struct FooInAB; + } +} From 87890561f3d09c86b2d99a2115930622b0899d50 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" <leoyvens@gmail.com> Date: Sun, 13 May 2018 12:52:50 -0300 Subject: [PATCH 13/19] Improve eager type resolution error message This PR improves the span of eager resolution type errors referring to indexing and field access to use the base span rather than the whole expression. Also a note "Type must be known at this point." is added to where we at some point in the past emitted the "type must be known at this context" error, so that early failures can be differentiated and will hopefully be less surprising. Fixes #50692 (or at least does the best we can for the moment) r? @estebank --- .../infer/error_reporting/need_type_info.rs | 9 +++++-- src/librustc/traits/error_reporting.rs | 10 ++++---- src/librustc_typeck/check/mod.rs | 8 +++--- src/librustc_typeck/check/writeback.rs | 2 +- .../issue-42234-unknown-receiver-type.stderr | 4 +++ .../span/method-and-field-eager-resolution.rs | 25 +++++++++++++++++++ .../method-and-field-eager-resolution.stderr | 23 +++++++++++++++++ 7 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/span/method-and-field-eager-resolution.rs create mode 100644 src/test/ui/span/method-and-field-eager-resolution.stderr diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index ea3c0a8ddb450..7352c14490d1a 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -14,6 +14,7 @@ use infer::InferCtxt; use infer::type_variable::TypeVariableOrigin; use ty::{self, Ty, TyInfer, TyVar}; use syntax_pos::Span; +use errors::DiagnosticBuilder; struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, @@ -86,7 +87,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - pub fn need_type_info(&self, body_id: Option<hir::BodyId>, span: Span, ty: Ty<'tcx>) { + pub fn need_type_info_err(&self, + body_id: Option<hir::BodyId>, + span: Span, + ty: Ty<'tcx>) + -> DiagnosticBuilder<'gcx> { let ty = self.resolve_type_vars_if_possible(&ty); let name = self.extract_type_name(&ty); @@ -142,6 +147,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.span_label(target_span, label_message); } - err.emit(); + err } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 25be4a2ff5c8b..f6ec01546c18d 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1234,7 +1234,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.lang_items().sized_trait() .map_or(false, |sized_id| sized_id == trait_ref.def_id()) { - self.need_type_info(body_id, span, self_ty); + self.need_type_info_err(body_id, span, self_ty).emit(); } else { let mut err = struct_span_err!(self.tcx.sess, span, E0283, @@ -1251,7 +1251,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Same hacky approach as above to avoid deluging user // with error messages. if !ty.references_error() && !self.tcx.sess.has_errors() { - self.need_type_info(body_id, span, ty); + self.need_type_info_err(body_id, span, ty).emit(); } } @@ -1262,9 +1262,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.need_type_info(body_id, - obligation.cause.span, - a); + self.need_type_info_err(body_id, + obligation.cause.span, + a).emit(); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7b859635f60df..9ac55fda3c1f9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3067,7 +3067,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { base: &'gcx hir::Expr, field: &Spanned<ast::Name>) -> Ty<'tcx> { let expr_t = self.check_expr_with_needs(base, needs); - let expr_t = self.structurally_resolved_type(expr.span, + let expr_t = self.structurally_resolved_type(base.span, expr_t); let mut private_candidate = None; let mut autoderef = self.autoderef(expr.span, expr_t); @@ -4080,7 +4080,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else if idx_t.references_error() { idx_t } else { - let base_t = self.structurally_resolved_type(expr.span, base_t); + let base_t = self.structurally_resolved_type(base.span, base_t); match self.lookup_indexing(expr, base, base_t, idx_t, needs) { Some((index_ty, element_ty)) => { // two-phase not needed because index_ty is never mutable @@ -5053,7 +5053,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty } else { if !self.is_tainted_by_errors() { - self.need_type_info((**self).body_id, sp, ty); + self.need_type_info_err((**self).body_id, sp, ty) + .note("type must be known at this point") + .emit(); } self.demand_suptype(sp, self.tcx.types.err, ty); self.tcx.types.err diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 57c1d33cb5d2a..b0ee1154e863b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -593,7 +593,7 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { fn report_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { self.infcx - .need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t); + .need_type_info_err(Some(self.body.id()), self.span.to_span(&self.tcx), t).emit(); } } } diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr index 23315e3b76a4f..e1e13e9256dcd 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr @@ -5,6 +5,8 @@ LL | let x: Option<_> = None; | - consider giving `x` a type LL | x.unwrap().method_that_could_exist_on_some_type(); | ^^^^^^^^^^ cannot infer type for `T` + | + = note: type must be known at this point error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:22:5 @@ -12,6 +14,8 @@ error[E0282]: type annotations needed LL | / data.iter() //~ ERROR 22:5: 23:20: type annotations needed LL | | .sum::<_>() | |___________________^ cannot infer type for `_` + | + = note: type must be known at this point error: aborting due to 2 previous errors diff --git a/src/test/ui/span/method-and-field-eager-resolution.rs b/src/test/ui/span/method-and-field-eager-resolution.rs new file mode 100644 index 0000000000000..29011abb46016 --- /dev/null +++ b/src/test/ui/span/method-and-field-eager-resolution.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <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. + +// Test that spans get only base in eager type resolution (structurally_resolve_type). + +fn main() { + let mut x = Default::default(); + x.0; + //~^ ERROR type annotations needed + x = 1; +} + +fn foo() { + let mut x = Default::default(); + x[0]; + //~^ ERROR type annotations needed + x = 1; +} diff --git a/src/test/ui/span/method-and-field-eager-resolution.stderr b/src/test/ui/span/method-and-field-eager-resolution.stderr new file mode 100644 index 0000000000000..21e19828a99cf --- /dev/null +++ b/src/test/ui/span/method-and-field-eager-resolution.stderr @@ -0,0 +1,23 @@ +error[E0282]: type annotations needed + --> $DIR/method-and-field-eager-resolution.rs:15:5 + | +LL | let mut x = Default::default(); + | ----- consider giving `x` a type +LL | x.0; + | ^ cannot infer type for `_` + | + = note: type must be known at this point + +error[E0282]: type annotations needed + --> $DIR/method-and-field-eager-resolution.rs:22:5 + | +LL | let mut x = Default::default(); + | ----- consider giving `x` a type +LL | x[0]; + | ^ cannot infer type for `_` + | + = note: type must be known at this point + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. From 2c4b152356fb95afb27a101d7df6c8a7ad6ebf5b Mon Sep 17 00:00:00 2001 From: Corey Farwell <coreyf@rwell.org> Date: Sun, 13 May 2018 15:54:40 -0400 Subject: [PATCH 14/19] =?UTF-8?q?Add=20=E2=80=9CExamples=E2=80=9D=20sectio?= =?UTF-8?q?n=20header=20in=20f32/f64=20doc=20comments.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is recommend by [RFC 0505] and as far as I know, the only primitive types without this heading. [RFC 0505]: https://github.com/rust-lang/rfcs/blob/c892139be692586e0846fbf934be6fceec17f329/text/0505-api-comment-conventions.md#using-markdown --- src/libstd/f32.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++++ src/libstd/f64.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index f849db4ec6027..7314d32b0206a 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -49,6 +49,8 @@ impl f32 { /// Returns the largest integer less than or equal to a number. /// + /// # Examples + /// /// ``` /// let f = 3.99_f32; /// let g = 3.0_f32; @@ -80,6 +82,8 @@ impl f32 { /// Returns the smallest integer greater than or equal to a number. /// + /// # Examples + /// /// ``` /// let f = 3.01_f32; /// let g = 4.0_f32; @@ -100,6 +104,8 @@ impl f32 { /// Returns the nearest integer to a number. Round half-way cases away from /// `0.0`. /// + /// # Examples + /// /// ``` /// let f = 3.3_f32; /// let g = -3.3_f32; @@ -115,6 +121,8 @@ impl f32 { /// Returns the integer part of a number. /// + /// # Examples + /// /// ``` /// let f = 3.3_f32; /// let g = -3.7_f32; @@ -130,6 +138,8 @@ impl f32 { /// Returns the fractional part of a number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -148,6 +158,8 @@ impl f32 { /// Computes the absolute value of `self`. Returns `NAN` if the /// number is `NAN`. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -174,6 +186,8 @@ impl f32 { /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` /// - `NAN` if the number is `NAN` /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -200,6 +214,8 @@ impl f32 { /// Using `mul_add` can be more performant than an unfused multiply-add if /// the target architecture has a dedicated `fma` CPU instruction. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -225,6 +241,8 @@ impl f32 { /// In other words, the result is `self / rhs` rounded to the integer `n` /// such that `self >= n * rhs`. /// + /// # Examples + /// /// ``` /// #![feature(euclidean_division)] /// let a: f32 = 7.0; @@ -248,6 +266,8 @@ impl f32 { /// /// In particular, the result `n` satisfies `0 <= n < rhs.abs()`. /// + /// # Examples + /// /// ``` /// #![feature(euclidean_division)] /// let a: f32 = 7.0; @@ -273,6 +293,8 @@ impl f32 { /// /// Using this function is generally faster than using `powf` /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -289,6 +311,8 @@ impl f32 { /// Raises a number to a floating point power. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -311,6 +335,8 @@ impl f32 { /// /// Returns NaN if `self` is a negative number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -334,6 +360,8 @@ impl f32 { /// Returns `e^(self)`, (the exponential function). /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -358,6 +386,8 @@ impl f32 { /// Returns `2^(self)`. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -376,6 +406,8 @@ impl f32 { /// Returns the natural logarithm of the number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -404,6 +436,8 @@ impl f32 { /// `self.log2()` can produce more accurate results for base 2, and /// `self.log10()` can produce more accurate results for base 10. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -420,6 +454,8 @@ impl f32 { /// Returns the base 2 logarithm of the number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -441,6 +477,8 @@ impl f32 { /// Returns the base 10 logarithm of the number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -466,6 +504,8 @@ impl f32 { /// * If `self <= other`: `0:0` /// * Else: `self - other` /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -493,6 +533,8 @@ impl f32 { /// Takes the cubic root of a number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -512,6 +554,8 @@ impl f32 { /// Calculates the length of the hypotenuse of a right-angle triangle given /// legs of length `x` and `y`. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -531,6 +575,8 @@ impl f32 { /// Computes the sine of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -552,6 +598,8 @@ impl f32 { /// Computes the cosine of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -573,6 +621,8 @@ impl f32 { /// Computes the tangent of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -591,6 +641,8 @@ impl f32 { /// the range [-pi/2, pi/2] or NaN if the number is outside the range /// [-1, 1]. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -611,6 +663,8 @@ impl f32 { /// the range [0, pi] or NaN if the number is outside the range /// [-1, 1]. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -630,6 +684,8 @@ impl f32 { /// Computes the arctangent of a number. Return value is in radians in the /// range [-pi/2, pi/2]; /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -653,6 +709,8 @@ impl f32 { /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -682,6 +740,8 @@ impl f32 { /// Simultaneously computes the sine and cosine of the number, `x`. Returns /// `(sin(x), cos(x))`. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -703,6 +763,8 @@ impl f32 { /// Returns `e^(self) - 1` in a way that is accurate even if the /// number is close to zero. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -722,6 +784,8 @@ impl f32 { /// Returns `ln(1+n)` (natural logarithm) more accurately than if /// the operations were performed separately. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -740,6 +804,8 @@ impl f32 { /// Hyperbolic sine function. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -761,6 +827,8 @@ impl f32 { /// Hyperbolic cosine function. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -782,6 +850,8 @@ impl f32 { /// Hyperbolic tangent function. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -803,6 +873,8 @@ impl f32 { /// Inverse hyperbolic sine function. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -825,6 +897,8 @@ impl f32 { /// Inverse hyperbolic cosine function. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -846,6 +920,8 @@ impl f32 { /// Inverse hyperbolic tangent function. /// + /// # Examples + /// /// ``` /// use std::f32; /// diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 40c3f4d0ef726..75edba8979f9a 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -49,6 +49,8 @@ impl f64 { /// Returns the largest integer less than or equal to a number. /// + /// # Examples + /// /// ``` /// let f = 3.99_f64; /// let g = 3.0_f64; @@ -64,6 +66,8 @@ impl f64 { /// Returns the smallest integer greater than or equal to a number. /// + /// # Examples + /// /// ``` /// let f = 3.01_f64; /// let g = 4.0_f64; @@ -80,6 +84,8 @@ impl f64 { /// Returns the nearest integer to a number. Round half-way cases away from /// `0.0`. /// + /// # Examples + /// /// ``` /// let f = 3.3_f64; /// let g = -3.3_f64; @@ -95,6 +101,8 @@ impl f64 { /// Returns the integer part of a number. /// + /// # Examples + /// /// ``` /// let f = 3.3_f64; /// let g = -3.7_f64; @@ -110,6 +118,8 @@ impl f64 { /// Returns the fractional part of a number. /// + /// # Examples + /// /// ``` /// let x = 3.5_f64; /// let y = -3.5_f64; @@ -126,6 +136,8 @@ impl f64 { /// Computes the absolute value of `self`. Returns `NAN` if the /// number is `NAN`. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -152,6 +164,8 @@ impl f64 { /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` /// - `NAN` if the number is `NAN` /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -178,6 +192,8 @@ impl f64 { /// Using `mul_add` can be more performant than an unfused multiply-add if /// the target architecture has a dedicated `fma` CPU instruction. /// + /// # Examples + /// /// ``` /// let m = 10.0_f64; /// let x = 4.0_f64; @@ -201,6 +217,8 @@ impl f64 { /// In other words, the result is `self / rhs` rounded to the integer `n` /// such that `self >= n * rhs`. /// + /// # Examples + /// /// ``` /// #![feature(euclidean_division)] /// let a: f64 = 7.0; @@ -224,6 +242,8 @@ impl f64 { /// /// In particular, the result `n` satisfies `0 <= n < rhs.abs()`. /// + /// # Examples + /// /// ``` /// #![feature(euclidean_division)] /// let a: f64 = 7.0; @@ -248,6 +268,8 @@ impl f64 { /// /// Using this function is generally faster than using `powf` /// + /// # Examples + /// /// ``` /// let x = 2.0_f64; /// let abs_difference = (x.powi(2) - x*x).abs(); @@ -262,6 +284,8 @@ impl f64 { /// Raises a number to a floating point power. /// + /// # Examples + /// /// ``` /// let x = 2.0_f64; /// let abs_difference = (x.powf(2.0) - x*x).abs(); @@ -278,6 +302,8 @@ impl f64 { /// /// Returns NaN if `self` is a negative number. /// + /// # Examples + /// /// ``` /// let positive = 4.0_f64; /// let negative = -4.0_f64; @@ -299,6 +325,8 @@ impl f64 { /// Returns `e^(self)`, (the exponential function). /// + /// # Examples + /// /// ``` /// let one = 1.0_f64; /// // e^1 @@ -317,6 +345,8 @@ impl f64 { /// Returns `2^(self)`. /// + /// # Examples + /// /// ``` /// let f = 2.0_f64; /// @@ -333,6 +363,8 @@ impl f64 { /// Returns the natural logarithm of the number. /// + /// # Examples + /// /// ``` /// let one = 1.0_f64; /// // e^1 @@ -355,6 +387,8 @@ impl f64 { /// `self.log2()` can produce more accurate results for base 2, and /// `self.log10()` can produce more accurate results for base 10. /// + /// # Examples + /// /// ``` /// let five = 5.0_f64; /// @@ -369,6 +403,8 @@ impl f64 { /// Returns the base 2 logarithm of the number. /// + /// # Examples + /// /// ``` /// let two = 2.0_f64; /// @@ -390,6 +426,8 @@ impl f64 { /// Returns the base 10 logarithm of the number. /// + /// # Examples + /// /// ``` /// let ten = 10.0_f64; /// @@ -409,6 +447,8 @@ impl f64 { /// * If `self <= other`: `0:0` /// * Else: `self - other` /// + /// # Examples + /// /// ``` /// let x = 3.0_f64; /// let y = -3.0_f64; @@ -434,6 +474,8 @@ impl f64 { /// Takes the cubic root of a number. /// + /// # Examples + /// /// ``` /// let x = 8.0_f64; /// @@ -451,6 +493,8 @@ impl f64 { /// Calculates the length of the hypotenuse of a right-angle triangle given /// legs of length `x` and `y`. /// + /// # Examples + /// /// ``` /// let x = 2.0_f64; /// let y = 3.0_f64; @@ -468,6 +512,8 @@ impl f64 { /// Computes the sine of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -485,6 +531,8 @@ impl f64 { /// Computes the cosine of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -502,6 +550,8 @@ impl f64 { /// Computes the tangent of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -520,6 +570,8 @@ impl f64 { /// the range [-pi/2, pi/2] or NaN if the number is outside the range /// [-1, 1]. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -540,6 +592,8 @@ impl f64 { /// the range [0, pi] or NaN if the number is outside the range /// [-1, 1]. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -559,6 +613,8 @@ impl f64 { /// Computes the arctangent of a number. Return value is in radians in the /// range [-pi/2, pi/2]; /// + /// # Examples + /// /// ``` /// let f = 1.0_f64; /// @@ -580,6 +636,8 @@ impl f64 { /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -609,6 +667,8 @@ impl f64 { /// Simultaneously computes the sine and cosine of the number, `x`. Returns /// `(sin(x), cos(x))`. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -630,6 +690,8 @@ impl f64 { /// Returns `e^(self) - 1` in a way that is accurate even if the /// number is close to zero. /// + /// # Examples + /// /// ``` /// let x = 7.0_f64; /// @@ -647,6 +709,8 @@ impl f64 { /// Returns `ln(1+n)` (natural logarithm) more accurately than if /// the operations were performed separately. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -665,6 +729,8 @@ impl f64 { /// Hyperbolic sine function. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -686,6 +752,8 @@ impl f64 { /// Hyperbolic cosine function. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -707,6 +775,8 @@ impl f64 { /// Hyperbolic tangent function. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -728,6 +798,8 @@ impl f64 { /// Inverse hyperbolic sine function. /// + /// # Examples + /// /// ``` /// let x = 1.0_f64; /// let f = x.sinh().asinh(); @@ -748,6 +820,8 @@ impl f64 { /// Inverse hyperbolic cosine function. /// + /// # Examples + /// /// ``` /// let x = 1.0_f64; /// let f = x.cosh().acosh(); @@ -767,6 +841,8 @@ impl f64 { /// Inverse hyperbolic tangent function. /// + /// # Examples + /// /// ``` /// use std::f64; /// From 703ecebe02333014e6c948370042db9df696d818 Mon Sep 17 00:00:00 2001 From: Katrin Leinweber <9948149+katrinleinweber@users.noreply.github.com> Date: Mon, 14 May 2018 07:17:56 +0200 Subject: [PATCH 15/19] Hyperlink DOI against preferred resolver https://www.doi.org/doi_handbook/3_Resolution.html#3.8 --- src/libsyntax_pos/hygiene.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 658408519b9c7..be031ea98c9d2 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -13,7 +13,7 @@ //! `[1]` Matthew Flatt, Ryan Culpepper, David Darais, and Robert Bruce Findler. 2012. //! *Macros that work together: Compile-time bindings, partial expansion, //! and definition contexts*. J. Funct. Program. 22, 2 (March 2012), 181-216. -//! DOI=10.1017/S0956796812000093 <http://dx.doi.org/10.1017/S0956796812000093> +//! DOI=10.1017/S0956796812000093 <https://doi.org/10.1017/S0956796812000093> use GLOBALS; use Span; From 6d1da8232997af4b785486329f01995440818920 Mon Sep 17 00:00:00 2001 From: Tobias Bucher <tobiasbucher5991@gmail.com> Date: Mon, 14 May 2018 13:20:39 +0200 Subject: [PATCH 16/19] Don't unconditionally set CLOEXEC twice on every fd we open on Linux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, every `open64` was accompanied by a `ioctl(…, FIOCLEX)`, because some old Linux version would ignore the `O_CLOEXEC` flag we pass to the `open64` function. Now, we check whether the `CLOEXEC` flag is set on the first file we open – if it is, we won't do extra syscalls for every opened file. If it is not set, we fall back to the old behavior of unconditionally calling `ioctl(…, FIOCLEX)` on newly opened files. On old Linuxes, this amounts to one extra syscall per process, namely the `fcntl(…, F_GETFD)` call to check the `CLOEXEC` flag. On new Linuxes, this reduces the number of syscalls per opened file by one, except for the first file, where it does the same number of syscalls as before (`fcntl(…, F_GETFD)` to check the flag instead of `ioctl(…, FIOCLEX)` to set it). --- src/libstd/sys/unix/fd.rs | 7 +++++++ src/libstd/sys/unix/fs.rs | 41 +++++++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 5dafc3251e755..72272d0581a79 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -140,6 +140,13 @@ impl FileDesc { } } + #[cfg(target_os = "linux")] + pub fn get_cloexec(&self) -> io::Result<bool> { + unsafe { + Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) + } + } + #[cfg(not(any(target_env = "newlib", target_os = "solaris", target_os = "emscripten", diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index a1ca839dc1872..77968ffdedf37 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -441,15 +441,48 @@ impl File { // 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, so we continue - // to explicitly ask for a CLOEXEC fd here. + // 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. - if cfg!(target_os = "linux") { - fd.set_cloexec()?; + #[cfg(target_os = "linux")] + fn ensure_cloexec(fd: &FileDesc) -> io::Result<()> { + use 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)) } From af2af4a30262cfd0a176e89ef2a965ee0fdcf171 Mon Sep 17 00:00:00 2001 From: Eric Huss <eric@huss.org> Date: Sat, 12 May 2018 13:08:55 -0700 Subject: [PATCH 17/19] Update Cargo Regression fixes: - rust-lang/cargo#5503 - cargo rustc broken for tests in project with bins - rust-lang/cargo#5520 - (#50640) shared proc-macro dependency built incorrectly Changes: - rust-lang/cargo#5522 - Add option to set user-agent - rust-lang/cargo#5519 - NFC: fix a couple of typos, found by codespell. - rust-lang/cargo#5513 - Fix `panic` for binaries built during tests. - rust-lang/cargo#5512 - simplify build_requirements - rust-lang/cargo#5301 - Add --build-plan for 'cargo build' - rust-lang/cargo#5460 - Be more conservative about which files are linked to the output dir. - rust-lang/cargo#5509 - Use the new stable - rust-lang/cargo#5507 - Does not print seconds fraction with minutes - rust-lang/cargo#5498 - Bump to 0.29.0 - rust-lang/cargo#5497 - Mention +nightly in ARCHITECTURE.md --- src/Cargo.lock | 8 ++++---- src/tools/cargo | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 70a230cb7f7ac..bcc3c90d3cf17 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -190,13 +190,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo" -version = "0.28.0" +version = "0.29.0" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crates-io 0.16.0", + "crates-io 0.17.0", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -457,7 +457,7 @@ dependencies = [ [[package]] name = "crates-io" -version = "0.16.0" +version = "0.17.0" dependencies = [ "curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1634,7 +1634,7 @@ dependencies = [ name = "rls" version = "0.127.0" dependencies = [ - "cargo 0.28.0", + "cargo 0.29.0", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.197 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/tools/cargo b/src/tools/cargo index 9e53ac6e6525d..b24b455c32704 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 9e53ac6e6525da914cb05a85e5e8eff7b5dca81f +Subproject commit b24b455c327048df940ab8322cc6f9d361fef918 From 3a5b13ad36d5cb4081c727c78e7d6fd6711108b9 Mon Sep 17 00:00:00 2001 From: Oliver Schneider <git-no-reply-9879165716479413131@oli-obk.de> Date: Mon, 14 May 2018 16:11:24 +0200 Subject: [PATCH 18/19] Bump clippy --- src/Cargo.lock | 6 +++--- src/tools/clippy | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 70a230cb7f7ac..2f52c88955885 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -288,12 +288,12 @@ dependencies = [ [[package]] name = "clippy" -version = "0.0.198" +version = "0.0.200" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.2.0", - "clippy_lints 0.0.198", + "clippy_lints 0.0.200", "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -331,7 +331,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.0.198" +version = "0.0.200" dependencies = [ "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/tools/clippy b/src/tools/clippy index 7a4c00c669b3b..c658fc8cbcd1f 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 7a4c00c669b3bf0ffb24c7aa89a776cd48f1e2d0 +Subproject commit c658fc8cbcd1f199edd445a49cb43139ebdc5f02 From 2ccf71c3b24e9a3ba5062c8230aa66079b748edb Mon Sep 17 00:00:00 2001 From: kennytm <kennytm@gmail.com> Date: Fri, 11 May 2018 01:08:58 +0800 Subject: [PATCH 19/19] Migrate the toolstate update bot to rust-highfive --- .travis.yml | 2 +- appveyor.yml | 2 +- src/ci/docker/x86_64-gnu-tools/repo.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 23c47bc9f7648..9e62b895ed21e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -197,7 +197,7 @@ env: # AWS_SECRET_ACCESS_KEY=... - secure: "j96XxTVOSUf4s4r4htIxn/fvIa5DWbMgLqWl7r8z2QfgUwscmkMXAwXuFNc7s7bGTpV/+CgDiMFFM6BAFLGKutytIF6oA02s9b+usQYnM0th7YQ2AIgm9GtMTJCJp4AoyfFmh8F2faUICBZlfVLUJ34udHEe35vOklix+0k4WDo=" # TOOLSTATE_REPO_ACCESS_TOKEN=... - - secure: "cFh8thThqEJLC98XKI5pfqflUzOlxsYPRW20AWRaYOOgYHPTiGWypTXiPbGSKaeAXTZoOA+DpQtEmefc0U6lt9dHc7a/MIaK6isFurjlnKYiLOeTruzyu1z7PWCeZ/jKXsU2RK/88DBtlNwfMdaMIeuKj14IVfpepPPL71ETbuk=" + - secure: "ESfcXqv4N2VMhqi2iIyw6da9VrsA78I4iR1asouCaq4hzTTrkB4WNRrfURy6xg72gQ4nMhtRJbB0/2jmc9Cu1+g2CzXtyiL223aJ5CKrXdcvbitopQSDfp07dMWm+UED+hNFEanpErKAeU/6FM3A+J+60PMk8MCF1h9tqNRISJw=" before_install: # We'll use the AWS cli to download/upload cached docker layers, so install diff --git a/appveyor.yml b/appveyor.yml index 60f5b4be8def8..b1e2e1545cf85 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: 7Y+JiquYedOAgnUU26uL0DPzrxmTtR+qIwG6rNKSuWDffqU3vVZxbGXim9QpTO80 SCCACHE_DIGEST: f808afabb4a4eb1d7112bcb3fa6be03b61e93412890c88e177c667eb37f46353d7ec294e559b16f9f4b5e894f2185fe7670a0df15fd064889ecbd80f0c34166c TOOLSTATE_REPO_ACCESS_TOKEN: - secure: PTZiSxJMVUZ0VnMR5i13E4OagbXfglj7pcskDQiKufVrDm13mLoI0vDJAEM35+bY + secure: gKGlVktr7iuqCoYSxHxDE9ltLOKU0nYDEuQxvWbNxUIW7ri5ppn8L06jQzN0GGzN # By default schannel checks revocation of certificates unlike some other SSL # backends, but we've historically had problems on CI where a revocation diff --git a/src/ci/docker/x86_64-gnu-tools/repo.sh b/src/ci/docker/x86_64-gnu-tools/repo.sh index c10afef753e81..807e6fb7b642e 100644 --- a/src/ci/docker/x86_64-gnu-tools/repo.sh +++ b/src/ci/docker/x86_64-gnu-tools/repo.sh @@ -60,7 +60,7 @@ commit_toolstate_change() { OLDFLAGS="$-" set -eu - git config --global user.email '34210020+rust-toolstate-update@users.noreply.github.com' + git config --global user.email '7378925+rust-toolstate-update@users.noreply.github.com' git config --global user.name 'Rust Toolstate Update' git config --global credential.helper store printf 'https://%s:x-oauth-basic@github.com\n' "$TOOLSTATE_REPO_ACCESS_TOKEN" \