diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 7756a6f71dbd6..56a24168e28d9 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -962,59 +962,127 @@ 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`], but
+    /// with the argument order swapped.
+    ///
+    /// [`copy`]: ./fn.copy.html
+    /// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/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.
+    /// Behavior is undefined if any of the following conditions are violated:
+    ///
+    /// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
+    ///
+    /// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
+    ///
+    /// * Both `src` and `dst` must be properly aligned.
+    ///
+    /// * The region of memory beginning at `src` with a size of `count *
+    ///   size_of::<T>()` bytes must *not* overlap with the region of memory
+    ///   beginning at `dst` with the same size.
+    ///
+    /// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
+    /// whether `T` is [`Copy`].  If `T` is not [`Copy`], using *both* the values
+    /// in the region beginning at `*src` and the region beginning at `*dst` can
+    /// [violate memory safety][read-ownership].
+    ///
+    /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
+    /// `0`, the pointers must be non-NULL and properly aligned.
+    ///
+    /// [`Copy`]: ../marker/trait.Copy.html
+    /// [`read`]: ../ptr/fn.read.html
+    /// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
+    /// [valid]: ../ptr/index.html#safety
     ///
     /// # 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) {
-    ///     unsafe {
-    ///         // Give ourselves some scratch space to work with
-    ///         let mut t: T = mem::uninitialized();
+    /// /// 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();
     ///
-    ///         // 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);
+    ///     // Ensure that `dst` has enough capacity to hold all of `src`.
+    ///     dst.reserve(src_len);
     ///
-    ///         // 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);
+    ///     unsafe {
+    ///         // The call to offset is always safe because `Vec` will never
+    ///         // allocate more than `isize::MAX` bytes.
+    ///         let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize);
+    ///         let src_ptr = src.as_ptr();
+    ///
+    ///         // Truncate `src` without dropping its contents. We do this first,
+    ///         // to avoid problems in case something further down panics.
+    ///         src.set_len(0);
+    ///
+    ///         // The two regions cannot overlap becuase mutable references do
+    ///         // not alias, and two different vectors cannot own the same
+    ///         // memory.
+    ///         ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);
+    ///
+    ///         // 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`]: ../../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);
 
-    /// 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`], but with the argument
+    /// order swapped.  Copying takes place as if the bytes were copied from `src`
+    /// to a temporary array and then copied from the array to `dst`.
+    ///
+    /// [`copy_nonoverlapping`]: ./fn.copy_nonoverlapping.html
+    /// [`memmove`]: https://en.cppreference.com/w/c/string/byte/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.
+    /// Behavior is undefined if any of the following conditions are violated:
+    ///
+    /// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
+    ///
+    /// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
+    ///
+    /// * Both `src` and `dst` must be properly aligned.
+    ///
+    /// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of
+    /// whether `T` is [`Copy`].  If `T` is not [`Copy`], using both the values
+    /// in the region beginning at `*src` and the region beginning at `*dst` can
+    /// [violate memory safety][read-ownership].
+    ///
+    /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
+    /// `0`, the pointers must be non-NULL and properly aligned.
+    ///
+    /// [`Copy`]: ../marker/trait.Copy.html
+    /// [`read`]: ../ptr/fn.read.html
+    /// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
+    /// [valid]: ../ptr/index.html#safety
     ///
     /// # Examples
     ///
@@ -1031,24 +1099,80 @@ 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 similar to C's [`memset`], but sets `count *
+    /// size_of::<T>()` bytes to `val`.
+    ///
+    /// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset
+    ///
+    /// # Safety
+    ///
+    /// Behavior is undefined if any of the following conditions are violated:
+    ///
+    /// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
+    ///
+    /// * `dst` must be properly aligned.
+    ///
+    /// Additionally, the caller must ensure that writing `count *
+    /// size_of::<T>()` bytes to the given region of memory results in a valid
+    /// value of `T`. Using a region of memory typed as a `T` that contains an
+    /// invalid value of `T` is undefined behavior.
+    ///
+    /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
+    /// `0`, the pointer must be non-NULL and properly aligned.
+    ///
+    /// [valid]: ../ptr/index.html#safety
     ///
     /// # Examples
     ///
+    /// Basic usage:
+    ///
     /// ```
     /// use std::ptr;
     ///
-    /// let mut vec = vec![0; 4];
+    /// let mut vec = vec![0u32; 4];
     /// unsafe {
     ///     let vec_ptr = vec.as_mut_ptr();
-    ///     ptr::write_bytes(vec_ptr, b'a', 2);
+    ///     ptr::write_bytes(vec_ptr, 0xfe, 2);
+    /// }
+    /// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]);
+    /// ```
+    ///
+    /// Creating an invalid value:
+    ///
+    /// ```
+    /// use std::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 as *mut Box<i32>, 0, 1);
     /// }
