about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-07-19 14:17:08 +0000
committerbors <bors@rust-lang.org>2020-07-19 14:17:08 +0000
commitd7f94516345a36ddfcd68cbdf1df835d356795c3 (patch)
treebea3e4ab40d0c1eaf79c02d717cf8f5be4d3366f /src/libstd
parent48036804d2bc461b243c5d291b850e44bcca68ef (diff)
parent1636961a0e02adb7a1200d98a3c94f68decd3a13 (diff)
downloadrust-d7f94516345a36ddfcd68cbdf1df835d356795c3.tar.gz
rust-d7f94516345a36ddfcd68cbdf1df835d356795c3.zip
Auto merge of #74518 - Manishearth:rollup-jfmnh1r, r=Manishearth
Rollup of 4 pull requests

Successful merges:

 - #74333 (Deny unsafe operations in unsafe functions in libstd/alloc.rs)
 - #74356 (Remove combine function)
 - #74419 (Add a thumbv4t-none-eabi target)
 - #74485 (More intra-doc links, add explicit exception list to linkchecker)

Failed merges:

 - #74486 (Improve Read::read_exact documentation)

r? @ghost
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/alloc.rs91
-rw-r--r--src/libstd/collections/hash/map.rs87
-rw-r--r--src/libstd/collections/hash/set.rs47
-rw-r--r--src/libstd/io/mod.rs141
-rw-r--r--src/libstd/sys/unix/process/process_unix.rs10
5 files changed, 153 insertions, 223 deletions
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs
index 38d223d84e9..ecfaaeace51 100644
--- a/src/libstd/alloc.rs
+++ b/src/libstd/alloc.rs
@@ -59,6 +59,7 @@
 //! The `#[global_allocator]` can only be used once in a crate
 //! or its recursive dependencies.
 
+#![deny(unsafe_op_in_unsafe_fn)]
 #![stable(feature = "alloc_module", since = "1.28.0")]
 
 use core::intrinsics;
@@ -158,7 +159,9 @@ unsafe impl AllocRef for System {
     #[inline]
     unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
         if layout.size() != 0 {
-            GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
+            // SAFETY: The safety guarantees are explained in the documentation
+            // for the `GlobalAlloc` trait and its `dealloc` method.
+            unsafe { GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) }
         }
     }
 
@@ -184,16 +187,36 @@ unsafe impl AllocRef for System {
         match placement {
             ReallocPlacement::InPlace => Err(AllocErr),
             ReallocPlacement::MayMove if layout.size() == 0 => {
-                let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
+                let new_layout =
+                    // SAFETY: The new size and layout alignement guarantees
+                    // are transfered to the caller (they come from parameters).
+                    //
+                    // See the preconditions for `Layout::from_size_align` to
+                    // see what must be checked.
+                    unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) };
                 self.alloc(new_layout, init)
             }
             ReallocPlacement::MayMove => {
-                // `realloc` probably checks for `new_size > size` or something similar.
-                intrinsics::assume(new_size > size);
-                let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size);
-                let memory =
-                    MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size };
-                init.init_offset(memory, size);
+                // SAFETY:
+                //
+                // The safety guarantees are explained in the documentation
+                // for the `GlobalAlloc` trait and its `dealloc` method.
+                //
+                // `realloc` probably checks for `new_size > size` or something
+                // similar.
+                //
+                // For the guarantees about `init_offset`, see its documentation:
+                // `ptr` is assumed valid (and checked for non-NUL) and
+                // `memory.size` is set to `new_size` so the offset being `size`
+                // is valid.
+                let memory = unsafe {
+                    intrinsics::assume(new_size > size);
+                    let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size);
+                    let memory =
+                        MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size };
+                    init.init_offset(memory, size);
+                    memory
+                };
                 Ok(memory)
             }
         }
@@ -220,14 +243,28 @@ unsafe impl AllocRef for System {
         match placement {
             ReallocPlacement::InPlace => Err(AllocErr),
             ReallocPlacement::MayMove if new_size == 0 => {
-                self.dealloc(ptr, layout);
+                // SAFETY: see `GlobalAlloc::dealloc` for the guarantees that
+                // must be respected. `ptr` and `layout` are parameters and so
+                // those guarantees must be checked by the caller.
+                unsafe { self.dealloc(ptr, layout) };
                 Ok(MemoryBlock { ptr: layout.dangling(), size: 0 })
             }
             ReallocPlacement::MayMove => {
-                // `realloc` probably checks for `new_size < size` or something similar.
-                intrinsics::assume(new_size < size);
-                let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size);
-                Ok(MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size })
+                // SAFETY:
+                //
+                // See `GlobalAlloc::realloc` for more informations about the
+                // guarantees expected by this method. `ptr`, `layout` and
+                // `new_size` are parameters and the responsability for their
+                // correctness is left to the caller.
+                //
+                // `realloc` probably checks for `new_size < size` or something
+                // similar.
+                let memory = unsafe {
+                    intrinsics::assume(new_size < size);
+                    let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size);
+                    MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }
+                };
+                Ok(memory)
             }
         }
     }
