about summary refs log tree commit diff
path: root/src/libcore/ops
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-08-12 19:40:49 +0000
committerbors <bors@rust-lang.org>2017-08-12 19:40:49 +0000
commitf774bced502cf190426f778001a342715acb1d47 (patch)
tree00edb67e2b56034d186a73b95852a8c1798c42ff /src/libcore/ops
parent0269acbb10bc7a5b083a5daf095ff391e21ee4e9 (diff)
parent6bdba82ba18fe69ac448f81b10bbbc7d0c10bce1 (diff)
downloadrust-f774bced502cf190426f778001a342715acb1d47.tar.gz
rust-f774bced502cf190426f778001a342715acb1d47.zip
Auto merge of #43724 - lukaramu:std-ops-docs, r=QuietMisdreavus
Improve std::ops docs

Fixes #29365. (This fixes all but one point from @steveklabnik's list, but that point was referring to examples of implementing range traits, but there are no range traits in std::ops.)

The main changes are quite a bit of copyediting, adding more "real" examples for some of the traits, incorporating some guidance from the API docs, more linking (cross-docs and to the book & reference), cleaning up examples, moving things around, and so on. Refer to the commit messages for more details.

Note: I decided to link to the second edition of the book since I think it's more appropriate now for the sections I linked, if this is not okay, please say so!
Diffstat (limited to 'src/libcore/ops')
-rw-r--r--src/libcore/ops/arith.rs302
-rw-r--r--src/libcore/ops/bit.rs278
-rw-r--r--src/libcore/ops/deref.rs102
-rw-r--r--src/libcore/ops/drop.rs62
-rw-r--r--src/libcore/ops/function.rs128
-rw-r--r--src/libcore/ops/index.rs49
-rw-r--r--src/libcore/ops/mod.rs17
-rw-r--r--src/libcore/ops/range.rs206
8 files changed, 615 insertions, 529 deletions
diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs
index d898f9146cd..62007caedd3 100644
--- a/src/libcore/ops/arith.rs
+++ b/src/libcore/ops/arith.rs
@@ -10,15 +10,20 @@
 
 /// The addition operator `+`.
 ///
+/// Note that `RHS` is `Self` by default, but this is not mandatory. For
+/// example, [`std::time::SystemTime`] implements `Add<Duration>`, which permits
+/// operations of the form `SystemTime = SystemTime + Duration`.
+///
+/// [`std::time::SystemTime`]: ../../std/time/struct.SystemTime.html
+///
 /// # Examples
 ///
-/// This example creates a `Point` struct that implements the `Add` trait, and
-/// then demonstrates adding two `Point`s.
+/// ## `Add`able points
 ///
 /// ```
 /// use std::ops::Add;
 ///
-/// #[derive(Debug)]
+/// #[derive(Debug, PartialEq)]
 /// struct Point {
 ///     x: i32,
 ///     y: i32,
@@ -35,31 +40,25 @@
 ///     }
 /// }
 ///
-/// impl PartialEq for Point {
-///     fn eq(&self, other: &Self) -> bool {
-///         self.x == other.x && self.y == other.y
-///     }
-/// }
-///
-/// fn main() {
-///     assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
-///                Point { x: 3, y: 3 });
-/// }
+/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
+///            Point { x: 3, y: 3 });
 /// ```
 ///
+/// ## Implementing `Add` with generics
+///
 /// Here is an example of the same `Point` struct implementing the `Add` trait
 /// using generics.
 ///
 /// ```
 /// use std::ops::Add;
 ///
-/// #[derive(Debug)]
+/// #[derive(Debug, PartialEq)]
 /// struct Point<T> {
 ///     x: T,
 ///     y: T,
 /// }
 ///
-/// // Notice that the implementation uses the `Output` associated type
+/// // Notice that the implementation uses the associated type `Output`.
 /// impl<T: Add<Output=T>> Add for Point<T> {
 ///     type Output = Point<T>;
 ///
@@ -71,32 +70,18 @@
 ///     }
 /// }
 ///
-/// impl<T: PartialEq> PartialEq for Point<T> {
-///     fn eq(&self, other: &Self) -> bool {
-///         self.x == other.x && self.y == other.y
-///     }
-/// }
-///
-/// fn main() {
-///     assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
-///                Point { x: 3, y: 3 });
-/// }
+/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
+///            Point { x: 3, y: 3 });
 /// ```
-///
-/// Note that `RHS = Self` by default, but this is not mandatory. For example,
-/// [std::time::SystemTime] implements `Add<Duration>`, which permits
-/// operations of the form `SystemTime = SystemTime + Duration`.
-///
-/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html
 #[lang = "add"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"]
 pub trait Add<RHS=Self> {
-    /// The resulting type after applying the `+` operator
+    /// The resulting type after applying the `+` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
-    /// The method for the `+` operator
+    /// Performs the `+` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn add(self, rhs: RHS) -> Self::Output;
 }
@@ -120,15 +105,20 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
 /// The subtraction operator `-`.
 ///
+/// Note that `RHS` is `Self` by default, but this is not mandatory. For
+/// example, [`std::time::SystemTime`] implements `Sub<Duration>`, which permits
+/// operations of the form `SystemTime = SystemTime - Duration`.
+///
+/// [`std::time::SystemTime`]: ../../std/time/struct.SystemTime.html
+///
 /// # Examples
 ///
-/// This example creates a `Point` struct that implements the `Sub` trait, and
-/// then demonstrates subtracting two `Point`s.
+/// ## `Sub`tractable points
 ///
 /// ```
 /// use std::ops::Sub;
 ///
-/// #[derive(Debug)]
+/// #[derive(Debug, PartialEq)]
 /// struct Point {
 ///     x: i32,
 ///     y: i32,
@@ -145,31 +135,25 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 ///     }
 /// }
 ///
-/// impl PartialEq for Point {
-///     fn eq(&self, other: &Self) -> bool {
-///         self.x == other.x && self.y == other.y
-///     }
-/// }
-///
-/// fn main() {
-///     assert_eq!(Point { x: 3, y: 3 } - Point { x: 2, y: 3 },
-///                Point { x: 1, y: 0 });
-/// }
+/// assert_eq!(Point { x: 3, y: 3 } - Point { x: 2, y: 3 },
+///            Point { x: 1, y: 0 });
 /// ```
 ///
+/// ## Implementing `Sub` with generics
+///
 /// Here is an example of the same `Point` struct implementing the `Sub` trait
 /// using generics.
 ///
 /// ```
 /// use std::ops::Sub;
 ///
-/// #[derive(Debug)]
+/// #[derive(Debug, PartialEq)]
 /// struct Point<T> {
 ///     x: T,
 ///     y: T,
 /// }
 ///
-/// // Notice that the implementation uses the `Output` associated type
+/// // Notice that the implementation uses the associated type `Output`.
 /// impl<T: Sub<Output=T>> Sub for Point<T> {
 ///     type Output = Point<T>;
 ///
@@ -181,32 +165,18 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 ///     }
 /// }
 ///
-/// impl<T: PartialEq> PartialEq for Point<T> {
-///     fn eq(&self, other: &Self) -> bool {
-///         self.x == other.x && self.y == other.y
-///     }
-/// }
-///
-/// fn main() {
-///     assert_eq!(Point { x: 2, y: 3 } - Point { x: 1, y: 0 },
-///                Point { x: 1, y: 3 });
-/// }
+/// assert_eq!(Point { x: 2, y: 3 } - Point { x: 1, y: 0 },
+///            Point { x: 1, y: 3 });
 /// ```
-///
-/// Note that `RHS = Self` by default, but this is not mandatory. For example,
-/// [std::time::SystemTime] implements `Sub<Duration>`, which permits
-/// operations of the form `SystemTime = SystemTime - Duration`.
-///
-/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html
 #[lang = "sub"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"]
 pub trait Sub<RHS=Self> {
-    /// The resulting type after applying the `-` operator
+    /// The resulting type after applying the `-` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
-    /// The method for the `-` operator
+    /// Performs the `-` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn sub(self, rhs: RHS) -> Self::Output;
 }
@@ -230,17 +200,19 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
 /// The multiplication operator `*`.
 ///
+/// Note that `RHS` is `Self` by default, but this is not mandatory.
+///
 /// # Examples
 ///
-/// Implementing a `Mul`tipliable rational number struct:
+/// ## `Mul`tipliable rational numbers
 ///
 /// ```
 /// use std::ops::Mul;
 ///
-/// // The uniqueness of rational numbers in lowest terms is a consequence of
-/// // the fundamental theorem of arithmetic.
-/// #[derive(Eq)]
-/// #[derive(PartialEq, Debug)]
+/// // By the fundamental theorem of arithmetic, rational numbers in lowest
+/// // terms are unique. So, by keeping `Rational`s in reduced form, we can
+/// // derive `Eq` and `PartialEq`.
+/// #[derive(Debug, Eq, PartialEq)]
 /// struct Rational {
 ///     nominator: usize,
 ///     denominator: usize,
@@ -291,45 +263,37 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 ///            Rational::new(1, 2));
 /// ```
 ///
-/// Note that `RHS = Self` by default, but this is not mandatory. Here is an
-/// implementation which enables multiplication of vectors by scalars, as is
-/// done in linear algebra.
+/// ## Multiplying vectors by scalars as in linear algebra
 ///
 /// ```
 /// use std::ops::Mul;
 ///
-/// struct Scalar {value: usize};
+/// struct Scalar { value: usize }
 ///
-/// #[derive(Debug)]
-/// struct Vector {value: Vec<usize>};
+/// #[derive(Debug, PartialEq)]
+/// struct Vector { value: Vec<usize> }
 ///
-/// impl Mul<Vector> for Scalar {
+/// impl Mul<Scalar> for Vector {
 ///     type Output = Vector;
 ///