-    /// assert_eq!(vec, [b'a', b'a', 0, 0]);
+    ///
+    /// // At this point, using or dropping `v` results in undefined behavior.
+    /// // drop(v); // ERROR
+    ///
+    /// // Even leaking `v` "uses" it, and hence is undefined behavior.
+    /// // mem::forget(v); // ERROR
+    ///
+    /// // In fact, `v` is invalid according to basic type layout invariants, so *any*
+    /// // operation touching it is undefined behavior.
+    /// // let v2 = v; // ERROR
+    ///
+    /// unsafe {
+    ///     // Let us instead put in a valid value
+    ///     ptr::write(&mut v as *mut Box<i32>, Box::new(42i32));
+    /// }
+    ///
+    /// // Now the box is fine
+    /// assert_eq!(*v, 42);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
@@ -1066,7 +1190,7 @@ extern "rust-intrinsic" {
     /// `min_align_of::<T>()`
     ///
     /// The volatile parameter is set to `true`, so it will not be optimized out
-    /// unless size is equal to zero..
+    /// unless size is equal to zero.
     pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize);
     /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
     /// size of `count` * `size_of::<T>()` and an alignment of
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 57351822cc3cf..14f2148a64e0e 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -8,11 +8,68 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// FIXME: talk about offset, copy_memory, copy_nonoverlapping_memory
-
-//! Raw, unsafe pointers, `*const T`, and `*mut T`.
+//! Manually manage memory through raw pointers.
 //!
 //! *[See also the pointer primitive types](../../std/primitive.pointer.html).*
+//!
+//! # Safety
+//!
+//! Many functions in this module take raw pointers as arguments and read from
+//! or write to them. For this to be safe, these pointers must be *valid*.
+//! Whether a pointer is valid depends on the operation it is used for
+//! (read or write), and the extent of the memory that is accessed (i.e.,
+//! how many bytes are read/written). Most functions use `*mut T` and `*const T`
+//! to access only a single value, in which case the documentation omits the size
+//! and implicitly assumes it to be `size_of::<T>()` bytes.
+//!
+//! The precise rules for validity are not determined yet.  The guarantees that are
+//! provided at this point are very minimal:
+//!
+//! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst].
+//! * All pointers (except for the null pointer) are valid for all operations of
+//!   [size zero][zst].
+//! * All accesses performed by functions in this module are *non-atomic* in the sense
+//!   of [atomic operations] used to synchronize between threads. This means it is
+//!   undefined behavior to perform two concurrent accesses to the same location from different
+//!   threads unless both accesses only read from memory. Notice that this explicitly
+//!   includes [`read_volatile`] and [`write_volatile`]: Volatile accesses cannot
+//!   be used for inter-thread synchronization.
+//! * The result of casting a reference to a pointer is valid for as long as the
+//!   underlying object is live and no reference (just raw pointers) is used to
+//!   access the same memory.
+//!
+//! These axioms, along with careful use of [`offset`] for pointer arithmentic,
+//! are enough to correctly implement many useful things in unsafe code. Stronger guarantees
+//! will be provided eventually, as the [aliasing] rules are being determined. For more
+//! information, see the [book] as well as the section in the reference devoted
+//! to [undefined behavior][ub].
+//!
+//! ## Alignment
+//!
+//! Valid raw pointers as defined above are not necessarily properly aligned (where
+//! "proper" alignment is defined by the pointee type, i.e., `*const T` must be
+//! aligned to `mem::align_of::<T>()`). However, most functions require their
+//! arguments to be properly aligned, and will explicitly state
+//! this requirement in their documentation. Notable exceptions to this are
+//! [`read_unaligned`] and [`write_unaligned`].
+//!
+//! When a function requires proper alignment, it does so even if the access
+//! has size 0, i.e., even if memory is not actually touched. Consider using
+//! [`NonNull::dangling`] in such cases.
+//!
+//! [aliasing]: ../../nomicon/aliasing.html
+//! [book]: ../../book/second-edition/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer
+//! [ub]: ../../reference/behavior-considered-undefined.html
+//! [null]: ./fn.null.html
+//! [zst]: ../../nomicon/exotic-sizes.html#zero-sized-types-zsts
+//! [atomic operations]: ../../std/sync/atomic/index.html
+//! [`copy`]: ../../std/ptr/fn.copy.html
+//! [`offset`]: ../../std/primitive.pointer.html#method.offset
+//! [`read_unaligned`]: ./fn.read_unaligned.html
+//! [`write_unaligned`]: ./fn.write_unaligned.html
+//! [`read_volatile`]: ./fn.read_volatile.html
+//! [`write_volatile`]: ./fn.write_volatile.html
+//! [`NonNull::dangling`]: ./struct.NonNull.html#method.dangling
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -38,21 +95,99 @@ 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`]: ../ptr/fn.read.html
+///
 /// # Safety
 ///
-/// This has all the same safety problems as `ptr::read` with respect to
-/// invalid pointers, types, and double drops.
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `to_drop` must be [valid] for reads.
+///
+/// * `to_drop` must be properly aligned.  See the example below for how to drop
+///   an unaligned pointer.
+///
+/// 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.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
+/// [`Copy`]: ../marker/trait.Copy.html
+/// [`write`]: ../ptr/fn.write.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 {
+///     // Get a raw pointer to the last element in `v`.
+///     let ptr = &mut v[1] as *mut _;
+///     // Shorten `v` to prevent the last item from being dropped.  We do that first,
+///     // to prevent issues if the `drop_in_place` below panics.
+///     v.set_len(1);
+///     // 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(ptr);
+/// }
+///
+/// assert_eq!(v, &[0.into()]);
+///
+/// // Ensure that the last item was dropped.
+/// assert!(weak.upgrade().is_none());
+/// ```
+///
+/// Unaligned values cannot be dropped in place, they must be copied to an aligned
+/// location first:
+/// ```
+/// use std::ptr;
+/// use std::mem;
+///
+/// unsafe fn drop_after_copy<T>(to_drop: *mut T) {
+///     let mut copy: T = mem::uninitialized();
+///     ptr::copy(to_drop, &mut copy, 1);
+///     drop(copy);
+/// }
+///
+/// #[repr(packed, C)]
+/// struct Packed {
+///     _padding: u8,
+///     unaligned: Vec<i32>,
+/// }
+///
+/// let mut p = Packed { _padding: 0, unaligned: vec![42] };
+/// unsafe {
+///     drop_after_copy(&mut p.unaligned as *mut _);
+///     mem::forget(p);
+/// }
+/// ```
+///
+/// Notice that the compiler performs this copy automatically when dropping packed structs,
+/// i.e., you do not usually have to worry about such issues unless you call `drop_in_place`
+/// manually.
 #[stable(feature = "drop_in_place", since = "1.8.0")]
 #[lang = "drop_in_place"]
 #[allow(unconditional_recursion)]