@@ -300,13 +337,19 @@ pub mod __default_lib_allocator {
 
     #[rustc_std_internal_symbol]
     pub unsafe extern "C" fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
-        let layout = Layout::from_size_align_unchecked(size, align);
-        System.alloc(layout)
+        // SAFETY: see the guarantees expected by `Layout::from_size_align` and
+        // `GlobalAlloc::alloc`.
+        unsafe {
+            let layout = Layout::from_size_align_unchecked(size, align);
+            System.alloc(layout)
+        }
     }
 
     #[rustc_std_internal_symbol]
     pub unsafe extern "C" fn __rdl_dealloc(ptr: *mut u8, size: usize, align: usize) {
-        System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
+        // SAFETY: see the guarantees expected by `Layout::from_size_align` and
+        // `GlobalAlloc::dealloc`.
+        unsafe { System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) }
     }
 
     #[rustc_std_internal_symbol]
@@ -316,13 +359,21 @@ pub mod __default_lib_allocator {
         align: usize,
         new_size: usize,
     ) -> *mut u8 {
-        let old_layout = Layout::from_size_align_unchecked(old_size, align);
-        System.realloc(ptr, old_layout, new_size)
+        // SAFETY: see the guarantees expected by `Layout::from_size_align` and
+        // `GlobalAlloc::realloc`.
+        unsafe {
+            let old_layout = Layout::from_size_align_unchecked(old_size, align);
+            System.realloc(ptr, old_layout, new_size)
+        }
     }
 
     #[rustc_std_internal_symbol]
     pub unsafe extern "C" fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
-        let layout = Layout::from_size_align_unchecked(size, align);
-        System.alloc_zeroed(layout)
+        // SAFETY: see the guarantees expected by `Layout::from_size_align` and
+        // `GlobalAlloc::alloc_zeroed`.
+        unsafe {
+            let layout = Layout::from_size_align_unchecked(size, align);
+            System.alloc_zeroed(layout)
+        }
     }
 }
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 5ba5eff4407..7b48deee1ab 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -148,14 +148,11 @@ use crate::sys;
 /// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`].
 /// We must also derive [`PartialEq`].
 ///
-/// [`Eq`]: ../../std/cmp/trait.Eq.html
-/// [`Hash`]: ../../std/hash/trait.Hash.html
-/// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html
-/// [`RefCell`]: ../../std/cell/struct.RefCell.html
-/// [`Cell`]: ../../std/cell/struct.Cell.html
-/// [`default`]: #method.default
-/// [`with_hasher`]: #method.with_hasher
-/// [`with_capacity_and_hasher`]: #method.with_capacity_and_hasher
+/// [`RefCell`]: crate::cell::RefCell
+/// [`Cell`]: crate::cell::Cell
+/// [`default`]: Default::default
+/// [`with_hasher`]: Self::with_hasher
+/// [`with_capacity_and_hasher`]: Self::with_capacity_and_hasher
 /// [`fnv`]: https://crates.io/crates/fnv
 ///
 /// ```