-///     fn mul(self, rhs: Vector) -> Vector {
-///         Vector {value: rhs.value.iter().map(|v| self.value * v).collect()}
+///     fn mul(self, rhs: Scalar) -> Vector {
+///         Vector { value: self.value.iter().map(|v| v * rhs.value).collect() }
 ///     }
 /// }
 ///
-/// impl PartialEq<Vector> for Vector {
-///     fn eq(&self, other: &Self) -> bool {
-///         self.value == other.value
-///     }
-/// }
-///
-/// let scalar = Scalar{value: 3};
-/// let vector = Vector{value: vec![2, 4, 6]};
-/// assert_eq!(scalar * vector, Vector{value: vec![6, 12, 18]});
+/// let vector = Vector { value: vec![2, 4, 6] };
+/// let scalar = Scalar { value: 3 };
+/// assert_eq!(vector * scalar, Vector { value: vec![6, 12, 18] });
 /// ```
 #[lang = "mul"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"]
 pub trait Mul<RHS=Self> {
-    /// The resulting type after applying the `*` operator
+    /// The resulting type after applying the `*` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
-    /// The method for the `*` operator
+    /// Performs the `*` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn mul(self, rhs: RHS) -> Self::Output;
 }
@@ -353,17 +317,19 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
 /// The division operator `/`.
 ///
+/// Note that `RHS` is `Self` by default, but this is not mandatory.
+///
 /// # Examples
 ///
-/// Implementing a `Div`idable rational number struct:
+/// ## `Div`idable rational numbers
 ///
 /// ```
 /// use std::ops::Div;
 ///
-/// // The uniqueness of rational numbers in lowest terms is a consequence of
-/// // the fundamental theorem of arithmetic.
-/// #[derive(Eq)]
-/// #[derive(PartialEq, Debug)]
+/// // By the fundamental theorem of arithmetic, rational numbers in lowest
+/// // terms are unique. So, by keeping `Rational`s in reduced form, we can
+/// // derive `Eq` and `PartialEq`.
+/// #[derive(Debug, Eq, PartialEq)]
 /// struct Rational {
 ///     nominator: usize,
 ///     denominator: usize,
@@ -413,52 +379,42 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 ///     x
 /// }
 ///
-/// fn main() {
-///     assert_eq!(Rational::new(1, 2), Rational::new(2, 4));
-///     assert_eq!(Rational::new(1, 2) / Rational::new(3, 4),
-///                Rational::new(2, 3));
-/// }
+/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4));
+/// assert_eq!(Rational::new(1, 2) / Rational::new(3, 4),
+///            Rational::new(2, 3));
 /// ```
 ///
-/// Note that `RHS = Self` by default, but this is not mandatory. Here is an
-/// implementation which enables division of vectors by scalars, as is done in
-/// linear algebra.
+/// ## Dividing vectors by scalars as in linear algebra
 ///
 /// ```
 /// use std::ops::Div;
 ///
-/// struct Scalar {value: f32};
+/// struct Scalar { value: f32 }
 ///
-/// #[derive(Debug)]
-/// struct Vector {value: Vec<f32>};
+/// #[derive(Debug, PartialEq)]
+/// struct Vector { value: Vec<f32> }
 ///
 /// impl Div<Scalar> for Vector {
 ///     type Output = Vector;
 ///
 ///     fn div(self, rhs: Scalar) -> Vector {
-///         Vector {value: self.value.iter().map(|v| v / rhs.value).collect()}
-///     }
-/// }
-///
-/// impl PartialEq<Vector> for Vector {
-///     fn eq(&self, other: &Self) -> bool {
-///         self.value == other.value
+///         Vector { value: self.value.iter().map(|v| v / rhs.value).collect() }
 ///     }
 /// }
 ///
-/// let scalar = Scalar{value: 2f32};
-/// let vector = Vector{value: vec![2f32, 4f32, 6f32]};
-/// assert_eq!(vector / scalar, Vector{value: vec![1f32, 2f32, 3f32]});
+/// let scalar = Scalar { value: 2f32 };
+/// let vector = Vector { value: vec![2f32, 4f32, 6f32] };
+/// assert_eq!(vector / scalar, Vector { value: vec![1f32, 2f32, 3f32] });
 /// ```
 #[lang = "div"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"]
 pub trait Div<RHS=Self> {
-    /// The resulting type after applying the `/` operator
+    /// The resulting type after applying the `/` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
-    /// The method for the `/` operator
+    /// Performs the `/` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn div(self, rhs: RHS) -> Self::Output;
 }
@@ -499,6 +455,8 @@ div_impl_float! { f32 f64 }
 
 /// The remainder operator `%`.
 ///
+/// Note that `RHS` is `Self` by default, but this is not mandatory.
+///
 /// # Examples
 ///
 /// This example implements `Rem` on a `SplitSlice` object. After `Rem` is
@@ -526,7 +484,7 @@ div_impl_float! { f32 f64 }
 /// }
 ///
 /// // If we were to divide &[0, 1, 2, 3, 4, 5, 6, 7] into slices of size 3,
-/// // the remainder would be &[6, 7]
+/// // the remainder would be &[6, 7].
 /// assert_eq!(SplitSlice { slice: &[0, 1, 2, 3, 4, 5, 6, 7] } % 3,
 ///            SplitSlice { slice: &[6, 7] });
 /// ```
@@ -534,11 +492,11 @@ div_impl_float! { f32 f64 }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"]
 pub trait Rem<RHS=Self> {
-    /// The resulting type after applying the `%` operator
+    /// The resulting type after applying the `%` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output = Self;
 
-    /// The method for the `%` operator
+    /// Performs the `%` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn rem(self, rhs: RHS) -> Self::Output;
 }
@@ -607,21 +565,21 @@ rem_impl_float! { f32 f64 }
 ///     }
 /// }
 ///
-/// // a negative positive is a negative
+/// // A negative positive is a negative.
 /// assert_eq!(-Sign::Positive, Sign::Negative);
-/// // a double negative is a positive
+/// // A double negative is a positive.
 /// assert_eq!(-Sign::Negative, Sign::Positive);
-/// // zero is its own negation
+/// // Zero is its own negation.
 /// assert_eq!(-Sign::Zero, Sign::Zero);
 /// ```
 #[lang = "neg"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Neg {
-    /// The resulting type after applying the `-` operator
+    /// The resulting type after applying the `-` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
-    /// The method for the unary `-` operator
+    /// Performs the unary `-` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn neg(self) -> Self::Output;
 }
@@ -668,7 +626,7 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
 /// ```
 /// use std::ops::AddAssign;
 ///
-/// #[derive(Debug)]
+/// #[derive(Debug, PartialEq)]
 /// struct Point {
 ///     x: i32,
 ///     y: i32,
@@ -683,12 +641,6 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
 ///     }
 /// }
 ///
-/// impl PartialEq for Point {
-///     fn eq(&self, other: &Self) -> bool {
-///         self.x == other.x && self.y == other.y
-///     }
-/// }
-///
 /// let mut point = Point { x: 1, y: 0 };
 /// point += Point { x: 2, y: 3 };
 /// assert_eq!(point, Point { x: 3, y: 3 });
@@ -697,7 +649,7 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"]
 pub trait AddAssign<Rhs=Self> {
-    /// The method for the `+=` operator
+    /// Performs the `+=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn add_assign(&mut self, rhs: Rhs);
 }
@@ -725,7 +677,7 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 /// ```
 /// use std::ops::SubAssign;
 ///
-/// #[derive(Debug)]
+/// #[derive(Debug, PartialEq)]
 /// struct Point {
 ///     x: i32,
 ///     y: i32,
@@ -740,12 +692,6 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 ///     }
 /// }
 ///
-/// impl PartialEq for Point {
-///     fn eq(&self, other: &Self) -> bool {
-///         self.x == other.x && self.y == other.y
-///     }
-/// }
-///
 /// let mut point = Point { x: 3, y: 3 };
 /// point -= Point { x: 2, y: 3 };
 /// assert_eq!(point, Point {x: 1, y: 0});
@@ -754,7 +700,7 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"]
 pub trait SubAssign<Rhs=Self> {
-    /// The method for the `-=` operator
+    /// Performs the `-=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn sub_assign(&mut self, rhs: Rhs);
 }
@@ -776,31 +722,27 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 ///
 /// # Examples
 ///
-/// A trivial implementation of `MulAssign`. When `Foo *= Foo` happens, it ends up
-/// calling `mul_assign`, and therefore, `main` prints `Multiplying!`.
-///
 /// ```
 /// use std::ops::MulAssign;
 ///
-/// struct Foo;
+/// #[derive(Debug, PartialEq)]
+/// struct Frequency { hertz: f64 }
 ///
-/// impl MulAssign for Foo {
-///     fn mul_assign(&mut self, _rhs: Foo) {
-///         println!("Multiplying!");
+/// impl MulAssign<f64> for Frequency {
+///     fn mul_assign(&mut self, rhs: f64) {
+///         self.hertz *= rhs;
 ///     }
 /// }
 ///
-/// # #[allow(unused_assignments)]
-/// fn main() {
-///     let mut foo = Foo;
-///     foo *= Foo;
-/// }
+/// let mut frequency = Frequency { hertz: 50.0 };
+/// frequency *= 4.0;
+/// assert_eq!(Frequency { hertz: 200.0 }, frequency);
 /// ```
 #[lang = "mul_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"]
 pub trait MulAssign<Rhs=Self> {
-    /// The method for the `*=` operator
+    /// Performs the `*=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn mul_assign(&mut self, rhs: Rhs);
 }
@@ -822,31 +764,27 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 ///
 /// # Examples
 ///
-/// A trivial implementation of `DivAssign`. When `Foo /= Foo` happens, it ends up
-/// calling `div_assign`, and therefore, `main` prints `Dividing!`.
-///
 /// ```
 /// use std::ops::DivAssign;
 ///