@@ -93,17 +228,29 @@ 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 second example below.
+///
+/// [`mem::swap`]: ../mem/fn.swap.html
 ///
 /// # Safety
 ///
-/// This function copies the memory through the raw pointers passed to it
-/// as arguments.
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * Both `x` and `y` must be [valid] for reads and writes.
+///
+/// * Both `x` and `y` must be properly aligned.
 ///
-/// Ensure that these pointers are valid before calling `swap`.
+/// Note that even if `T` has size `0`, the pointers must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
 ///
 /// # Examples
 ///
@@ -114,8 +261,8 @@ pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
 ///
 /// let mut array = [0, 1, 2, 3];
 ///
-/// let x = array[0..].as_mut_ptr() as *mut [u32; 2];
-/// let y = array[2..].as_mut_ptr() as *mut [u32; 2];
+/// let x = array[0..].as_mut_ptr() as *mut [u32; 2]; // this is `array[0..2]`
+/// let y = array[2..].as_mut_ptr() as *mut [u32; 2]; // this is `array[2..4]`
 ///
 /// unsafe {
 ///     ptr::swap(x, y);
@@ -130,11 +277,16 @@ pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
 ///
 /// let mut array = [0, 1, 2, 3];
 ///
-/// let x = array[0..].as_mut_ptr() as *mut [u32; 3];
-/// let y = array[1..].as_mut_ptr() as *mut [u32; 3];
+/// let x = array[0..].as_mut_ptr() as *mut [u32; 3]; // this is `array[0..3]`
+/// let y = array[1..].as_mut_ptr() as *mut [u32; 3]; // this is `array[1..4]`
 ///
 /// unsafe {
 ///     ptr::swap(x, y);
+///     // The indices `1..3` of the slice overlap between `x` and `y`.
+///     // Reasonable results would be for to them be `[2, 3]`, so that indices `0..3` are
+///     // `[1, 2, 3]` (matching `y` before the `swap`); or for them to be `[0, 1]`
+///     // so that indices `1..4` are `[0, 1, 2]` (matching `x` before the `swap`).
+///     // This implementation is defined to make the latter choice.
 ///     assert_eq!([1, 0, 1, 2], array);
 /// }
 /// ```
@@ -154,12 +306,26 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
     mem::forget(tmp);
 }
 
-/// Swaps a sequence of values at two mutable locations of the same type.
+/// Swaps `count * size_of::<T>()` bytes between the two regions of memory
+/// beginning at `x` and `y`. The two regions must *not* overlap.
 ///
 /// # Safety
 ///
-/// The two arguments must each point to the beginning of `count` locations
-/// of valid memory, and the two memory ranges must not overlap.
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * Both `x` and `y` must be [valid] for reads and writes of `count *
+///   size_of::<T>()` bytes.
+///
+/// * Both `x` and `y` must be properly aligned.
+///
+/// * The region of memory beginning at `x` with a size of `count *
+///   size_of::<T>()` bytes must *not* overlap with the region of memory
+///   beginning at `y` with the same size.
+///
+/// Note that even if the effectively copied size (`count * size_of::<T>()`) is `0`,
+/// the pointers must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
 ///
 /// # Examples
 ///
@@ -252,18 +418,48 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
     }
 }
 
-/// Moves `src` into the pointed `dest`, returning the previous `dest` value.
+/// Moves `src` into the pointed `dst`, returning the previous `dst` value.
 ///
 /// Neither value is dropped.
 ///
+/// 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.
+///
+/// [`mem::replace`]: ../mem/fn.replace.html
+///
 /// # Safety
 ///
-/// This is only unsafe because it accepts a raw pointer.
-/// Otherwise, this operation is identical to `mem::replace`.
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `dst` must be [valid] for writes.
+///
+/// * `dst` must be properly aligned.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
+///
+/// # 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 rust[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 {
-    mem::swap(&mut *dest, &mut src); // cannot overlap
+pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
+    mem::swap(&mut *dst, &mut src); // cannot overlap
     src
 }
 