@@ -264,8 +261,6 @@ impl<K, V, S> HashMap<K, V, S> {
     /// let mut map = HashMap::with_hasher(s);
     /// map.insert(1, 2);
     /// ```
-    ///
-    /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
@@ -296,8 +291,6 @@ impl<K, V, S> HashMap<K, V, S> {
     /// let mut map = HashMap::with_capacity_and_hasher(10, s);
     /// map.insert(1, 2);
     /// ```
-    ///
-    /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
@@ -524,8 +517,6 @@ impl<K, V, S> HashMap<K, V, S> {
 
     /// Returns a reference to the map's [`BuildHasher`].
     ///
-    /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -556,8 +547,6 @@ where
     ///
     /// Panics if the new allocation size overflows [`usize`].
     ///
-    /// [`usize`]: ../../std/primitive.usize.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -676,9 +665,6 @@ where
     /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
     /// the key type.
     ///
-    /// [`Eq`]: ../../std/cmp/trait.Eq.html
-    /// [`Hash`]: ../../std/hash/trait.Hash.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -705,9 +691,6 @@ where
     /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
     /// the key type.
     ///
-    /// [`Eq`]: ../../std/cmp/trait.Eq.html
-    /// [`Hash`]: ../../std/hash/trait.Hash.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -734,9 +717,6 @@ where
     /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
     /// the key type.
     ///
-    /// [`Eq`]: ../../std/cmp/trait.Eq.html
-    /// [`Hash`]: ../../std/hash/trait.Hash.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -763,9 +743,6 @@ where
     /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
     /// the key type.
     ///
-    /// [`Eq`]: ../../std/cmp/trait.Eq.html
-    /// [`Hash`]: ../../std/hash/trait.Hash.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -797,8 +774,7 @@ where
     /// types that can be `==` without being identical. See the [module-level
     /// documentation] for more.
     ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [module-level documentation]: index.html#insert-and-complex-keys
+    /// [module-level documentation]: crate::collections#insert-and-complex-keys
     ///
     /// # Examples
     ///
@@ -826,9 +802,6 @@ where
     /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
     /// the key type.
     ///
-    /// [`Eq`]: ../../std/cmp/trait.Eq.html
-    /// [`Hash`]: ../../std/hash/trait.Hash.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -856,9 +829,6 @@ where
     /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
     /// the key type.
     ///
-    /// [`Eq`]: ../../std/cmp/trait.Eq.html
-    /// [`Hash`]: ../../std/hash/trait.Hash.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -1040,8 +1010,7 @@ where
 /// This `struct` is created by the [`iter`] method on [`HashMap`]. See its
 /// documentation for more.
 ///
-/// [`iter`]: struct.HashMap.html#method.iter
-/// [`HashMap`]: struct.HashMap.html
+/// [`iter`]: HashMap::iter
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a, V: 'a> {
     base: base::Iter<'a, K, V>,
@@ -1068,8 +1037,7 @@ impl<K: Debug, V: Debug> fmt::Debug for Iter<'_, K, V> {
 /// This `struct` is created by the [`iter_mut`] method on [`HashMap`]. See its
 /// documentation for more.
 ///
-/// [`iter_mut`]: struct.HashMap.html#method.iter_mut
-/// [`HashMap`]: struct.HashMap.html
+/// [`iter_mut`]: HashMap::iter_mut
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, K: 'a, V: 'a> {
     base: base::IterMut<'a, K, V>,
@@ -1088,8 +1056,7 @@ impl<'a, K, V> IterMut<'a, K, V> {
 /// This `struct` is created by the [`into_iter`] method on [`HashMap`]
 /// (provided by the `IntoIterator` trait). See its documentation for more.
 ///
-/// [`into_iter`]: struct.HashMap.html#method.into_iter
-/// [`HashMap`]: struct.HashMap.html
+/// [`into_iter`]: IntoIterator::into_iter
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K, V> {
     base: base::IntoIter<K, V>,
@@ -1108,8 +1075,7 @@ impl<K, V> IntoIter<K, V> {
 /// This `struct` is created by the [`keys`] method on [`HashMap`]. See its
 /// documentation for more.
 ///
-/// [`keys`]: struct.HashMap.html#method.keys
-/// [`HashMap`]: struct.HashMap.html
+/// [`keys`]: HashMap::keys
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Keys<'a, K: 'a, V: 'a> {
     inner: Iter<'a, K, V>,
@@ -1136,8 +1102,7 @@ impl<K: Debug, V> fmt::Debug for Keys<'_, K, V> {
 /// This `struct` is created by the [`values`] method on [`HashMap`]. See its
 /// documentation for more.
 ///
-/// [`values`]: struct.HashMap.html#method.values
-/// [`HashMap`]: struct.HashMap.html
+/// [`values`]: HashMap::values
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Values<'a, K: 'a, V: 'a> {
     inner: Iter<'a, K, V>,
@@ -1164,8 +1129,7 @@ impl<K, V: Debug> fmt::Debug for Values<'_, K, V> {
 /// This `struct` is created by the [`drain`] method on [`HashMap`]. See its
 /// documentation for more.
 ///
-/// [`drain`]: struct.HashMap.html#method.drain
-/// [`HashMap`]: struct.HashMap.html
+/// [`drain`]: HashMap::drain
 #[stable(feature = "drain", since = "1.6.0")]
 pub struct Drain<'a, K: 'a, V: 'a> {
     base: base::Drain<'a, K, V>,
@@ -1184,8 +1148,7 @@ impl<'a, K, V> Drain<'a, K, V> {
 /// This `struct` is created by the [`values_mut`] method on [`HashMap`]. See its
 /// documentation for more.
 ///
-/// [`values_mut`]: struct.HashMap.html#method.values_mut
-/// [`HashMap`]: struct.HashMap.html
+/// [`values_mut`]: HashMap::values_mut
 #[stable(feature = "map_values_mut", since = "1.10.0")]
 pub struct ValuesMut<'a, K: 'a, V: 'a> {
     inner: IterMut<'a, K, V>,
@@ -1195,7 +1158,7 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> {
 ///
 /// See the [`HashMap::raw_entry_mut`] docs for usage examples.
 ///
-/// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut
+/// [`HashMap::raw_entry_mut`]: HashMap::raw_entry_mut
 
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> {
@@ -1209,9 +1172,8 @@ pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> {
 /// This `enum` is constructed through the [`raw_entry_mut`] method on [`HashMap`],
 /// then calling one of the methods of that [`RawEntryBuilderMut`].
 ///
-/// [`HashMap`]: struct.HashMap.html
 /// [`Entry`]: enum.Entry.html
-/// [`raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut
+/// [`raw_entry_mut`]: HashMap::raw_entry_mut
 /// [`RawEntryBuilderMut`]: struct.RawEntryBuilderMut.html
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> {
@@ -1223,8 +1185,6 @@ pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> {
 
 /// A view into an occupied entry in a `HashMap`.
 /// It is part of the [`RawEntryMut`] enum.
-///
-/// [`RawEntryMut`]: enum.RawEntryMut.html
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> {
     base: base::RawOccupiedEntryMut<'a, K, V>,
@@ -1232,8 +1192,6 @@ pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> {
 
 /// A view into a vacant entry in a `HashMap`.
 /// It is part of the [`RawEntryMut`] enum.
-///
-/// [`RawEntryMut`]: enum.RawEntryMut.html
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> {
     base: base::RawVacantEntryMut<'a, K, V, S>,
@@ -1243,7 +1201,7 @@ pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> {
 ///
 /// See the [`HashMap::raw_entry`] docs for usage examples.
 ///
-/// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry
+/// [`HashMap::raw_entry`]: HashMap::raw_entry
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 pub struct RawEntryBuilder<'a, K: 'a, V: 'a, S: 'a> {
     map: &'a HashMap<K, V, S>,
@@ -1597,8 +1555,7 @@ impl<K, V, S> Debug for RawEntryBuilder<'_, K, V, S> {
 ///
 /// This `enum` is constructed from the [`entry`] method on [`HashMap`].
 ///
-/// [`HashMap`]: struct.HashMap.html
-/// [`entry`]: struct.HashMap.html#method.entry
+/// [`entry`]: HashMap::entry
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Entry<'a, K: 'a, V: 'a> {
     /// An occupied entry.
@@ -2156,7 +2113,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// If you need a reference to the `OccupiedEntry` which may outlive the
     /// destruction of the `Entry` value, see [`into_mut`].
     ///
-    /// [`into_mut`]: #method.into_mut
+    /// [`into_mut`]: Self::into_mut
     ///
     /// # Examples
     ///
@@ -2189,7 +2146,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     ///
     /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
     ///
-    /// [`get_mut`]: #method.get_mut
+    /// [`get_mut`]: Self::get_mut
     ///
     /// # Examples
     ///
@@ -2475,9 +2432,6 @@ where
 /// [`Hasher`], but the hashers created by two different `RandomState`
 /// instances are unlikely to produce the same result for the same values.
 ///
-/// [`HashMap`]: struct.HashMap.html
-/// [`Hasher`]: ../../hash/trait.Hasher.html
-///
 /// # Examples
 ///
 /// ```
@@ -2547,9 +2501,6 @@ impl BuildHasher for RandomState {
 ///
 /// The internal algorithm is not specified, and so it and its hashes should
 /// not be relied upon over releases.
-///
-/// [`RandomState`]: struct.RandomState.html
-/// [`Hasher`]: ../../hash/trait.Hasher.html
 #[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
 #[allow(deprecated)]
 #[derive(Clone, Debug)]
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index cb2f829803b..10bf917daea 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -98,12 +98,8 @@ use super::map::{self, HashMap, Keys, RandomState};
 /// // use the values stored in the set
 /// ```
 ///
-/// [`Cell`]: ../../std/cell/struct.Cell.html
-/// [`Eq`]: ../../std/cmp/trait.Eq.html
-/// [`Hash`]: ../../std/hash/trait.Hash.html
-/// [`HashMap`]: struct.HashMap.html
-/// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html
-/// [`RefCell`]: ../../std/cell/struct.RefCell.html
+/// [`RefCell`]: crate::cell::RefCell
+/// [`Cell`]: crate::cell::Cell
 #[derive(Clone)]
 #[cfg_attr(not(test), rustc_diagnostic_item = "hashset_type")]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -286,8 +282,6 @@ impl<T, S> HashSet<T, S> {
     /// let mut set = HashSet::with_hasher(s);
     /// set.insert(2);
     /// ```
-    ///
-    /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn with_hasher(hasher: S) -> HashSet<T, S> {
@@ -318,8 +312,6 @@ impl<T, S> HashSet<T, S> {
     /// let mut set = HashSet::with_capacity_and_hasher(10, s);
     /// set.insert(1);
     /// ```
-    ///
-    /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashSet<T, S> {
@@ -328,8 +320,6 @@ impl<T, S> HashSet<T, S> {
 
     /// Returns a reference to the set's [`BuildHasher`].
     ///
-    /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -577,9 +567,6 @@ where
     /// assert_eq!(set.contains(&1), true);
     /// assert_eq!(set.contains(&4), false);
     /// ```
-    ///
-    /// [`Eq`]: ../../std/cmp/trait.Eq.html
-    /// [`Hash`]: ../../std/hash/trait.Hash.html
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
@@ -605,9 +592,6 @@ where
     /// assert_eq!(set.get(&2), Some(&2));
     /// assert_eq!(set.get(&4), None);
     /// ```
-    ///
-    /// [`Eq`]: ../../std/cmp/trait.Eq.html
-    /// [`Hash`]: ../../std/hash/trait.Hash.html
     #[inline]
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
@@ -849,9 +833,6 @@ where
     /// assert_eq!(set.remove(&2), true);
     /// assert_eq!(set.remove(&2), false);
     /// ```
-    ///
-    /// [`Eq`]: ../../std/cmp/trait.Eq.html
-    /// [`Hash`]: ../../std/hash/trait.Hash.html
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
@@ -877,9 +858,6 @@ where
     /// assert_eq!(set.take(&2), Some(2));
     /// assert_eq!(set.take(&2), None);
     /// ```
-    ///
-    /// [`Eq`]: ../../std/cmp/trait.Eq.html
-    /// [`Hash`]: ../../std/hash/trait.Hash.html
     #[inline]
     #[stable(feature = "set_recovery", since = "1.9.0")]
     pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
@@ -1153,8 +1131,7 @@ where
 /// This `struct` is created by the [`iter`] method on [`HashSet`].
 /// See its documentation for more.
 ///
-/// [`HashSet`]: struct.HashSet.html
-/// [`iter`]: struct.HashSet.html#method.iter
+/// [`iter`]: HashSet::iter
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a> {
     iter: Keys<'a, K, ()>,
@@ -1165,8 +1142,7 @@ pub struct Iter<'a, K: 'a> {
 /// This `struct` is created by the [`into_iter`] method on [`HashSet`]
 /// (provided by the `IntoIterator` trait). See its documentation for more.
 ///
-/// [`HashSet`]: struct.HashSet.html
-/// [`into_iter`]: struct.HashSet.html#method.into_iter
+/// [`into_iter`]: IntoIterator::into_iter
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K> {
     iter: map::IntoIter<K, ()>,
@@ -1177,8 +1153,7 @@ pub struct IntoIter<K> {
 /// This `struct` is created by the [`drain`] method on [`HashSet`].
 /// See its documentation for more.
 ///
-/// [`HashSet`]: struct.HashSet.html
-/// [`drain`]: struct.HashSet.html#method.drain
+/// [`drain`]: HashSet::drain
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Drain<'a, K: 'a> {
     iter: map::Drain<'a, K, ()>,
@@ -1189,8 +1164,7 @@ pub struct Drain<'a, K: 'a> {
 /// This `struct` is created by the [`intersection`] method on [`HashSet`].
 /// See its documentation for more.
 ///
-/// [`HashSet`]: struct.HashSet.html
-/// [`intersection`]: struct.HashSet.html#method.intersection
+/// [`intersection`]: HashSet::intersection
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Intersection<'a, T: 'a, S: 'a> {
     // iterator of the first set
@@ -1204,8 +1178,7 @@ pub struct Intersection<'a, T: 'a, S: 'a> {
 /// This `struct` is created by the [`difference`] method on [`HashSet`].
 /// See its documentation for more.
 ///
-/// [`HashSet`]: struct.HashSet.html
-/// [`difference`]: struct.HashSet.html#method.difference
+/// [`difference`]: HashSet::difference
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Difference<'a, T: 'a, S: 'a> {
     // iterator of the first set
@@ -1219,8 +1192,7 @@ pub struct Difference<'a, T: 'a, S: 'a> {
 /// This `struct` is created by the [`symmetric_difference`] method on
 /// [`HashSet`]. See its documentation for more.
 ///
-/// [`HashSet`]: struct.HashSet.html
-/// [`symmetric_difference`]: struct.HashSet.html#method.symmetric_difference
+/// [`symmetric_difference`]: HashSet::symmetric_difference
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
     iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>,
@@ -1231,8 +1203,7 @@ pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
 /// This `struct` is created by the [`union`] method on [`HashSet`].
 /// See its documentation for more.
 ///
-/// [`HashSet`]: struct.HashSet.html
-/// [`union`]: struct.HashSet.html#method.union
+/// [`union`]: HashSet::union
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Union<'a, T: 'a, S: 'a> {
     iter: Chain<Iter<'a, T>, Difference<'a, T, S>>,
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index d5af4f25102..823ce30febe 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -238,25 +238,14 @@
 //! contract. The implementation of many of these functions are subject to change over
 //! time and may call fewer or more syscalls/library functions.
 //!
-//! [`Read`]: trait.Read.html
-//! [`Write`]: trait.Write.html
-//! [`Seek`]: trait.Seek.html
-//! [`BufRead`]: trait.BufRead.html
-//! [`File`]: ../fs/struct.File.html
-//! [`TcpStream`]: ../net/struct.TcpStream.html
-//! [`Vec<T>`]: ../vec/struct.Vec.html
-//! [`BufReader`]: struct.BufReader.html
-//! [`BufWriter`]: struct.BufWriter.html
-//! [`Write::write`]: trait.Write.html#tymethod.write
-//! [`io::stdout`]: fn.stdout.html
-//! [`println!`]: ../macro.println.html
-//! [`Lines`]: struct.Lines.html
-//! [`io::Result`]: type.Result.html
+//! [`File`]: crate::fs::File
+//! [`TcpStream`]: crate::net::TcpStream
+//! [`Vec<T>`]: crate::vec::Vec
+//! [`io::stdout`]: stdout
+//! [`io::Result`]: crate::io::Result
 //! [`?` operator]: ../../book/appendix-02-operators.html
-//! [`Read::read`]: trait.Read.html#tymethod.read
-//! [`Result`]: ../result/enum.Result.html
-//! [`.unwrap()`]: ../result/enum.Result.html#method.unwrap
-// ignore-tidy-filelength
+//! [`Result`]: crate::result::Result
+//! [`.unwrap()`]: crate::result::Result::unwrap
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -491,12 +480,10 @@ where
 /// }
 /// ```
 ///
-/// [`read()`]: trait.Read.html#tymethod.read
-/// [`std::io`]: ../../std/io/index.html
-/// [`File`]: ../fs/struct.File.html
-/// [`BufRead`]: trait.BufRead.html
-/// [`BufReader`]: struct.BufReader.html
-/// [`&str`]: ../../std/primitive.str.html
+/// [`read()`]: Read::read
+/// [`&str`]: str
+/// [`std::io`]: self
+/// [`File`]: crate::fs::File
 /// [slice]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(spotlight)]
@@ -535,7 +522,7 @@ pub trait Read {
     /// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one
     /// obtains via [`MaybeUninit<T>`]) is not safe, and can lead to undefined behavior.
     ///
-    /// [`MaybeUninit<T>`]: ../mem/union.MaybeUninit.html
+    /// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
     ///
     /// # Errors
     ///
@@ -550,10 +537,8 @@ pub trait Read {
     ///
     /// [`File`]s implement `Read`:
     ///
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`Ok(n)`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
-    /// [`File`]: ../fs/struct.File.html
+    /// [`Ok(n)`]: Ok
+    /// [`File`]: crate::fs::File
     ///
     /// ```no_run
     /// use std::io;
@@ -620,9 +605,6 @@ pub trait Read {
     /// This method is unsafe because a `Read`er could otherwise return a
     /// non-zeroing `Initializer` from another `Read` type without an `unsafe`
     /// block.
-    ///
-    /// [`Initializer::nop()`]: ../../std/io/struct.Initializer.html#method.nop
-    /// [`Initializer`]: ../../std/io/struct.Initializer.html
     #[unstable(feature = "read_initializer", issue = "42788")]
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
@@ -652,10 +634,9 @@ pub trait Read {
     ///
     /// [`File`]s implement `Read`:
     ///
-    /// [`read()`]: trait.Read.html#tymethod.read
-    /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
-    /// [`File`]: ../fs/struct.File.html
+    /// [`read()`]: Read::read
+    /// [`Ok(0)`]: Ok
+    /// [`File`]: crate::fs::File
     ///
     /// ```no_run
     /// use std::io;
@@ -675,7 +656,7 @@ pub trait Read {
     /// (See also the [`std::fs::read`] convenience function for reading from a
     /// file.)
     ///
-    /// [`std::fs::read`]: ../fs/fn.read.html
+    /// [`std::fs::read`]: crate::fs::read
     #[stable(feature = "rust1", since = "1.0.0")]
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
         read_to_end(self, buf)
@@ -693,13 +674,13 @@ pub trait Read {
     ///
     /// See [`read_to_end`][readtoend] for other error semantics.
     ///
-    /// [readtoend]: #method.read_to_end
+    /// [readtoend]: Self::read_to_end
     ///
     /// # Examples
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../fs/struct.File.html
+    /// [file]: crate::fs::File
     ///
     /// ```no_run
     /// use std::io;
@@ -718,7 +699,7 @@ pub trait Read {
     /// (See also the [`std::fs::read_to_string`] convenience function for
     /// reading from a file.)
     ///
-    /// [`std::fs::read_to_string`]: ../fs/fn.read_to_string.html
+    /// [`std::fs::read_to_string`]: crate::fs::read_to_string
     #[stable(feature = "rust1", since = "1.0.0")]
     fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
         // Note that we do *not* call `.read_to_end()` here. We are passing
@@ -764,9 +745,7 @@ pub trait Read {
     ///
     /// [`File`]s implement `Read`:
     ///
-    /// [`File`]: ../fs/struct.File.html
-    /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
-    /// [`ErrorKind::UnexpectedEof`]: ../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
+    /// [`File`]: crate::fs::File
     ///
     /// ```no_run
     /// use std::io;
@@ -811,7 +790,7 @@ pub trait Read {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../fs/struct.File.html
+    /// [file]: crate::fs::File
     ///
     /// ```no_run
     /// use std::io;
@@ -855,14 +834,10 @@ pub trait Read {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../fs/struct.File.html
-    /// [`Iterator`]: ../../std/iter/trait.Iterator.html
-    /// [`Result`]: ../../std/result/enum.Result.html
-    /// [`io::Error`]: ../../std/io/struct.Error.html
-    /// [`u8`]: ../../std/primitive.u8.html
-    /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [file]: crate::fs::File
+    /// [`Iterator`]: crate::iter::Iterator
+    /// [`Result`]: crate::result::Result
+    /// [`io::Error`]: self::Error
     ///
     /// ```no_run
     /// use std::io;
@@ -896,7 +871,7 @@ pub trait Read {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../fs/struct.File.html
+    /// [file]: crate::fs::File
     ///
     /// ```no_run
     /// use std::io;
@@ -935,9 +910,9 @@ pub trait Read {
     ///
     /// [`File`]s implement `Read`:
     ///
-    /// [`File`]: ../fs/struct.File.html
-    /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`read()`]: trait.Read.html#tymethod.read
+    /// [`File`]: crate::fs::File
+    /// [`Ok(0)`]: Ok
+    /// [`read()`]: Read::read
     ///
     /// ```no_run
     /// use std::io;
@@ -1233,8 +1208,8 @@ impl Initializer {
 /// throughout [`std::io`] take and provide types which implement the `Write`
 /// trait.
 ///
-/// [`write`]: #tymethod.write
-/// [`flush`]: #tymethod.flush
+/// [`write`]: Self::write
+/// [`flush`]: Self::flush
 /// [`std::io`]: index.html
 ///
 /// # Examples
@@ -1260,7 +1235,7 @@ impl Initializer {
 /// The trait also provides convenience methods like [`write_all`], which calls
 /// `write` in a loop until its entire input has been written.
 ///
-/// [`write_all`]: #method.write_all
+/// [`write_all`]: Self::write_all
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(spotlight)]
 pub trait Write {
@@ -1292,10 +1267,6 @@ pub trait Write {
     /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the
     /// write operation should be retried if there is nothing else to do.
     ///
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`Ok(n)`]:  ../../std/result/enum.Result.html#variant.Ok
-    /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
-    ///
     /// # Examples
     ///
     /// ```no_run
@@ -1381,8 +1352,7 @@ pub trait Write {
     /// This function will return the first error of
     /// non-[`ErrorKind::Interrupted`] kind that [`write`] returns.
     ///
-    /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
-    /// [`write`]: #tymethod.write
+    /// [`write`]: Self::write
     ///
     /// # Examples
     ///
@@ -1423,8 +1393,7 @@ pub trait Write {
     ///
     /// If the buffer contains no data, this will never call [`write_vectored`].
     ///
-    /// [`write_vectored`]: #method.write_vectored
-    /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+    /// [`write_vectored`]: Self::write_vectored
     ///
     /// # Notes
     ///
@@ -1480,19 +1449,16 @@ pub trait Write {
     /// encountered.
     ///
     /// This method is primarily used to interface with the
-    /// [`format_args!`][formatargs] macro, but it is rare that this should
-    /// explicitly be called. The [`write!`][write] macro should be favored to
+    /// [`format_args!()`] macro, but it is rare that this should
+    /// explicitly be called. The [`write!()`] macro should be favored to
     /// invoke this method instead.
     ///
-    /// [formatargs]: ../macro.format_args.html
-    /// [write]: ../macro.write.html
-    ///
     /// This function internally uses the [`write_all`][writeall] method on
     /// this trait and hence will continuously write data so long as no errors
     /// are received. This also means that partial writes are not indicated in
     /// this signature.
     ///
-    /// [writeall]: #method.write_all
+    /// [writeall]: Self::write_all
     ///
     /// # Errors
     ///
@@ -1589,7 +1555,7 @@ pub trait Write {
 ///
 /// [`File`][file]s implement `Seek`:
 ///
-/// [file]: ../fs/struct.File.html
+/// [file]: crate::fs::File
 ///
 /// ```no_run
 /// use std::io;
@@ -1789,9 +1755,9 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> R
 /// [`BufReader`] to the rescue!
 ///
 /// [`BufReader`]: struct.BufReader.html
-/// [`File`]: ../fs/struct.File.html
-/// [`read_line`]: #method.read_line
-/// [`lines`]: #method.lines
+/// [`File`]: crate::fs::File
+/// [`read_line`]: Self::read_line
+/// [`lines`]: Self::lines
 /// [`Read`]: trait.Read.html
 ///
 /// ```no_run
@@ -1823,7 +1789,7 @@ pub trait BufRead: Read {
     /// be called with the number of bytes that are consumed from this buffer to
     /// ensure that the bytes are never returned twice.
     ///
-    /// [`consume`]: #tymethod.consume
+    /// [`consume`]: Self::consume
     ///
     /// An empty buffer returned indicates that the stream has reached EOF.
     ///
@@ -1873,7 +1839,7 @@ pub trait BufRead: Read {
     /// Since `consume()` is meant to be used with [`fill_buf`],
     /// that method's example includes an example of `consume()`.
     ///
-    /// [`fill_buf`]: #tymethod.fill_buf
+    /// [`fill_buf`]: Self::fill_buf
     #[stable(feature = "rust1", since = "1.0.0")]
     fn consume(&mut self, amt: usize);
 
@@ -1897,7 +1863,7 @@ pub trait BufRead: Read {
     /// If an I/O error is encountered then all bytes read so far will be
     /// present in `buf` and its length will have been adjusted appropriately.
     ///
-    /// [`fill_buf`]: #tymethod.fill_buf
+    /// [`fill_buf`]: Self::fill_buf
     /// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted
     ///
     /// # Examples
@@ -1962,7 +1928,7 @@ pub trait BufRead: Read {
     /// error is encountered then `buf` may contain some bytes already read in
     /// the event that all data read so far was valid UTF-8.
     ///
-    /// [`read_until`]: #method.read_until
+    /// [`read_until`]: Self::read_until
     ///
     /// # Examples
     ///
@@ -2015,9 +1981,9 @@ pub trait BufRead: Read {
     /// This function will yield errors whenever [`read_until`] would have
     /// also yielded an error.
     ///
-    /// [`io::Result`]: type.Result.html
-    /// [`Vec<u8>`]: ../vec/struct.Vec.html
-    /// [`read_until`]: #method.read_until
+    /// [`io::Result`]: self::Result
+    /// [`Vec<u8>`]: crate::vec::Vec
+    /// [`read_until`]: Self::read_until
     ///
     /// # Examples
     ///
@@ -2052,8 +2018,7 @@ pub trait BufRead: Read {
     /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
     /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
     ///
-    /// [`io::Result`]: type.Result.html
-    /// [`String`]: ../string/struct.String.html
+    /// [`io::Result`]: self::Result
     ///
     /// # Examples
     ///
@@ -2061,8 +2026,6 @@ pub trait BufRead: Read {
     /// this example, we use [`Cursor`] to iterate over all the lines in a byte
     /// slice.
     ///
-    /// [`Cursor`]: struct.Cursor.html
-    ///
     /// ```
     /// use std::io::{self, BufRead};
     ///
@@ -2253,8 +2216,6 @@ impl<T> Take<T> {
     /// This instance may reach `EOF` after reading fewer bytes than indicated by
     /// this method if the underlying [`Read`] instance reaches EOF.
     ///
-    /// [`Read`]: ../../std/io/trait.Read.html
-    ///
     /// # Examples
     ///
     /// ```no_run
diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs
index 371291b9f76..0f349dfa302 100644
--- a/src/libstd/sys/unix/process/process_unix.rs
+++ b/src/libstd/sys/unix/process/process_unix.rs
@@ -84,12 +84,12 @@ impl Command {
                 Ok(0) => return Ok((p, ours)),
                 Ok(8) => {
                     let (errno, footer) = bytes.split_at(4);
-                    assert!(
-                        combine(CLOEXEC_MSG_FOOTER) == combine(footer.try_into().unwrap()),
+                    assert_eq!(
+                        CLOEXEC_MSG_FOOTER, footer,
                         "Validation on the CLOEXEC pipe failed: {:?}",
                         bytes
                     );
-                    let errno = combine(errno.try_into().unwrap());
+                    let errno = i32::from_be_bytes(errno.try_into().unwrap());
                     assert!(p.wait().is_ok(), "wait() should either return Ok or panic");
                     return Err(Error::from_raw_os_error(errno));
                 }
@@ -105,10 +105,6 @@ impl Command {
                 }
             }
         }
-
-        fn combine(arr: [u8; 4]) -> i32 {
-            i32::from_be_bytes(arr)
-        }
     }
 
     pub fn exec(&mut self, default: Stdio) -> io::Error {