-/// struct Foo;
+/// #[derive(Debug, PartialEq)]
+/// struct Frequency { hertz: f64 }
 ///
-/// impl DivAssign for Foo {
-///     fn div_assign(&mut self, _rhs: Foo) {
-///         println!("Dividing!");
+/// impl DivAssign<f64> for Frequency {
+///     fn div_assign(&mut self, rhs: f64) {
+///         self.hertz /= rhs;
 ///     }
 /// }
 ///
-/// # #[allow(unused_assignments)]
-/// fn main() {
-///     let mut foo = Foo;
-///     foo /= Foo;
-/// }
+/// let mut frequency = Frequency { hertz: 200.0 };
+/// frequency /= 4.0;
+/// assert_eq!(Frequency { hertz: 50.0 }, frequency);
 /// ```
 #[lang = "div_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"]
 pub trait DivAssign<Rhs=Self> {
-    /// The method for the `/=` operator
+    /// Performs the `/=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn div_assign(&mut self, rhs: Rhs);
 }
@@ -867,31 +805,31 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 ///
 /// # Examples
 ///
-/// A trivial implementation of `RemAssign`. When `Foo %= Foo` happens, it ends up
-/// calling `rem_assign`, and therefore, `main` prints `Remainder-ing!`.
-///
 /// ```
 /// use std::ops::RemAssign;
 ///
-/// struct Foo;
+/// struct CookieJar { cookies: u32 }
 ///
-/// impl RemAssign for Foo {
-///     fn rem_assign(&mut self, _rhs: Foo) {
-///         println!("Remainder-ing!");
+/// impl RemAssign<u32> for CookieJar {
+///     fn rem_assign(&mut self, piles: u32) {
+///         self.cookies %= piles;
 ///     }
 /// }
 ///
-/// # #[allow(unused_assignments)]
-/// fn main() {
-///     let mut foo = Foo;
-///     foo %= Foo;
-/// }
+/// let mut jar = CookieJar { cookies: 31 };
+/// let piles = 4;
+///
+/// println!("Splitting up {} cookies into {} even piles!", jar.cookies, piles);
+///
+/// jar %= piles;
+///
+/// println!("{} cookies remain in the cookie jar!", jar.cookies);
 /// ```
 #[lang = "rem_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"]
 pub trait RemAssign<Rhs=Self> {
-    /// The method for the `%=` operator
+    /// Performs the `%=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn rem_assign(&mut self, rhs: Rhs);
 }
diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs
index 8743be3557c..0bc5e554cb3 100644
--- a/src/libcore/ops/bit.rs
+++ b/src/libcore/ops/bit.rs
@@ -41,11 +41,11 @@
 #[lang = "not"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Not {
-    /// The resulting type after applying the `!` operator
+    /// The resulting type after applying the `!` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
-    /// The method for the unary `!` operator
+    /// Performs the unary `!` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn not(self) -> Self::Output;
 }
@@ -68,9 +68,11 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
 /// The bitwise AND operator `&`.
 ///
+/// Note that `RHS` is `Self` by default, but this is not mandatory.
+///
 /// # Examples
 ///
-/// In this example, the `&` operator is lifted to a trivial `Scalar` type.
+/// An implementation of `BitAnd` for a wrapper around `bool`.
 ///
 /// ```
 /// use std::ops::BitAnd;
@@ -87,16 +89,13 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///     }
 /// }
 ///
-/// fn main() {
-///     assert_eq!(Scalar(true) & Scalar(true), Scalar(true));
-///     assert_eq!(Scalar(true) & Scalar(false), Scalar(false));
-///     assert_eq!(Scalar(false) & Scalar(true), Scalar(false));
-///     assert_eq!(Scalar(false) & Scalar(false), Scalar(false));
-/// }
+/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true));
+/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false));
+/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false));
+/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false));
 /// ```
 ///
-/// In this example, the `BitAnd` trait is implemented for a `BooleanVector`
-/// struct.
+/// An implementation of `BitAnd` for a wrapper around `Vec<bool>`.
 ///
 /// ```
 /// use std::ops::BitAnd;
@@ -114,22 +113,20 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///     }
 /// }
 ///
-/// fn main() {
-///     let bv1 = BooleanVector(vec![true, true, false, false]);
-///     let bv2 = BooleanVector(vec![true, false, true, false]);
-///     let expected = BooleanVector(vec![true, false, false, false]);
-///     assert_eq!(bv1 & bv2, expected);
-/// }
+/// let bv1 = BooleanVector(vec![true, true, false, false]);
+/// let bv2 = BooleanVector(vec![true, false, true, false]);
+/// let expected = BooleanVector(vec![true, false, false, false]);
+/// assert_eq!(bv1 & bv2, expected);
 /// ```
 #[lang = "bitand"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"]
 pub trait BitAnd<RHS=Self> {
-    /// The resulting type after applying the `&` operator
+    /// The resulting type after applying the `&` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
-    /// The method for the `&` operator
+    /// Performs the `&` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn bitand(self, rhs: RHS) -> Self::Output;
 }
@@ -152,9 +149,11 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
 /// The bitwise OR operator `|`.
 ///
+/// Note that `RHS` is `Self` by default, but this is not mandatory.
+///
 /// # Examples
 ///
-/// In this example, the `|` operator is lifted to a trivial `Scalar` type.
+/// An implementation of `BitOr` for a wrapper around `bool`.
 ///
 /// ```
 /// use std::ops::BitOr;
@@ -171,16 +170,13 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///     }
 /// }
 ///
-/// fn main() {
-///     assert_eq!(Scalar(true) | Scalar(true), Scalar(true));
-///     assert_eq!(Scalar(true) | Scalar(false), Scalar(true));
-///     assert_eq!(Scalar(false) | Scalar(true), Scalar(true));
-///     assert_eq!(Scalar(false) | Scalar(false), Scalar(false));
-/// }
+/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true));
+/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true));
+/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true));
+/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false));
 /// ```
 ///
-/// In this example, the `BitOr` trait is implemented for a `BooleanVector`
-/// struct.
+/// An implementation of `BitOr` for a wrapper around `Vec<bool>`.
 ///
 /// ```
 /// use std::ops::BitOr;
@@ -198,22 +194,20 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///     }
 /// }
 ///
-/// fn main() {
-///     let bv1 = BooleanVector(vec![true, true, false, false]);
-///     let bv2 = BooleanVector(vec![true, false, true, false]);
-///     let expected = BooleanVector(vec![true, true, true, false]);
-///     assert_eq!(bv1 | bv2, expected);
-/// }
+/// let bv1 = BooleanVector(vec![true, true, false, false]);
+/// let bv2 = BooleanVector(vec![true, false, true, false]);
+/// let expected = BooleanVector(vec![true, true, true, false]);
+/// assert_eq!(bv1 | bv2, expected);
 /// ```
 #[lang = "bitor"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"]
 pub trait BitOr<RHS=Self> {
-    /// The resulting type after applying the `|` operator
+    /// The resulting type after applying the `|` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
-    /// The method for the `|` operator
+    /// Performs the `|` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn bitor(self, rhs: RHS) -> Self::Output;
 }
@@ -236,9 +230,11 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
 /// The bitwise XOR operator `^`.
 ///
+/// Note that `RHS` is `Self` by default, but this is not mandatory.
+///
 /// # Examples
 ///
-/// In this example, the `^` operator is lifted to a trivial `Scalar` type.
+/// An implementation of `BitXor` that lifts `^` to a wrapper around `bool`.
 ///
 /// ```
 /// use std::ops::BitXor;
@@ -255,16 +251,13 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///     }
 /// }
 ///
-/// fn main() {
-///     assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false));
-///     assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true));
-///     assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true));
-///     assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false));
-/// }
+/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false));
+/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true));
+/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true));
+/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false));
 /// ```
 ///
-/// In this example, the `BitXor` trait is implemented for a `BooleanVector`
-/// struct.
+/// An implementation of `BitXor` trait for a wrapper around `Vec<bool>`.
 ///
 /// ```
 /// use std::ops::BitXor;
@@ -285,22 +278,20 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///     }
 /// }
 ///
-/// fn main() {
-///     let bv1 = BooleanVector(vec![true, true, false, false]);
-///     let bv2 = BooleanVector(vec![true, false, true, false]);
-///     let expected = BooleanVector(vec![false, true, true, false]);
-///     assert_eq!(bv1 ^ bv2, expected);
-/// }
+/// let bv1 = BooleanVector(vec![true, true, false, false]);
+/// let bv2 = BooleanVector(vec![true, false, true, false]);
+/// let expected = BooleanVector(vec![false, true, true, false]);
+/// assert_eq!(bv1 ^ bv2, expected);
 /// ```
 #[lang = "bitxor"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"]
 pub trait BitXor<RHS=Self> {
-    /// The resulting type after applying the `^` operator
+    /// The resulting type after applying the `^` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
-    /// The method for the `^` operator
+    /// Performs the `^` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn bitxor(self, rhs: RHS) -> Self::Output;
 }
@@ -326,7 +317,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// # Examples
 ///
 /// An implementation of `Shl` that lifts the `<<` operation on integers to a
-/// `Scalar` struct.
+/// wrapper around `usize`.
 ///
 /// ```
 /// use std::ops::Shl;
@@ -342,9 +333,8 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///         Scalar(lhs << rhs)
 ///     }
 /// }
-/// fn main() {
-///     assert_eq!(Scalar(4) << Scalar(2), Scalar(16));
-/// }
+///
+/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16));
 /// ```
 ///
 /// An implementation of `Shl` that spins a vector leftward by a given amount.
@@ -361,7 +351,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///     type Output = Self;
 ///
 ///     fn shl(self, rhs: usize) -> SpinVector<T> {