@@ -272,14 +468,14 @@ 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`.
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads.
+///
+/// * `src` must be properly aligned. Use [`read_unaligned`] if this is not the
+///   case.
 ///
-/// The pointer must be aligned; use `read_unaligned` if that is not the case.
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
 ///
 /// # Examples
 ///
@@ -293,6 +489,87 @@ 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);
+///
+///         // `tmp` has been moved (`write` takes ownership of its second argument),
+///         // so nothing is dropped implicitly here.
+///     }
+/// }
+///
+/// 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");
+/// ```
+///
+/// ## Ownership of the Returned Value
+///
+/// `read` creates a bitwise copy of `T`, regardless of whether `T` is [`Copy`].
+/// If `T` is not [`Copy`], using both the returned value and the value at
+/// `*src` can violate memory safety.  Note that assigning to `*src` counts as a
+/// use because it will attempt to drop the value at `*src`.
+///
+/// [`write`] can be used to overwrite data without causing it to be dropped.
+///
+/// ```
+/// use std::ptr;
+///
+/// let mut s = String::from("foo");
+/// unsafe {
+///     // `s2` now points to the same underlying memory as `s`.
+///     let mut s2: String = ptr::read(&s);
+///
+///     assert_eq!(s2, "foo");
+///
+///     // Assigning to `s2` causes its original value to be dropped. Beyond
+///     // this point, `s` must no longer be used, as the underlying memory has
+///     // been freed.
+///     s2 = String::default();
+///     assert_eq!(s2, "");
+///
+///     // Assigning to `s` would cause the old value to be dropped again,
+///     // resulting in undefined behavior.
+///     // s = String::from("bar"); // ERROR
+///
+///     // `ptr::write` can be used to overwrite a value without dropping it.
+///     ptr::write(&mut s, String::from("bar"));
+/// }
+///
+/// assert_eq!(s, "bar");
+/// ```
+///
+/// [`mem::swap`]: ../mem/fn.swap.html
+/// [valid]: ../ptr/index.html#safety
+/// [`Copy`]: ../marker/trait.Copy.html
+/// [`read_unaligned`]: ./fn.read_unaligned.html
+/// [`write`]: ./fn.write.html
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn read<T>(src: *const T) -> T {
@@ -304,28 +581,61 @@ 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
 ///
-/// 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`.
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads.
+///
+/// Like [`read`], `read_unaligned` creates a bitwise copy of `T`, regardless of
+/// whether `T` is [`Copy`].  If `T` is not [`Copy`], using both the returned
+/// value and the value at `*src` can [violate memory safety][read-ownership].
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [`Copy`]: ../marker/trait.Copy.html
+/// [`read`]: ./fn.read.html
+/// [`write_unaligned`]: ./fn.write_unaligned.html
+/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
+/// [valid]: ../ptr/index.html#safety
 ///
 /// # 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)]
+/// struct Packed {
+///     _padding: u8,
+///     unaligned: u32,
 /// }
+///
+/// let x = Packed {
+///     _padding: 0x00,
+///     unaligned: 0x01020304,
+/// };
+///
+/// let v = unsafe {
+///     // Take the address of a 32-bit integer which is not aligned.
+///     // This must be done as a raw pointer; unaligned references are invalid.
+///     let unaligned = &x.unaligned as *const u32;
+///
+///     // Dereferencing normally will emit an aligned 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")]
@@ -340,21 +650,31 @@ 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
-/// allocations or resources, so care must be taken not to overwrite an object
+/// `write` does not drop the contents of `dst`. This is safe, but it could leak
+/// allocations or resources, so care should 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.
+///
+/// [`read`]: ./fn.read.html
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
 ///
-/// The pointer must be aligned; use `write_unaligned` if that is not the case.
+/// * `dst` must be [valid] for writes.
+///
+/// * `dst` must be properly aligned. Use [`write_unaligned`] if this is not the
+///   case.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
+/// [`write_unaligned`]: ./fn.write_unaligned.html
 ///
 /// # Examples
 ///
@@ -370,6 +690,47 @@ 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 {
+///         // 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);
+///
+///         // `tmp` has been moved (`write` takes ownership of its second argument),
+///         // so nothing is dropped implicitly here.
+///     }
+/// }
+///
+/// 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) {
@@ -379,35 +740,62 @@ 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.
-///
-/// # Safety
-///
-/// This operation is marked unsafe because it accepts a raw pointer.
+/// Unlike [`write`], the pointer may be unaligned.
 ///
-/// 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 should 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 with [`read_unaligned`].
+///
+/// [`write`]: ./fn.write.html
+/// [`read_unaligned`]: ./fn.read_unaligned.html
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `dst` must be [valid] for writes.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
 ///
 /// # 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 as *mut u32;
+///
+///     // Dereferencing normally will emit an aligned store instruction,
+///     // causing undefined behavior because the pointer is not aligned.
+///     // *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")]
@@ -425,6 +813,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 accessed with `read_volatile` or [`write_volatile`] should not be
+/// accessed with non-volatile operations.
+///
+/// [`write_volatile`]: ./fn.write_volatile.html
+///
 /// # Notes
 ///
 /// Rust does not currently have a rigorously and formally defined memory model,
@@ -441,12 +834,23 @@ 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`.
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads.
+///
+/// * `src` must be properly aligned.
+///
+/// Like [`read`], `read_unaligned` creates a bitwise copy of `T`, regardless of
+/// whether `T` is [`Copy`].  If `T` is not [`Copy`], using both the returned
+/// value and the value at `*src` can [violate memory safety][read-ownership].
+/// However, storing non-[`Copy`] types in volatile memory is almost certainly
+/// incorrect.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
+/// [`Copy`]: ../marker/trait.Copy.html
+/// [`read`]: ./fn.read.html
 ///
 /// Just like in C, whether an operation is volatile has no bearing whatsoever
 /// on questions involving concurrent access from multiple threads. Volatile
@@ -479,6 +883,18 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 /// to not be elided or reordered by the compiler across other volatile
 /// operations.
 ///
+/// Memory accessed with [`read_volatile`] or `write_volatile` should not be
+/// accessed with non-volatile operations.
+///
+/// `write_volatile` does not drop the contents of `dst`. This is safe, but it
+/// could leak allocations or resources, so care should 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`.
+///
+/// [`read_volatile`]: ./fn.read_volatile.html
+///
 /// # Notes
 ///
 /// Rust does not currently have a rigorously and formally defined memory model,
@@ -495,14 +911,15 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 ///
 /// # Safety
 ///
-/// This operation is marked unsafe because it accepts a raw pointer.
+/// Behavior is undefined if any of the following conditions are violated:
 ///
-/// 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.
+/// * `dst` must be [valid] for writes.
 ///
-/// This is appropriate for initializing uninitialized memory, or overwriting
-/// memory that has previously been `read` from.
+/// * `dst` must be properly aligned.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
 ///
 /// Just like in C, whether an operation is volatile has no bearing whatsoever
 /// on questions involving concurrent access from multiple threads. Volatile
@@ -1023,29 +1440,9 @@ impl<T: ?Sized> *const T {
     /// Reads the value from `self` without moving it. This leaves the
     /// memory in `self` unchanged.
     ///
-    /// # Safety
+    /// See [`ptr::read`] for safety concerns and examples.
     ///
-    /// Beyond accepting a raw pointer, this is unsafe because it semantically
-    /// moves the value out of `self` without preventing further usage of `self`.
-    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
-    /// `self` is not used before the data is overwritten again (e.g. with `write`,
-    /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use
-    /// because it will attempt to drop the value previously at `*self`.
-    ///
-    /// The pointer must be aligned; use `read_unaligned` if that is not the case.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let x = 12;
-    /// let y = &x as *const i32;
-    ///
-    /// unsafe {
-    ///     assert_eq!(y.read(), 12);
-    /// }
-    /// ```
+    /// [`ptr::read`]: ./ptr/fn.read.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read(self) -> T
@@ -1061,47 +1458,9 @@ impl<T: ?Sized> *const T {
     /// to not be elided or reordered by the compiler across other volatile
     /// operations.
     ///
-    /// # Notes
-    ///
-    /// Rust does not currently have a rigorously and formally defined memory model,
-    /// so the precise semantics of what "volatile" means here is subject to change
-    /// over time. That being said, the semantics will almost always end up pretty
-    /// similar to [C11's definition of volatile][c11].
-    ///
-    /// The compiler shouldn't change the relative order or number of volatile
-    /// memory operations. However, volatile memory operations on zero-sized types
-    /// (e.g. if a zero-sized type is passed to `read_volatile`) are no-ops
-    /// and may be ignored.
-    ///
-    /// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
-    ///
-    /// # Safety
-    ///
-    /// Beyond accepting a raw pointer, this is unsafe because it semantically
-    /// moves the value out of `self` without preventing further usage of `self`.
-    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
-    /// `self` is not used before the data is overwritten again (e.g. with `write`,
-    /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use
-    /// because it will attempt to drop the value previously at `*self`.
+    /// See [`ptr::read_volatile`] for safety concerns and examples.
     ///
-    /// Just like in C, whether an operation is volatile has no bearing whatsoever
-    /// on questions involving concurrent access from multiple threads. Volatile
-    /// accesses behave exactly like non-atomic accesses in that regard. In particular,
-    /// a race between a `read_volatile` and any write operation to the same location
-    /// is undefined behavior.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let x = 12;
-    /// let y = &x as *const i32;
-    ///
-    /// unsafe {
-    ///     assert_eq!(y.read_volatile(), 12);
-    /// }
-    /// ```
+    /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_volatile(self) -> T
@@ -1115,27 +1474,9 @@ impl<T: ?Sized> *const T {
     ///
     /// Unlike `read`, the pointer may be unaligned.
     ///
-    /// # Safety
-    ///
-    /// Beyond accepting a raw pointer, this is unsafe because it semantically
-    /// moves the value out of `self` without preventing further usage of `self`.
-    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
-    /// `self` is not used before the data is overwritten again (e.g. with `write`,
-    /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use
-    /// because it will attempt to drop the value previously at `*self`.
+    /// See [`ptr::read_unaligned`] for safety concerns and examples.
     ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let x = 12;
-    /// let y = &x as *const i32;
-    ///
-    /// unsafe {
-    ///     assert_eq!(y.read_unaligned(), 12);
-    /// }
-    /// ```
+    /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_unaligned(self) -> T
@@ -1147,30 +1488,11 @@ impl<T: ?Sized> *const T {
     /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
     /// and destination may overlap.
     ///
-    /// NOTE: this has the *same* argument order as `ptr::copy`.
-    ///
-    /// This is semantically equivalent to C's `memmove`.
-    ///
-    /// # Safety
+    /// NOTE: this has the *same* argument order as [`ptr::copy`].
     ///
-    /// Care must be taken with the ownership of `self` and `dest`.
-    /// This method semantically moves the values of `self` into `dest`.
-    /// However it does not drop the contents of `dest`, or prevent the contents
-    /// of `self` from being dropped or used.
+    /// See [`ptr::copy`] for safety concerns and examples.
     ///
-    /// # Examples
-    ///
-    /// Efficiently create a Rust vector from an unsafe buffer:
-    ///
-    /// ```
-    /// # #[allow(dead_code)]
-    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
-    ///     let mut dst = Vec::with_capacity(elts);
-    ///     dst.set_len(elts);
-    ///     ptr.copy_to(dst.as_mut_ptr(), elts);
-    ///     dst
-    /// }
-    /// ```
+    /// [`ptr::copy`]: ./ptr/fn.copy.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to(self, dest: *mut T, count: usize)
@@ -1182,32 +1504,11 @@ impl<T: ?Sized> *const T {
     /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
     /// and destination may *not* overlap.
     ///
-    /// NOTE: this has the *same* argument order as `ptr::copy_nonoverlapping`.
+    /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`].
     ///
-    /// `copy_nonoverlapping` is semantically equivalent to C's `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 `self` and
-    /// `self`. This method semantically moves the values of `self` into `dest`.
-    /// However it does not drop the contents of `dest`, or prevent the contents
-    /// of `self` from being dropped or used.
-    ///
-    /// # Examples
+    /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
     ///
-    /// Efficiently create a Rust vector from an unsafe buffer:
-    ///
-    /// ```
-    /// # #[allow(dead_code)]
-    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
-    ///     let mut dst = Vec::with_capacity(elts);
-    ///     dst.set_len(elts);
-    ///     ptr.copy_to_nonoverlapping(dst.as_mut_ptr(), elts);
-    ///     dst
-    /// }
-    /// ```
+    /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
@@ -1777,29 +2078,9 @@ impl<T: ?Sized> *mut T {
     /// Reads the value from `self` without moving it. This leaves the
     /// memory in `self` unchanged.
     ///
-    /// # Safety
-    ///
-    /// Beyond accepting a raw pointer, this is unsafe because it semantically
-    /// moves the value out of `self` without preventing further usage of `self`.
-    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
-    /// `self` is not used before the data is overwritten again (e.g. with `write`,
-    /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use
-    /// because it will attempt to drop the value previously at `*self`.
+    /// See [`ptr::read`] for safety concerns and examples.
     ///
-    /// The pointer must be aligned; use `read_unaligned` if that is not the case.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let x = 12;
-    /// let y = &x as *const i32;
-    ///
-    /// unsafe {
-    ///     assert_eq!(y.read(), 12);
-    /// }
-    /// ```
+    /// [`ptr::read`]: ./ptr/fn.read.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read(self) -> T
@@ -1815,47 +2096,9 @@ impl<T: ?Sized> *mut T {
     /// to not be elided or reordered by the compiler across other volatile
     /// operations.
     ///
-    /// # Notes
-    ///
-    /// Rust does not currently have a rigorously and formally defined memory model,
-    /// so the precise semantics of what "volatile" means here is subject to change
-    /// over time. That being said, the semantics will almost always end up pretty
-    /// similar to [C11's definition of volatile][c11].
-    ///
-    /// The compiler shouldn't change the relative order or number of volatile
-    /// memory operations. However, volatile memory operations on zero-sized types
-    /// (e.g. if a zero-sized type is passed to `read_volatile`) are no-ops
-    /// and may be ignored.
-    ///
-    /// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
-    ///
-    /// # Safety
-    ///
-    /// Beyond accepting a raw pointer, this is unsafe because it semantically
-    /// moves the value out of `self` without preventing further usage of `self`.
-    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
-    /// `self` is not used before the data is overwritten again (e.g. with `write`,
-    /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use
-    /// because it will attempt to drop the value previously at `*self`.
-    ///
-    /// Just like in C, whether an operation is volatile has no bearing whatsoever
-    /// on questions involving concurrent access from multiple threads. Volatile
-    /// accesses behave exactly like non-atomic accesses in that regard. In particular,
-    /// a race between a `read_volatile` and any write operation to the same location
-    /// is undefined behavior.
+    /// See [`ptr::read_volatile`] for safety concerns and examples.
     ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let x = 12;
-    /// let y = &x as *const i32;
-    ///
-    /// unsafe {
-    ///     assert_eq!(y.read_volatile(), 12);
-    /// }
-    /// ```
+    /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_volatile(self) -> T
@@ -1869,27 +2112,9 @@ impl<T: ?Sized> *mut T {
     ///
     /// Unlike `read`, the pointer may be unaligned.
     ///
-    /// # Safety
-    ///
-    /// Beyond accepting a raw pointer, this is unsafe because it semantically
-    /// moves the value out of `self` without preventing further usage of `self`.
-    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
-    /// `self` is not used before the data is overwritten again (e.g. with `write`,
-    /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use
-    /// because it will attempt to drop the value previously at `*self`.
+    /// See [`ptr::read_unaligned`] for safety concerns and examples.
     ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let x = 12;
-    /// let y = &x as *const i32;
-    ///
-    /// unsafe {
-    ///     assert_eq!(y.read_unaligned(), 12);
-    /// }
-    /// ```
+    /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_unaligned(self) -> T
@@ -1901,30 +2126,11 @@ impl<T: ?Sized> *mut T {
     /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
     /// and destination may overlap.
     ///
-    /// NOTE: this has the *same* argument order as `ptr::copy`.
-    ///
-    /// This is semantically equivalent to C's `memmove`.
-    ///
-    /// # Safety
+    /// NOTE: this has the *same* argument order as [`ptr::copy`].
     ///
-    /// Care must be taken with the ownership of `self` and `dest`.
-    /// This method semantically moves the values of `self` into `dest`.
-    /// However it does not drop the contents of `self`, or prevent the contents
-    /// of `dest` from being dropped or used.
+    /// See [`ptr::copy`] for safety concerns and examples.
     ///
-    /// # Examples
-    ///
-    /// Efficiently create a Rust vector from an unsafe buffer:
-    ///
-    /// ```
-    /// # #[allow(dead_code)]
-    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
-    ///     let mut dst = Vec::with_capacity(elts);
-    ///     dst.set_len(elts);
-    ///     ptr.copy_to(dst.as_mut_ptr(), elts);
-    ///     dst
-    /// }
-    /// ```
+    /// [`ptr::copy`]: ./ptr/fn.copy.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to(self, dest: *mut T, count: usize)
@@ -1936,32 +2142,11 @@ impl<T: ?Sized> *mut T {
     /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
     /// and destination may *not* overlap.
     ///
-    /// NOTE: this has the *same* argument order as `ptr::copy_nonoverlapping`.
-    ///
-    /// `copy_nonoverlapping` is semantically equivalent to C's `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 `self` and
-    /// `self`. This method semantically moves the values of `self` into `dest`.
-    /// However it does not drop the contents of `dest`, or prevent the contents
-    /// of `self` from being dropped or used.
-    ///
-    /// # Examples
+    /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`].
     ///
-    /// Efficiently create a Rust vector from an unsafe buffer:
+    /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
     ///
-    /// ```
-    /// # #[allow(dead_code)]
-    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
-    ///     let mut dst = Vec::with_capacity(elts);
-    ///     dst.set_len(elts);
-    ///     ptr.copy_to_nonoverlapping(dst.as_mut_ptr(), elts);
-    ///     dst
-    /// }
-    /// ```
+    /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
@@ -1973,30 +2158,11 @@ impl<T: ?Sized> *mut T {
     /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
     /// and destination may overlap.
     ///
-    /// NOTE: this has the *opposite* argument order of `ptr::copy`.
-    ///
-    /// This is semantically equivalent to C's `memmove`.
-    ///
-    /// # Safety
+    /// NOTE: this has the *opposite* argument order of [`ptr::copy`].
     ///
-    /// Care must be taken with the ownership of `src` and `self`.
-    /// This method semantically moves the values of `src` into `self`.
-    /// However it does not drop the contents of `self`, or prevent the contents
-    /// of `src` from being dropped or used.
+    /// See [`ptr::copy`] for safety concerns and examples.
     ///
-    /// # Examples
-    ///
-    /// Efficiently create a Rust vector from an unsafe buffer:
-    ///
-    /// ```
-    /// # #[allow(dead_code)]
-    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
-    ///     let mut dst: Vec<T> = Vec::with_capacity(elts);
-    ///     dst.set_len(elts);
-    ///     dst.as_mut_ptr().copy_from(ptr, elts);
-    ///     dst
-    /// }
-    /// ```
+    /// [`ptr::copy`]: ./ptr/fn.copy.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_from(self, src: *const T, count: usize)
@@ -2008,32 +2174,11 @@ impl<T: ?Sized> *mut T {
     /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
     /// and destination may *not* overlap.
     ///
-    /// NOTE: this has the *opposite* argument order of `ptr::copy_nonoverlapping`.
-    ///
-    /// `copy_nonoverlapping` is semantically equivalent to C's `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
-    /// `self`. This method semantically moves the values of `src` into `self`.
-    /// However it does not drop the contents of `self`, or prevent the contents
-    /// of `src` from being dropped or used.
-    ///
-    /// # Examples
+    /// NOTE: this has the *opposite* argument order of [`ptr::copy_nonoverlapping`].
     ///
-    /// Efficiently create a Rust vector from an unsafe buffer:
+    /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
     ///
-    /// ```
-    /// # #[allow(dead_code)]
-    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
-    ///     let mut dst: Vec<T> = Vec::with_capacity(elts);
-    ///     dst.set_len(elts);
-    ///     dst.as_mut_ptr().copy_from_nonoverlapping(ptr, elts);
-    ///     dst
-    /// }
-    /// ```
+    /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
@@ -2044,21 +2189,9 @@ impl<T: ?Sized> *mut T {
 
     /// Executes the destructor (if any) of the pointed-to value.
     ///
-    /// This has two use cases:
-    ///
-    /// * 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
-    ///   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.
+    /// See [`ptr::drop_in_place`] for safety concerns and examples.
     ///
-    /// # Safety
-    ///
-    /// This has all the same safety problems as `ptr::read` with respect to
-    /// invalid pointers, types, and double drops.
+    /// [`ptr::drop_in_place`]: ./ptr/fn.drop_in_place.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn drop_in_place(self) {
@@ -2068,36 +2201,9 @@ impl<T: ?Sized> *mut T {
     /// Overwrites a memory location with the given value without reading or
     /// dropping the old value.
     ///
-    /// # Safety
-    ///
-    /// This operation is marked unsafe because it writes through a raw pointer.
-    ///
-    /// It does not drop the contents of `self`. 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 `val`. Semantically, `val` is moved into the
-    /// location pointed to by `self`.
-    ///
-    /// This is appropriate for initializing uninitialized memory, or overwriting
-    /// memory that has previously been `read` from.
-    ///
-    /// The pointer must be aligned; use `write_unaligned` if that is not the case.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut x = 0;
-    /// let y = &mut x as *mut i32;
-    /// let z = 12;
+    /// See [`ptr::write`] for safety concerns and examples.
     ///
-    /// unsafe {
-    ///     y.write(z);
-    ///     assert_eq!(y.read(), 12);
-    /// }
-    /// ```
+    /// [`ptr::write`]: ./ptr/fn.write.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write(self, val: T)
@@ -2109,16 +2215,9 @@ impl<T: ?Sized> *mut T {
     /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
     /// bytes of memory starting at `self` to `val`.
     ///
-    /// # Examples
+    /// See [`ptr::write_bytes`] for safety concerns and examples.
     ///
-    /// ```
-    /// let mut vec = vec![0; 4];
-    /// unsafe {
-    ///     let vec_ptr = vec.as_mut_ptr();
-    ///     vec_ptr.write_bytes(b'a', 2);
-    /// }
-    /// assert_eq!(vec, [b'a', b'a', 0, 0]);
-    /// ```
+    /// [`ptr::write_bytes`]: ./ptr/fn.write_bytes.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write_bytes(self, val: u8, count: usize)
@@ -2134,51 +2233,9 @@ impl<T: ?Sized> *mut T {
     /// to not be elided or reordered by the compiler across other volatile
     /// operations.
     ///
-    /// # Notes
-    ///
-    /// Rust does not currently have a rigorously and formally defined memory model,
-    /// so the precise semantics of what "volatile" means here is subject to change
-    /// over time. That being said, the semantics will almost always end up pretty
-    /// similar to [C11's definition of volatile][c11].
-    ///
-    /// The compiler shouldn't change the relative order or number of volatile
-    /// memory operations. However, volatile memory operations on zero-sized types
-    /// (e.g. if a zero-sized type is passed to `write_volatile`) are no-ops
-    /// and may be ignored.
-    ///
-    /// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
-    ///
-    /// # Safety
-    ///
-    /// This operation is marked unsafe because it accepts a raw pointer.
-    ///
-    /// It does not drop the contents of `self`. This is safe, but it could leak
-    /// allocations or resources, so care must be taken not to overwrite an object
-    /// that should be dropped.
-    ///
-    /// This is appropriate for initializing uninitialized memory, or overwriting
-    /// memory that has previously been `read` from.
-    ///
-    /// Just like in C, whether an operation is volatile has no bearing whatsoever
-    /// on questions involving concurrent access from multiple threads. Volatile
-    /// accesses behave exactly like non-atomic accesses in that regard. In particular,
-    /// a race between a `write_volatile` and any other operation (reading or writing)
-    /// on the same location is undefined behavior.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut x = 0;
-    /// let y = &mut x as *mut i32;
-    /// let z = 12;
+    /// See [`ptr::write_volatile`] for safety concerns and examples.
     ///
-    /// unsafe {
-    ///     y.write_volatile(z);
-    ///     assert_eq!(y.read_volatile(), 12);
-    /// }
-    /// ```
+    /// [`ptr::write_volatile`]: ./ptr/fn.write_volatile.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write_volatile(self, val: T)
@@ -2192,34 +2249,9 @@ impl<T: ?Sized> *mut T {
     ///
     /// Unlike `write`, the pointer may be unaligned.
     ///
-    /// # Safety
-    ///
-    /// This operation is marked unsafe because it writes through a raw pointer.
-    ///
-    /// It does not drop the contents of `self`. This is safe, but it could leak
-    /// allocations or resources, so care must be taken not to overwrite an object
-    /// that should be dropped.
+    /// See [`ptr::write_unaligned`] for safety concerns and examples.
     ///
-    /// Additionally, it does not drop `self`. Semantically, `self` is moved into the
-    /// location pointed to by `val`.
-    ///
-    /// This is appropriate for initializing uninitialized memory, or overwriting
-    /// memory that has previously been `read` from.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut x = 0;
-    /// let y = &mut x as *mut i32;
-    /// let z = 12;
-    ///
-    /// unsafe {
-    ///     y.write_unaligned(z);
-    ///     assert_eq!(y.read_unaligned(), 12);
-    /// }
-    /// ```
+    /// [`ptr::write_unaligned`]: ./ptr/fn.write_unaligned.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write_unaligned(self, val: T)
@@ -2231,10 +2263,9 @@ impl<T: ?Sized> *mut T {
     /// Replaces the value at `self` with `src`, returning the old
     /// value, without dropping either.
     ///
-    /// # Safety
+    /// See [`ptr::replace`] for safety concerns and examples.
     ///
-    /// This is only unsafe because it accepts a raw pointer.
-    /// Otherwise, this operation is identical to `mem::replace`.
+    /// [`ptr::replace`]: ./ptr/fn.replace.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn replace(self, src: T) -> T
@@ -2247,12 +2278,9 @@ impl<T: ?Sized> *mut T {
     /// deinitializing either. They may overlap, unlike `mem::swap` which is
     /// otherwise equivalent.
     ///
-    /// # Safety
-    ///
-    /// This function copies the memory through the raw pointers passed to it
-    /// as arguments.
+    /// See [`ptr::swap`] for safety concerns and examples.
     ///
-    /// Ensure that these pointers are valid before calling `swap`.
+    /// [`ptr::swap`]: ./ptr/fn.swap.html
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn swap(self, with: *mut T)