-///         // rotate the vector by `rhs` places
+///         // Rotate the vector by `rhs` places.
 ///         let (a, b) = self.vec.split_at(rhs);
 ///         let mut spun_vector: Vec<T> = vec![];
 ///         spun_vector.extend_from_slice(b);
@@ -370,20 +360,18 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///     }
 /// }
 ///
-/// fn main() {
-///     assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2,
-///                SpinVector { vec: vec![2, 3, 4, 0, 1] });
-/// }
+/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2,
+///            SpinVector { vec: vec![2, 3, 4, 0, 1] });
 /// ```
 #[lang = "shl"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"]
 pub trait Shl<RHS> {
-    /// The resulting type after applying the `<<` operator
+    /// The resulting type after applying the `<<` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
-    /// The method for the `<<` operator
+    /// Performs the `<<` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn shl(self, rhs: RHS) -> Self::Output;
 }
@@ -430,7 +418,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
 /// # Examples
 ///
 /// An implementation of `Shr` that lifts the `>>` operation on integers to a
-/// `Scalar` struct.
+/// wrapper around `usize`.
 ///
 /// ```
 /// use std::ops::Shr;
@@ -446,9 +434,8 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
 ///         Scalar(lhs >> rhs)
 ///     }
 /// }
-/// fn main() {
-///     assert_eq!(Scalar(16) >> Scalar(2), Scalar(4));
-/// }
+///
+/// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4));
 /// ```
 ///
 /// An implementation of `Shr` that spins a vector rightward by a given amount.
@@ -465,7 +452,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
 ///     type Output = Self;
 ///
 ///     fn shr(self, rhs: usize) -> SpinVector<T> {
-///         // rotate the vector by `rhs` places
+///         // Rotate the vector by `rhs` places.
 ///         let (a, b) = self.vec.split_at(self.vec.len() - rhs);
 ///         let mut spun_vector: Vec<T> = vec![];
 ///         spun_vector.extend_from_slice(b);
@@ -474,20 +461,18 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
 ///     }
 /// }
 ///
-/// fn main() {
-///     assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2,
-///                SpinVector { vec: vec![3, 4, 0, 1, 2] });
-/// }
+/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2,
+///            SpinVector { vec: vec![3, 4, 0, 1, 2] });
 /// ```
 #[lang = "shr"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"]
 pub trait Shr<RHS> {
-    /// The resulting type after applying the `>>` operator
+    /// The resulting type after applying the `>>` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
-    /// The method for the `>>` operator
+    /// Performs the `>>` operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn shr(self, rhs: RHS) -> Self::Output;
 }
@@ -533,7 +518,8 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 ///
 /// # Examples
 ///
-/// In this example, the `&=` operator is lifted to a trivial `Scalar` type.
+/// An implementation of `BitAndAssign` that lifts the `&=` operator to a
+/// wrapper around `bool`.
 ///
 /// ```
 /// use std::ops::BitAndAssign;
@@ -548,27 +534,25 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 ///     }
 /// }
 ///
-/// fn main() {
-///     let mut scalar = Scalar(true);
-///     scalar &= Scalar(true);
-///     assert_eq!(scalar, Scalar(true));
+/// let mut scalar = Scalar(true);
+/// scalar &= Scalar(true);
+/// assert_eq!(scalar, Scalar(true));
 ///
-///     let mut scalar = Scalar(true);
-///     scalar &= Scalar(false);
-///     assert_eq!(scalar, Scalar(false));
+/// let mut scalar = Scalar(true);
+/// scalar &= Scalar(false);
+/// assert_eq!(scalar, Scalar(false));
 ///
-///     let mut scalar = Scalar(false);
-///     scalar &= Scalar(true);
-///     assert_eq!(scalar, Scalar(false));
+/// let mut scalar = Scalar(false);
+/// scalar &= Scalar(true);
+/// assert_eq!(scalar, Scalar(false));
 ///
-///     let mut scalar = Scalar(false);
-///     scalar &= Scalar(false);
-///     assert_eq!(scalar, Scalar(false));
-/// }
+/// let mut scalar = Scalar(false);
+/// scalar &= Scalar(false);
+/// assert_eq!(scalar, Scalar(false));
 /// ```
 ///
-/// In this example, the `BitAndAssign` trait is implemented for a
-/// `BooleanVector` struct.
+/// Here, the `BitAndAssign` trait is implemented for a wrapper around
+/// `Vec<bool>`.
 ///
 /// ```
 /// use std::ops::BitAndAssign;
@@ -577,7 +561,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 /// struct BooleanVector(Vec<bool>);
 ///
 /// impl BitAndAssign for BooleanVector {
-///     // rhs is the "right-hand side" of the expression `a &= b`
+///     // `rhs` is the "right-hand side" of the expression `a &= b`.
 ///     fn bitand_assign(&mut self, rhs: Self) {
 ///         assert_eq!(self.0.len(), rhs.0.len());
 ///         *self = BooleanVector(self.0
@@ -588,18 +572,16 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 ///     }
 /// }
 ///
-/// fn main() {
-///     let mut bv = BooleanVector(vec![true, true, false, false]);
-///     bv &= BooleanVector(vec![true, false, true, false]);
-///     let expected = BooleanVector(vec![true, false, false, false]);
-///     assert_eq!(bv, expected);
-/// }
+/// let mut bv = BooleanVector(vec![true, true, false, false]);
+/// bv &= BooleanVector(vec![true, false, true, false]);
+/// let expected = BooleanVector(vec![true, false, false, false]);
+/// assert_eq!(bv, expected);
 /// ```
 #[lang = "bitand_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"]
 pub trait BitAndAssign<Rhs=Self> {
-    /// The method for the `&=` operator
+    /// Performs the `&=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn bitand_assign(&mut self, rhs: Rhs);
 }
@@ -620,31 +602,31 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///
 /// # Examples
 ///
-/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up
-/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`.
-///
 /// ```
 /// use std::ops::BitOrAssign;
 ///
-/// struct Foo;
+/// #[derive(Debug, PartialEq)]
+/// struct PersonalPreferences {
+///     likes_cats: bool,
+///     likes_dogs: bool,
+/// }
 ///
-/// impl BitOrAssign for Foo {
-///     fn bitor_assign(&mut self, _rhs: Foo) {
-///         println!("Bitwise Or-ing!");
+/// impl BitOrAssign for PersonalPreferences {
+///     fn bitor_assign(&mut self, rhs: Self) {
+///         self.likes_cats |= rhs.likes_cats;
+///         self.likes_dogs |= rhs.likes_dogs;
 ///     }
 /// }
 ///
-/// # #[allow(unused_assignments)]
-/// fn main() {
-///     let mut foo = Foo;
-///     foo |= Foo;
-/// }
+/// let mut prefs = PersonalPreferences { likes_cats: true, likes_dogs: false };
+/// prefs |= PersonalPreferences { likes_cats: false, likes_dogs: true };
+/// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true });
 /// ```
 #[lang = "bitor_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"]
 pub trait BitOrAssign<Rhs=Self> {
-    /// The method for the `|=` operator
+    /// Performs the `|=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn bitor_assign(&mut self, rhs: Rhs);
 }
@@ -665,31 +647,31 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///
 /// # Examples
 ///
-/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up
-/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`.
-///
 /// ```
 /// use std::ops::BitXorAssign;
 ///
-/// struct Foo;
+/// #[derive(Debug, PartialEq)]
+/// struct Personality {
+///     has_soul: bool,
+///     likes_knitting: bool,
+/// }
 ///
-/// impl BitXorAssign for Foo {
-///     fn bitxor_assign(&mut self, _rhs: Foo) {
-///         println!("Bitwise Xor-ing!");
+/// impl BitXorAssign for Personality {
+///     fn bitxor_assign(&mut self, rhs: Self) {
+///         self.has_soul ^= rhs.has_soul;
+///         self.likes_knitting ^= rhs.likes_knitting;
 ///     }
 /// }
 ///
-/// # #[allow(unused_assignments)]
-/// fn main() {
-///     let mut foo = Foo;
-///     foo ^= Foo;
-/// }
+/// let mut personality = Personality { has_soul: false, likes_knitting: true };
+/// personality ^= Personality { has_soul: true, likes_knitting: true };
+/// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false});
 /// ```
 #[lang = "bitxor_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"]
 pub trait BitXorAssign<Rhs=Self> {
-    /// The method for the `^=` operator
+    /// Performs the `^=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn bitxor_assign(&mut self, rhs: Rhs);
 }
@@ -710,31 +692,29 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///
 /// # Examples
 ///
-/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up
-/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`.
+/// An implementation of `ShlAssign` for a wrapper around `usize`.
 ///
 /// ```
 /// use std::ops::ShlAssign;
 ///
-/// struct Foo;
+/// #[derive(Debug, PartialEq)]
+/// struct Scalar(usize);
 ///
-/// impl ShlAssign<Foo> for Foo {
-///     fn shl_assign(&mut self, _rhs: Foo) {
-///         println!("Shifting left!");
+/// impl ShlAssign<usize> for Scalar {
+///     fn shl_assign(&mut self, rhs: usize) {
+///         self.0 <<= rhs;
 ///     }
 /// }
 ///
-/// # #[allow(unused_assignments)]
-/// fn main() {
-///     let mut foo = Foo;
-///     foo <<= Foo;
-/// }
+/// let mut scalar = Scalar(4);
+/// scalar <<= 2;
+/// assert_eq!(scalar, Scalar(16));
 /// ```
 #[lang = "shl_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"]
 pub trait ShlAssign<Rhs> {
-    /// The method for the `<<=` operator
+    /// Performs the `<<=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn shl_assign(&mut self, rhs: Rhs);
 }
@@ -776,31 +756,29 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 ///
 /// # Examples
 ///
-/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up
-/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`.
+/// An implementation of `ShrAssign` for a wrapper around `usize`.
 ///
 /// ```
 /// use std::ops::ShrAssign;
 ///
-/// struct Foo;
+/// #[derive(Debug, PartialEq)]
+/// struct Scalar(usize);
 ///
-/// impl ShrAssign<Foo> for Foo {
-///     fn shr_assign(&mut self, _rhs: Foo) {
-///         println!("Shifting right!");
+/// impl ShrAssign<usize> for Scalar {
+///     fn shr_assign(&mut self, rhs: usize) {
+///         self.0 >>= rhs;
 ///     }
 /// }
 ///
-/// # #[allow(unused_assignments)]
-/// fn main() {
-///     let mut foo = Foo;
-///     foo >>= Foo;
-/// }
+/// let mut scalar = Scalar(16);
+/// scalar >>= 2;
+/// assert_eq!(scalar, Scalar(4));
 /// ```
 #[lang = "shr_assign"]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"]
 pub trait ShrAssign<Rhs=Self> {
-    /// The method for the `>>=` operator
+    /// Performs the `>>=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn shr_assign(&mut self, rhs: Rhs);
 }
diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs
index 18cf20ac411..a2e7c44cb24 100644
--- a/src/libcore/ops/deref.rs
+++ b/src/libcore/ops/deref.rs
@@ -8,16 +8,44 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/// The `Deref` trait is used to specify the functionality of dereferencing
-/// operations, like `*v`.
+/// Used for immutable dereferencing operations, like `*v`.
 ///
-/// `Deref` also enables ['`Deref` coercions'][coercions].
+/// In addition to being used for explicit dereferencing operations with the
+/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
+/// by the compiler in many circumstances. This mechanism is called
+/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
 ///
-/// [coercions]: ../../book/first-edition/deref-coercions.html
+/// Implementing `Deref` for smart pointers makes accessing the data behind them
+/// convenient, which is why they implement `Deref`. On the other hand, the
+/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
+/// accomodate smart pointers. Because of this, **`Deref` should only be
+/// implemented for smart pointers** to avoid confusion.
+///
+/// For similar reasons, **this trait should never fail**. Failure during
+/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
+///
+/// # More on `Deref` coercion
+///
+/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
+/// * In immutable contexts, `*x` on non-pointer types is equivalent to
+///   `*Deref::deref(&x)`.
+/// * Values of type `&T` are coerced to values of type `&U`
+/// * `T` implicitly implements all the (immutable) methods of the type `U`.
+///
+/// For more details, visit [the chapter in *The Rust Programming Language*]
+/// [book] as well as the reference sections on [the dereference operator]
+/// [ref-deref-op], [the `Deref` trait][ref-deref-trait], and [type coercions].
+///
+/// [book]: ../../book/second-edition/ch15-02-deref.html
+/// [`DerefMut`]: trait.DerefMut.html
+/// [more]: #more-on-deref-coercion
+/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator
+/// [ref-deref-trait]: ../../reference/the-deref-trait.html
+/// [type coercions]: ../../reference/type-coercions.html
 ///
 /// # Examples
 ///
-/// A struct with a single field which is accessible via dereferencing the
+/// A struct with a single field which is accessible by dereferencing the
 /// struct.
 ///
 /// ```
@@ -35,19 +63,17 @@
 ///     }
 /// }
 ///
-/// fn main() {
-///     let x = DerefExample { value: 'a' };
-///     assert_eq!('a', *x);
-/// }
+/// let x = DerefExample { value: 'a' };
+/// assert_eq!('a', *x);
 /// ```
 #[lang = "deref"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Deref {
-    /// The resulting type after dereferencing
+    /// The resulting type after dereferencing.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Target: ?Sized;
 
-    /// The method called to dereference a value
+    /// Dereferences the value.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn deref(&self) -> &Self::Target;
 }
@@ -66,16 +92,46 @@ impl<'a, T: ?Sized> Deref for &'a mut T {
     fn deref(&self) -> &T { *self }
 }
 
-/// The `DerefMut` trait is used to specify the functionality of dereferencing
-/// mutably like `*v = 1;`
-///
-/// `DerefMut` also enables ['`Deref` coercions'][coercions].
-///
-/// [coercions]: ../../book/first-edition/deref-coercions.html
+/// Used for mutable dereferencing operations, like in `*v = 1;`.
+///
+/// In addition to being used for explicit dereferencing operations with the
+/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
+/// by the compiler in many circumstances. This mechanism is called
+/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
+///
+/// Implementing `DerefMut` for smart pointers makes mutating the data behind
+/// them convenient, which is why they implement `DerefMut`. On the other hand,
+/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
+/// accomodate smart pointers. Because of this, **`DerefMut` should only be
+/// implemented for smart pointers** to avoid confusion.
+///
+/// For similar reasons, **this trait should never fail**. Failure during
+/// dereferencing can be extremely confusing when `DerefMut` is invoked
+/// implicitly.
+///
+/// # More on `Deref` coercion
+///
+/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
+/// then:
+/// * In mutable contexts, `*x` on non-pointer types is equivalent to
+///   `*Deref::deref(&x)`.
+/// * Values of type `&mut T` are coerced to values of type `&mut U`
+/// * `T` implicitly implements all the (mutable) methods of the type `U`.
+///
+/// For more details, visit [the chapter in *The Rust Programming Language*]
+/// [book] as well as the reference sections on [the dereference operator]
+/// [ref-deref-op], [the `Deref` trait][ref-deref-trait], and [type coercions].
+///
+/// [book]: ../../book/second-edition/ch15-02-deref.html
+/// [`Deref`]: trait.Deref.html
+/// [more]: #more-on-deref-coercion
+/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator
+/// [ref-deref-trait]: ../../reference/the-deref-trait.html
+/// [type coercions]: ../../reference/type-coercions.html
 ///
 /// # Examples
 ///
-/// A struct with a single field which is modifiable via dereferencing the
+/// A struct with a single field which is modifiable by dereferencing the
 /// struct.
 ///
 /// ```
@@ -99,16 +155,14 @@ impl<'a, T: ?Sized> Deref for &'a mut T {
 ///     }
 /// }
 ///
-/// fn main() {
-///     let mut x = DerefMutExample { value: 'a' };
-///     *x = 'b';
-///     assert_eq!('b', *x);
-/// }
+/// let mut x = DerefMutExample { value: 'a' };
+/// *x = 'b';
+/// assert_eq!('b', *x);
 /// ```
 #[lang = "deref_mut"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait DerefMut: Deref {
-    /// The method called to mutably dereference a value
+    /// Mutably dereferences the value.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn deref_mut(&mut self) -> &mut Self::Target;
 }
diff --git a/src/libcore/ops/drop.rs b/src/libcore/ops/drop.rs
index 92f3cb256c8..70ab7b2f3b7 100644
--- a/src/libcore/ops/drop.rs
+++ b/src/libcore/ops/drop.rs
@@ -8,20 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/// The `Drop` trait is used to run some code when a value goes out of scope.
+/// Used to run some code when a value goes out of scope.
 /// This is sometimes called a 'destructor'.
 ///
-/// When a value goes out of scope, if it implements this trait, it will have
-/// its `drop` method called. Then any fields the value contains will also
+/// When a value goes out of scope, it will have its `drop` method called if
+/// its type implements `Drop`. Then, any fields the value contains will also
 /// be dropped recursively.
 ///
-/// Because of the recursive dropping, you do not need to implement this trait
+/// Because of this recursive dropping, you do not need to implement this trait
 /// unless your type needs its own destructor logic.
 ///
+/// Refer to [the chapter on `Drop` in *The Rust Programming Language*][book]
+/// for some more elaboration.
+///
+/// [book]: ../../book/second-edition/ch15-03-drop.html
+///
 /// # Examples
 ///
-/// A trivial implementation of `Drop`. The `drop` method is called when `_x`
-/// goes out of scope, and therefore `main` prints `Dropping!`.
+/// ## Implementing `Drop`
+///
+/// The `drop` method is called when `_x` goes out of scope, and therefore
+/// `main` prints `Dropping!`.
 ///
 /// ```
 /// struct HasDrop;
@@ -37,9 +44,11 @@
 /// }
 /// ```
 ///
-/// Showing the recursive nature of `Drop`. When `outer` goes out of scope, the
-/// `drop` method will be called first for `Outer`, then for `Inner`. Therefore
-/// `main` prints `Dropping Outer!` and then `Dropping Inner!`.
+/// ## Dropping is done recursively
+///
+/// When `outer` goes out of scope, the `drop` method will be called first for
+/// `Outer`, then for `Inner`. Therefore, `main` prints `Dropping Outer!` and
+/// then `Dropping Inner!`.
 ///
 /// ```
 /// struct Inner;
@@ -62,12 +71,20 @@
 /// }
 /// ```
 ///
-/// Because variables are dropped in the reverse order they are declared,
-/// `main` will print `Declared second!` and then `Declared first!`.
+/// ## Variables are dropped in reverse order of declaration
+///
+/// `_first` is declared first and `_second` is declared second, so `main` will
+/// print `Declared second!` and then `Declared first!`.
 ///
 /// ```
 /// struct PrintOnDrop(&'static str);
 ///
+/// impl Drop for PrintOnDrop {
+///     fn drop(&mut self) {
+///         println!("{}", self.0);
+///     }
+/// }
+///
 /// fn main() {
 ///     let _first = PrintOnDrop("Declared first!");
 ///     let _second = PrintOnDrop("Declared second!");
@@ -76,24 +93,25 @@
 #[lang = "drop"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Drop {
-    /// A method called when the value goes out of scope.
+    /// Executes the destructor for this type.
+    ///
+    /// This method is called implilcitly when the value goes out of scope,
+    /// and cannot be called explicitly (this is compiler error [E0040]).
+    /// However, the [`std::mem::drop`] function in the prelude can be
+    /// used to call the argument's `Drop` implementation.
     ///
     /// When this method has been called, `self` has not yet been deallocated.
-    /// If it were, `self` would be a dangling reference.
+    /// That only happens after the method is over.
+    /// If this wasn't the case, `self` would be a dangling reference.
     ///
-    /// After this function is over, the memory of `self` will be deallocated.
+    /// # Panics
     ///
-    /// This function cannot be called explicitly. This is compiler error
-    /// [E0040]. However, the [`std::mem::drop`] function in the prelude can be
-    /// used to call the argument's `Drop` implementation.
+    /// Given that a [`panic!`] will call `drop` as it unwinds, any [`panic!`]
+    /// in a `drop` implementation will likely abort.
     ///
     /// [E0040]: ../../error-index.html#E0040
+    /// [`panic!`]: ../macro.panic.html
     /// [`std::mem::drop`]: ../../std/mem/fn.drop.html
-    ///
-    /// # Panics
-    ///
-    /// Given that a `panic!` will call `drop()` as it unwinds, any `panic!` in
-    /// a `drop()` implementation will likely abort.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn drop(&mut self);
 }
diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs
index c5b3fbca1a6..d10fcb86b24 100644
--- a/src/libcore/ops/function.rs
+++ b/src/libcore/ops/function.rs
@@ -8,26 +8,51 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/// A version of the call operator that takes an immutable receiver.
+/// The version of the call operator that takes an immutable receiver.
 ///
-/// # Examples
+/// Instances of `Fn` can be called repeatedly without mutating state.
+///
+/// *This trait (`Fn`) is not to be confused with [function pointers][]
+/// (`fn`).*
+///
+/// `Fn` is implemented automatically by closures which only take immutable
+/// references to captured variables or don't capture anything at all, as well
+/// as (safe) [function pointers][] (with some caveats, see their documentation
+/// for more details). Additionally, for any type `F` that implements `Fn`, `&F`
+/// implements `Fn`, too.
+///
+/// Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any
+/// instance of `Fn` can be used as a parameter where a [`FnMut`] or [`FnOnce`]
+/// is expected.
 ///
-/// Closures automatically implement this trait, which allows them to be
-/// invoked. Note, however, that `Fn` takes an immutable reference to any
-/// captured variables. To take a mutable capture, implement [`FnMut`], and to
-/// consume the capture, implement [`FnOnce`].
+/// Use `Fn` as a bound when you want to accept a parameter of function-like
+/// type and need to call it repeatedly and without mutating state (e.g. when
+/// calling it concurrently). If you do not need such strict requirements, use
+/// [`FnMut`] or [`FnOnce`] as bounds.
 ///
+/// See the [chapter on closures in *The Rust Programming Language*][book] for
+/// some more information on this topic.
+///
+/// Also of note is the special syntax for `Fn` traits (e.g.
+/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
+/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
+///
+/// [book]: ../../book/second-edition/ch13-01-closures.html
 /// [`FnMut`]: trait.FnMut.html
 /// [`FnOnce`]: trait.FnOnce.html
+/// [function pointers]: ../../std/primitive.fn.html
+/// [nomicon]: ../../nomicon/hrtb.html
+///
+/// # Examples
+///
+/// ## Calling a closure
 ///
 /// ```
 /// let square = |x| x * x;
 /// assert_eq!(square(5), 25);
 /// ```
 ///
-/// Closures can also be passed to higher-level functions through a `Fn`
-/// parameter (or a `FnMut` or `FnOnce` parameter, which are supertraits of
-/// `Fn`).
+/// ## Using a `Fn` parameter
 ///
 /// ```
 /// fn call_with_one<F>(func: F) -> usize
@@ -43,17 +68,46 @@
 #[rustc_paren_sugar]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 pub trait Fn<Args> : FnMut<Args> {
-    /// This is called when the call operator is used.
+    /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
 }
 
-/// A version of the call operator that takes a mutable receiver.
+/// The version of the call operator that takes a mutable receiver.
+///
+/// Instances of `FnMut` can be called repeatedly and may mutate state.
+///
+/// `FnMut` is implemented automatically by closures which take mutable
+/// references to captured variables, as well as all types that implement
+/// [`Fn`], e.g. (safe) [function pointers][] (since `FnMut` is a supertrait of
+/// [`Fn`]). Additionally, for any type `F` that implements `FnMut`, `&mut F`
+/// implements `FnMut`, too.
+///
+/// Since [`FnOnce`] is a supertrait of `FnMut`, any instance of `FnMut` can be
+/// used where a [`FnOnce`] is expected, and since [`Fn`] is a subtrait of
+/// `FnMut`, any instance of [`Fn`] can be used where `FnMut` is expected.
+///
+/// Use `FnMut` as a bound when you want to accept a parameter of function-like
+/// type and need to call it repeatedly, while allowing it to mutate state.
+/// If you don't want the parameter to mutate state, use [`Fn`] as a
+/// bound; if you don't need to call it repeatedly, use [`FnOnce`].
+///
+/// See the [chapter on closures in *The Rust Programming Language*][book] for
+/// some more information on this topic.
+///
+/// Also of note is the special syntax for `Fn` traits (e.g.
+/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
+/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
+///
+/// [book]: ../../book/second-edition/ch13-01-closures.html
+/// [`Fn`]: trait.Fn.html
+/// [`FnOnce`]: trait.FnOnce.html
+/// [function pointers]: ../../std/primitive.fn.html
+/// [nomicon]: ../../nomicon/hrtb.html
 ///
 /// # Examples
 ///
-/// Closures that mutably capture variables automatically implement this trait,
-/// which allows them to be invoked.
+/// ## Calling a mutably capturing closure
 ///
 /// ```
 /// let mut x = 5;
@@ -64,8 +118,7 @@ pub trait Fn<Args> : FnMut<Args> {
 /// assert_eq!(x, 25);
 /// ```
 ///
-/// Closures can also be passed to higher-level functions through a `FnMut`
-/// parameter (or a `FnOnce` parameter, which is a supertrait of `FnMut`).
+/// ## Using a `FnMut` parameter
 ///
 /// ```
 /// fn do_twice<F>(mut func: F)
@@ -88,17 +141,45 @@ pub trait Fn<Args> : FnMut<Args> {
 #[rustc_paren_sugar]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 pub trait FnMut<Args> : FnOnce<Args> {
-    /// This is called when the call operator is used.
+    /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
 }
 
-/// A version of the call operator that takes a by-value receiver.
+/// The version of the call operator that takes a by-value receiver.
+///
+/// Instances of `FnOnce` can be called, but might not be callable multiple
+/// times. Because of this, if the only thing known about a type is that it
+/// implements `FnOnce`, it can only be called once.
+///
+/// `FnOnce` is implemented automatically by closure that might consume captured
+/// variables, as well as all types that implement [`FnMut`], e.g. (safe)
+/// [function pointers][] (since `FnOnce` is a supertrait of [`FnMut`]).
+///
+/// Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any instance of
+/// [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected.
+///
+/// Use `FnOnce` as a bound when you want to accept a parameter of function-like
+/// type and only need to call it once. If you need to call the parameter
+/// repeatedly, use [`FnMut`] as a bound; if you also need it to not mutate
+/// state, use [`Fn`].
+///
+/// See the [chapter on closures in *The Rust Programming Language*][book] for
+/// some more information on this topic.
+///
+/// Also of note is the special syntax for `Fn` traits (e.g.
+/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
+/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
+///
+/// [book]: ../../book/second-edition/ch13-01-closures.html
+/// [`Fn`]: trait.Fn.html
+/// [`FnMut`]: trait.FnMut.html
+/// [function pointers]: ../../std/primitive.fn.html
+/// [nomicon]: ../../nomicon/hrtb.html
 ///
 /// # Examples
 ///
-/// By-value closures automatically implement this trait, which allows them to
-/// be invoked.
+/// ## Calling a by-value closure
 ///
 /// ```
 /// let x = 5;
@@ -106,21 +187,20 @@ pub trait FnMut<Args> : FnOnce<Args> {
 /// assert_eq!(square_x(), 25);
 /// ```
 ///
-/// By-value Closures can also be passed to higher-level functions through a
-/// `FnOnce` parameter.
+/// ## Using a `FnOnce` parameter
 ///
 /// ```
 /// fn consume_with_relish<F>(func: F)
 ///     where F: FnOnce() -> String
 /// {
 ///     // `func` consumes its captured variables, so it cannot be run more
-///     // than once
+///     // than once.
 ///     println!("Consumed: {}", func());
 ///
 ///     println!("Delicious!");
 ///
 ///     // Attempting to invoke `func()` again will throw a `use of moved
-///     // value` error for `func`
+///     // value` error for `func`.
 /// }
 ///
 /// let x = String::from("x");
@@ -138,7 +218,7 @@ pub trait FnOnce<Args> {
     #[stable(feature = "fn_once_output", since = "1.12.0")]
     type Output;
 
-    /// This is called when the call operator is used.
+    /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 }
diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs
index b16b9567787..d65c0aba504 100644
--- a/src/libcore/ops/index.rs
+++ b/src/libcore/ops/index.rs
@@ -8,13 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/// The `Index` trait is used to specify the functionality of indexing operations
-/// like `container[index]` when used in an immutable context.
+/// Used for indexing operations (`container[index]`) in immutable contexts.
 ///
 /// `container[index]` is actually syntactic sugar for `*container.index(index)`,
 /// but only when used as an immutable value. If a mutable value is requested,
 /// [`IndexMut`] is used instead. This allows nice things such as
-/// `let value = v[index]` if `value` implements [`Copy`].
+/// `let value = v[index]` if the type of `value` implements [`Copy`].
 ///
 /// [`IndexMut`]: ../../std/ops/trait.IndexMut.html
 /// [`Copy`]: ../../std/marker/trait.Copy.html
@@ -64,25 +63,23 @@
 #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Index<Idx: ?Sized> {
-    /// The returned type after indexing
+    /// The returned type after indexing.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output: ?Sized;
 
-    /// The method for the indexing (`container[index]`) operation
+    /// Performs the indexing (`container[index]`) operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn index(&self, index: Idx) -> &Self::Output;
 }
 
-/// The `IndexMut` trait is used to specify the functionality of indexing
-/// operations like `container[index]` when used in a mutable context.
+/// Used for indexing operations (`container[index]`) in mutable contexts.
 ///
 /// `container[index]` is actually syntactic sugar for
 /// `*container.index_mut(index)`, but only when used as a mutable value. If
 /// an immutable value is requested, the [`Index`] trait is used instead. This
-/// allows nice things such as `v[index] = value` if `value` implements [`Copy`].
+/// allows nice things such as `v[index] = value`.
 ///
 /// [`Index`]: ../../std/ops/trait.Index.html
-/// [`Copy`]: ../../std/marker/trait.Copy.html
 ///
 /// # Examples
 ///
@@ -106,7 +103,7 @@ pub trait Index<Idx: ?Sized> {
 ///
 /// struct Balance {
 ///     pub left: Weight,
-///     pub right:Weight,
+///     pub right: Weight,
 /// }
 ///
 /// impl Index<Side> for Balance {
@@ -131,28 +128,26 @@ pub trait Index<Idx: ?Sized> {
 ///     }
 /// }
 ///
-/// fn main() {
-///     let mut balance = Balance {
-///         right: Weight::Kilogram(2.5),
-///         left: Weight::Pound(1.5),
-///     };
-///
-///     // In this case balance[Side::Right] is sugar for
-///     // *balance.index(Side::Right), since we are only reading
-///     // balance[Side::Right], not writing it.
-///     assert_eq!(balance[Side::Right],Weight::Kilogram(2.5));
-///
-///     // However in this case balance[Side::Left] is sugar for
-///     // *balance.index_mut(Side::Left), since we are writing
-///     // balance[Side::Left].
-///     balance[Side::Left] = Weight::Kilogram(3.0);
-/// }
+/// let mut balance = Balance {
+///     right: Weight::Kilogram(2.5),
+///     left: Weight::Pound(1.5),
+/// };
+///
+/// // In this case, `balance[Side::Right]` is sugar for
+/// // `*balance.index(Side::Right)`, since we are only *reading*
+/// // `balance[Side::Right]`, not writing it.
+/// assert_eq!(balance[Side::Right], Weight::Kilogram(2.5));
+///
+/// // However, in this case `balance[Side::Left]` is sugar for
+/// // `*balance.index_mut(Side::Left)`, since we are writing
+/// // `balance[Side::Left]`.
+/// balance[Side::Left] = Weight::Kilogram(3.0);
 /// ```
 #[lang = "index_mut"]
 #[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
-    /// The method for the mutable indexing (`container[index]`) operation
+    /// Performs the mutable indexing (`container[index]`) operation.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
 }
diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs
index a78f4fe28a6..b5e6912b10d 100644
--- a/src/libcore/ops/mod.rs
+++ b/src/libcore/ops/mod.rs
@@ -21,6 +21,12 @@
 //! custom operators are required, you should look toward macros or compiler
 //! plugins to extend Rust's syntax.
 //!
+//! Implementations of operator traits should be unsurprising in their
+//! respective contexts, keeping in mind their usual meanings and
+//! [operator precedence]. For example, when implementing [`Mul`], the operation
+//! should have some resemblance to multiplication (and share expected
+//! properties like associativity).
+//!
 //! Note that the `&&` and `||` operators short-circuit, i.e. they only
 //! evaluate their second operand if it contributes to the result. Since this
 //! behavior is not enforceable by traits, `&&` and `||` are not supported as
@@ -46,7 +52,7 @@
 //! ```rust
 //! use std::ops::{Add, Sub};
 //!
-//! #[derive(Debug)]
+//! #[derive(Debug, PartialEq)]
 //! struct Point {
 //!     x: i32,
 //!     y: i32,
@@ -67,10 +73,9 @@
 //!         Point {x: self.x - other.x, y: self.y - other.y}
 //!     }
 //! }
-//! fn main() {
-//!     println!("{:?}", Point {x: 1, y: 0} + Point {x: 2, y: 3});
-//!     println!("{:?}", Point {x: 1, y: 0} - Point {x: 2, y: 3});
-//! }
+//!
+//! assert_eq!(Point {x: 3, y: 3}, Point {x: 1, y: 0} + Point {x: 2, y: 3});
+//! assert_eq!(Point {x: -1, y: -3}, Point {x: 1, y: 0} - Point {x: 2, y: 3});
 //! ```
 //!
 //! See the documentation for each trait for an example implementation.
@@ -143,7 +148,9 @@
 //! [`FnOnce`]: trait.FnOnce.html
 //! [`Add`]: trait.Add.html
 //! [`Sub`]: trait.Sub.html
+//! [`Mul`]: trait.Mul.html
 //! [`clone`]: ../clone/trait.Clone.html#tymethod.clone
+//! [operator precedence]: ../../reference/expressions.html#operator-precedence
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index 33258b7a875..463a50491a8 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -10,10 +10,10 @@
 
 use fmt;
 
-/// An unbounded range. Use `..` (two dots) for its shorthand.
+/// An unbounded range (`..`).
 ///
-/// Its primary use case is slicing index. It cannot serve as an iterator
-/// because it doesn't have a starting point.
+/// `RangeFull` is primarily used as a [slicing index], its shorthand is `..`.
+/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
 ///
 /// # Examples
 ///
@@ -23,8 +23,8 @@ use fmt;
 /// assert_eq!((..), std::ops::RangeFull);
 /// ```
 ///
-/// It does not have an `IntoIterator` implementation, so you can't use it in a
-/// `for` loop directly. This won't compile:
+/// It does not have an [`IntoIterator`] implementation, so you can't use it in
+/// a `for` loop directly. This won't compile:
 ///
 /// ```compile_fail,E0277
 /// for i in .. {
@@ -32,7 +32,7 @@ use fmt;
 /// }
 /// ```
 ///
-/// Used as a slicing index, `RangeFull` produces the full array as a slice.
+/// Used as a [slicing index], `RangeFull` produces the full array as a slice.
 ///
 /// ```
 /// let arr = [0, 1, 2, 3];
@@ -41,6 +41,10 @@ use fmt;
 /// assert_eq!(arr[1.. ], [  1,2,3]);
 /// assert_eq!(arr[1..3], [  1,2  ]);
 /// ```
+///
+/// [`IntoIterator`]: ../iter/trait.Iterator.html
+/// [`Iterator`]: ../iter/trait.IntoIterator.html
+/// [slicing index]: ../slice/trait.SliceIndex.html
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFull;
@@ -52,24 +56,23 @@ impl fmt::Debug for RangeFull {
     }
 }
 
-/// A (half-open) range which is bounded at both ends: { x | start <= x < end }.
-/// Use `start..end` (two dots) for its shorthand.
+/// A (half-open) range bounded inclusively below and exclusively above
+/// (`start..end`).
 ///
-/// See the [`contains`](#method.contains) method for its characterization.
+/// The `Range` `start..end` contains all values with `x >= start` and
+/// `x < end`.
 ///
 /// # Examples
 ///
 /// ```
-/// fn main() {
-///     assert_eq!((3..5), std::ops::Range{ start: 3, end: 5 });
-///     assert_eq!(3+4+5, (3..6).sum());
-///
-///     let arr = [0, 1, 2, 3];
-///     assert_eq!(arr[ .. ], [0,1,2,3]);
-///     assert_eq!(arr[ ..3], [0,1,2  ]);
-///     assert_eq!(arr[1.. ], [  1,2,3]);
-///     assert_eq!(arr[1..3], [  1,2  ]);  // Range
-/// }
+/// assert_eq!((3..5), std::ops::Range { start: 3, end: 5 });
+/// assert_eq!(3 + 4 + 5, (3..6).sum());
+///
+/// let arr = [0, 1, 2, 3];
+/// assert_eq!(arr[ .. ], [0,1,2,3]);
+/// assert_eq!(arr[ ..3], [0,1,2  ]);
+/// assert_eq!(arr[1.. ], [  1,2,3]);
+/// assert_eq!(arr[1..3], [  1,2  ]);  // Range
 /// ```
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -91,49 +94,49 @@ impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
 
 #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
 impl<Idx: PartialOrd<Idx>> Range<Idx> {
+    /// Returns `true` if `item` is contained in the range.
+    ///
     /// # Examples
     ///
     /// ```
     /// #![feature(range_contains)]
-    /// fn main() {
-    ///     assert!( ! (3..5).contains(2));
-    ///     assert!(   (3..5).contains(3));
-    ///     assert!(   (3..5).contains(4));
-    ///     assert!( ! (3..5).contains(5));
     ///
-    ///     assert!( ! (3..3).contains(3));
-    ///     assert!( ! (3..2).contains(3));
-    /// }
+    /// assert!(!(3..5).contains(2));
+    /// assert!( (3..5).contains(3));
+    /// assert!( (3..5).contains(4));
+    /// assert!(!(3..5).contains(5));
+    ///
+    /// assert!(!(3..3).contains(3));
+    /// assert!(!(3..2).contains(3));
     /// ```
     pub fn contains(&self, item: Idx) -> bool {
         (self.start <= item) && (item < self.end)
     }
 }
 
-/// A range which is only bounded below: { x | start <= x }.
-/// Use `start..` for its shorthand.
+/// A range only bounded inclusively below (`start..`).
 ///
-/// See the [`contains`](#method.contains) method for its characterization.
+/// The `RangeFrom` `start..` contains all values with `x >= start`.
 ///
-/// Note: Currently, no overflow checking is done for the iterator
+/// *Note*: Currently, no overflow checking is done for the [`Iterator`]
 /// implementation; if you use an integer range and the integer overflows, it
-/// might panic in debug mode or create an endless loop in release mode. This
-/// overflow behavior might change in the future.
+/// might panic in debug mode or create an endless loop in release mode. **This
+/// overflow behavior might change in the future.**
 ///
 /// # Examples
 ///
 /// ```
-/// fn main() {
-///     assert_eq!((2..), std::ops::RangeFrom{ start: 2 });
-///     assert_eq!(2+3+4, (2..).take(3).sum());
-///
-///     let arr = [0, 1, 2, 3];
-///     assert_eq!(arr[ .. ], [0,1,2,3]);
-///     assert_eq!(arr[ ..3], [0,1,2  ]);
-///     assert_eq!(arr[1.. ], [  1,2,3]);  // RangeFrom
-///     assert_eq!(arr[1..3], [  1,2  ]);
-/// }
+/// assert_eq!((2..), std::ops::RangeFrom { start: 2 });
+/// assert_eq!(2 + 3 + 4, (2..).take(3).sum());
+///
+/// let arr = [0, 1, 2, 3];
+/// assert_eq!(arr[ .. ], [0,1,2,3]);
+/// assert_eq!(arr[ ..3], [0,1,2  ]);
+/// assert_eq!(arr[1.. ], [  1,2,3]);  // RangeFrom
+/// assert_eq!(arr[1..3], [  1,2  ]);
 /// ```
+///
+/// [`Iterator`]: ../iter/trait.IntoIterator.html
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFrom<Idx> {
@@ -151,46 +154,47 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
 
 #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
 impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
+    /// Returns `true` if `item` is contained in the range.
+    ///
     /// # Examples
     ///
     /// ```
     /// #![feature(range_contains)]
-    /// fn main() {
-    ///     assert!( ! (3..).contains(2));
-    ///     assert!(   (3..).contains(3));
-    ///     assert!(   (3..).contains(1_000_000_000));
-    /// }
+    ///
+    /// assert!(!(3..).contains(2));
+    /// assert!( (3..).contains(3));
+    /// assert!( (3..).contains(1_000_000_000));
     /// ```
     pub fn contains(&self, item: Idx) -> bool {
         (self.start <= item)
     }
 }
 
-/// A range which is only bounded above: { x | x < end }.
-/// Use `..end` (two dots) for its shorthand.
-///
-/// See the [`contains`](#method.contains) method for its characterization.
+/// A range only bounded exclusively above (`..end`).
 ///
-/// It cannot serve as an iterator because it doesn't have a starting point.
+/// The `RangeTo` `..end` contains all values with `x < end`.
+/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
 ///
 /// # Examples
 ///
-/// The `..{integer}` syntax is a `RangeTo`:
+/// The `..end` syntax is a `RangeTo`:
 ///
 /// ```
-/// assert_eq!((..5), std::ops::RangeTo{ end: 5 });
+/// assert_eq!((..5), std::ops::RangeTo { end: 5 });
 /// ```
 ///
-/// It does not have an `IntoIterator` implementation, so you can't use it in a
-/// `for` loop directly. This won't compile:
+/// It does not have an [`IntoIterator`] implementation, so you can't use it in
+/// a `for` loop directly. This won't compile:
 ///
 /// ```compile_fail,E0277
+/// // error[E0277]: the trait bound `std::ops::RangeTo<{integer}>:
+/// // std::iter::Iterator` is not satisfied
 /// for i in ..5 {
 ///     // ...
 /// }
 /// ```
 ///
-/// When used as a slicing index, `RangeTo` produces a slice of all array
+/// When used as a [slicing index], `RangeTo` produces a slice of all array
 /// elements before the index indicated by `end`.
 ///
 /// ```
@@ -200,6 +204,10 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
 /// assert_eq!(arr[1.. ], [  1,2,3]);
 /// assert_eq!(arr[1..3], [  1,2  ]);
 /// ```
+///
+/// [`IntoIterator`]: ../iter/trait.Iterator.html
+/// [`Iterator`]: ../iter/trait.IntoIterator.html
+/// [slicing index]: ../slice/trait.SliceIndex.html
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeTo<Idx> {
@@ -217,38 +225,38 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
 
 #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
 impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
+    /// Returns `true` if `item` is contained in the range.
+    ///
     /// # Examples
     ///
     /// ```
     /// #![feature(range_contains)]
-    /// fn main() {
-    ///     assert!(   (..5).contains(-1_000_000_000));
-    ///     assert!(   (..5).contains(4));
-    ///     assert!( ! (..5).contains(5));
-    /// }
+    ///
+    /// assert!( (..5).contains(-1_000_000_000));
+    /// assert!( (..5).contains(4));
+    /// assert!(!(..5).contains(5));
     /// ```
     pub fn contains(&self, item: Idx) -> bool {
         (item < self.end)
     }
 }
 
-/// An inclusive range which is bounded at both ends: { x | start <= x <= end }.
-/// Use `start...end` (three dots) for its shorthand.
+/// An range bounded inclusively below and above (`start...end`).
 ///
-/// See the [`contains`](#method.contains) method for its characterization.
+/// The `RangeInclusive` `start...end` contains all values with `x >= start`
+/// and `x <= end`.
 ///
 /// # Examples
 ///
 /// ```
 /// #![feature(inclusive_range,inclusive_range_syntax)]
-/// fn main() {
-///     assert_eq!((3...5), std::ops::RangeInclusive{ start: 3, end: 5 });
-///     assert_eq!(3+4+5, (3...5).sum());
 ///
-///     let arr = [0, 1, 2, 3];
-///     assert_eq!(arr[ ...2], [0,1,2  ]);
-///     assert_eq!(arr[1...2], [  1,2  ]);  // RangeInclusive
-/// }
+/// assert_eq!((3...5), std::ops::RangeInclusive { start: 3, end: 5 });
+/// assert_eq!(3 + 4 + 5, (3...5).sum());
+///
+/// let arr = [0, 1, 2, 3];
+/// assert_eq!(arr[ ...2], [0,1,2  ]);
+/// assert_eq!(arr[1...2], [  1,2  ]);  // RangeInclusive
 /// ```
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
@@ -274,61 +282,68 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
 
 #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
 impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
+    /// Returns `true` if `item` is contained in the range.
+    ///
     /// # Examples
     ///
     /// ```
     /// #![feature(range_contains,inclusive_range_syntax)]
-    /// fn main() {
-    ///     assert!( ! (3...5).contains(2));
-    ///     assert!(   (3...5).contains(3));
-    ///     assert!(   (3...5).contains(4));
-    ///     assert!(   (3...5).contains(5));
-    ///     assert!( ! (3...5).contains(6));
     ///
-    ///     assert!(   (3...3).contains(3));
-    ///     assert!( ! (3...2).contains(3));
-    /// }
+    /// assert!(!(3...5).contains(2));
+    /// assert!( (3...5).contains(3));
+    /// assert!( (3...5).contains(4));
+    /// assert!( (3...5).contains(5));
+    /// assert!(!(3...5).contains(6));
+    ///
+    /// assert!( (3...3).contains(3));
+    /// assert!(!(3...2).contains(3));
     /// ```
     pub fn contains(&self, item: Idx) -> bool {
         self.start <= item && item <= self.end
     }
 }
 
-/// An inclusive range which is only bounded above: { x | x <= end }.
-/// Use `...end` (three dots) for its shorthand.
+/// A range only bounded inclusively above (`...end`).
 ///
-/// See the [`contains`](#method.contains) method for its characterization.
-///
-/// It cannot serve as an iterator because it doesn't have a starting point.
+/// The `RangeToInclusive` `...end` contains all values with `x <= end`.
+/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
 ///
 /// # Examples
 ///
-/// The `...{integer}` syntax is a `RangeToInclusive`:
+/// The `...end` syntax is a `RangeToInclusive`:
 ///
 /// ```
 /// #![feature(inclusive_range,inclusive_range_syntax)]
 /// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 });
 /// ```
 ///
-/// It does not have an `IntoIterator` implementation, so you can't use it in a
+/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
 /// `for` loop directly. This won't compile:
 ///
 /// ```compile_fail,E0277
 /// #![feature(inclusive_range_syntax)]
+///
+/// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>:
+/// // std::iter::Iterator` is not satisfied
 /// for i in ...5 {
 ///     // ...
 /// }
 /// ```
 ///
-/// When used as a slicing index, `RangeToInclusive` produces a slice of all
+/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
 /// array elements up to and including the index indicated by `end`.
 ///
 /// ```
 /// #![feature(inclusive_range_syntax)]
+///
 /// let arr = [0, 1, 2, 3];
 /// assert_eq!(arr[ ...2], [0,1,2  ]);  // RangeToInclusive
 /// assert_eq!(arr[1...2], [  1,2  ]);
 /// ```
+///
+/// [`IntoIterator`]: ../iter/trait.Iterator.html
+/// [`Iterator`]: ../iter/trait.IntoIterator.html
+/// [slicing index]: ../slice/trait.SliceIndex.html
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
 pub struct RangeToInclusive<Idx> {
@@ -348,15 +363,16 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
 
 #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
 impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
+    /// Returns `true` if `item` is contained in the range.
+    ///
     /// # Examples
     ///
     /// ```
     /// #![feature(range_contains,inclusive_range_syntax)]
-    /// fn main() {
-    ///     assert!(   (...5).contains(-1_000_000_000));
-    ///     assert!(   (...5).contains(5));
-    ///     assert!( ! (...5).contains(6));
-    /// }
+    ///
+    /// assert!( (...5).contains(-1_000_000_000));
+    /// assert!( (...5).contains(5));
+    /// assert!(!(...5).contains(6));
     /// ```
     pub fn contains(&self, item: Idx) -> bool {
         (item <= self.end)