From 63fc1faf8298d2bd4e9385a2e0286b2ee0db6866 Mon Sep 17 00:00:00 2001 From: lukaramu Date: Mon, 7 Aug 2017 00:52:51 +0200 Subject: [PATCH 1/9] Revise documentation in core::ops::arith Part of #29365. * Replaced examples for Mul-/Div-/RemAssign with more illustrative ones * Made summary senteces for the trait methods use third person singular * Moved some explanations from Examples section to main explanation * Switched around argument order for the vector-scalar multiplication example such that the vector is on the left side (as it would be expected if one were to switch from `*` to `*=`) * Replaced mostly redundant example introductions with headings in traits with more than one example (where it made sense) * Cleaned up some examples to derive `PartialEq` instead of implementing it manually when that wasn't needed * Removed explicit `fn main()`s in examples where they weren't necessary * Rephrased some things * Added some missing periods * Fixed some formatting/punctuation in examples --- src/libcore/ops/arith.rs | 300 +++++++++++++++------------------------ 1 file changed, 118 insertions(+), 182 deletions(-) diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs index d898f9146cd1a..97fd8651b047b 100644 --- a/src/libcore/ops/arith.rs +++ b/src/libcore/ops/arith.rs @@ -10,15 +10,20 @@ /// The addition operator `+`. /// +/// Note that `RHS = Self` by default, but this is not mandatory. For example, +/// [`std::time::SystemTime`] implements `Add`, 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 { /// x: T, /// y: T, /// } /// -/// // Notice that the implementation uses the `Output` associated type +/// // Notice that the implementation uses the associated type `Output`. /// impl> Add for Point { /// type Output = Point; /// @@ -71,32 +70,18 @@ /// } /// } /// -/// 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 }); /// ``` -/// -/// Note that `RHS = Self` by default, but this is not mandatory. For example, -/// [std::time::SystemTime] implements `Add`, 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 { - /// 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 = Self` by default, but this is not mandatory. For example, +/// [std::time::SystemTime] implements `Sub`, 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 { /// x: T, /// y: T, /// } /// -/// // Notice that the implementation uses the `Output` associated type +/// // Notice that the implementation uses the associated type `Output`. /// impl> Sub for Point { /// type Output = Point; /// @@ -181,32 +165,18 @@ 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: 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`, 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 { - /// 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 = 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}; +/// #[derive(Debug, PartialEq)] +/// struct Vector { value: Vec } /// -/// impl Mul for Scalar { +/// impl Mul for Vector { /// type Output = Vector; /// -/// fn mul(self, rhs: Vector) -> Vector { -/// Vector {value: rhs.value.iter().map(|v| self.value * v).collect()} -/// } -/// } -/// -/// impl PartialEq for Vector { -/// fn eq(&self, other: &Self) -> bool { -/// self.value == other.value +/// fn mul(self, rhs: Scalar) -> Vector { +/// Vector { value: self.value.iter().map(|v| v * rhs.value).collect() } /// } /// } /// -/// 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 { - /// 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 = 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}; +/// #[derive(Debug, PartialEq)] +/// struct Vector { value: Vec } /// /// impl Div for Vector { /// type Output = Vector; /// /// fn div(self, rhs: Scalar) -> Vector { -/// Vector {value: self.value.iter().map(|v| v / rhs.value).collect()} +/// Vector { value: self.value.iter().map(|v| v / rhs.value).collect() } /// } /// } /// -/// impl PartialEq for Vector { -/// fn eq(&self, other: &Self) -> bool { -/// self.value == other.value -/// } -/// } -/// -/// 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 { - /// 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; } @@ -526,7 +482,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 +490,11 @@ div_impl_float! { f32 f64 } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"] pub trait Rem { - /// 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 +563,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 +624,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 +639,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 +647,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 { - /// 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 +675,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 +690,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 +698,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 { - /// 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 +720,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 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 { - /// 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 +762,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 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 { - /// 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 +803,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 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 { - /// The method for the `%=` operator + /// Performs the `%=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn rem_assign(&mut self, rhs: Rhs); } From f2ff646f5f71fd89b19ec11d7bb03128156f1af9 Mon Sep 17 00:00:00 2001 From: lukaramu Date: Mon, 7 Aug 2017 13:49:11 +0200 Subject: [PATCH 2/9] Revise documentation in core::ops::bit Part of #29365. * Added "real" examples for `BitOrAssign`, `BitXorAssign`, `ShlAssign`, and `ShrAssign` * Rewrote method summary senteces to be in 3rd person singular * Rephrased example introductions to be less redundant ("in this example" etc.) and to not use "trivial" * Removed superfluous explicit `fn main()`s in examples * Added some missing periods --- src/libcore/ops/bit.rs | 272 ++++++++++++++++++----------------------- 1 file changed, 122 insertions(+), 150 deletions(-) diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs index 8743be3557cc4..e6fadf616b028 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; } @@ -70,7 +70,7 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// /// # 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 +87,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`. /// /// ``` /// use std::ops::BitAnd; @@ -114,22 +111,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 { - /// 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; } @@ -154,7 +149,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// /// # 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 +166,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`. /// /// ``` /// use std::ops::BitOr; @@ -198,22 +190,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 { - /// 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; } @@ -238,7 +228,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// /// # 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 +245,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`. /// /// ``` /// use std::ops::BitXor; @@ -285,22 +272,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 { - /// 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 +311,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 +327,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 +345,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 { -/// // 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 = vec![]; /// spun_vector.extend_from_slice(b); @@ -370,20 +354,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 { - /// 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 +412,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 +428,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 +446,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 { -/// // 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 = vec![]; /// spun_vector.extend_from_slice(b); @@ -474,20 +455,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 { - /// 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 +512,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 +528,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`. /// /// ``` /// use std::ops::BitAndAssign; @@ -577,7 +555,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } /// struct BooleanVector(Vec); /// /// 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 +566,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 { - /// 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 +596,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 { - /// 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 +641,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 { - /// 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 +686,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 for Foo { -/// fn shl_assign(&mut self, _rhs: Foo) { -/// println!("Shifting left!"); +/// impl ShlAssign 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 { - /// 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 +750,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 for Foo { -/// fn shr_assign(&mut self, _rhs: Foo) { -/// println!("Shifting right!"); +/// impl ShrAssign 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 { - /// The method for the `>>=` operator + /// Performs the `>>=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn shr_assign(&mut self, rhs: Rhs); } From 5990be523d00edaf69cfd6d3e28d9fb78eb67bcd Mon Sep 17 00:00:00 2001 From: lukaramu Date: Mon, 7 Aug 2017 17:09:43 +0200 Subject: [PATCH 3/9] Expand docs on `Deref` and `DerefMut` Part of #29365. * Expanded the explanaition sections, adapting some parts from the book, the reference, as well as the API guidelines. As such, the docs now explicitly state that `Deref` and `DerefMut` should only be implemented for smart pointers and that they should not fail. Additionally, there is now a short primer on `Deref` coercion. * Added links to `DerefMut` from `Deref` and vice versa * Added links to relevant reference sections * Removed "stuttering" in summary sentences * Changed summary sentences of `Deref::deref` and `Deref::deref_mut` to be in 3rd person singular * Removed explicit uses of `fn main()` in the examples --- src/libcore/ops/deref.rs | 102 ++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 24 deletions(-) diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs index 18cf20ac411df..ac5ff1556f4de 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`, 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 `MutDeref`, 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; } From 4b945fd9fe9bc168e385532af1d2b7b30edef1cb Mon Sep 17 00:00:00 2001 From: lukaramu Date: Mon, 7 Aug 2017 19:32:34 +0200 Subject: [PATCH 4/9] Revise `Drop` docs Part of #29365. * Removed "stuttering" in summary sentence. * Copy-edited the explanaition sections * Added sub-headings in Examples section to aid linking * Actually implement `Drop` in the `PrintOnDrop` exampl * Add link to Drop chapter in TRPL * Changed `drop` summary sentence to be in 3rd person singular * Added missing link to `panic!` --- src/libcore/ops/drop.rs | 62 ++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/src/libcore/ops/drop.rs b/src/libcore/ops/drop.rs index 92f3cb256c833..70ab7b2f3b7ec 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); } From ffa327b3a44315bc664b726e01c04b13768ebee4 Mon Sep 17 00:00:00 2001 From: lukaramu Date: Mon, 7 Aug 2017 19:57:32 +0200 Subject: [PATCH 5/9] Revise `Index` and `IndexMut` docs. Part of #29365. * Shortened summary sentences, removing "stuttering" * Small copyediting * Changed method summary sentences to be in 3rd person singular * Removed extraneous explicit `fn main()` in example for `IndexMut` --- src/libcore/ops/index.rs | 49 +++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs index b16b956778744..0652421511aaa 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,22 +63,22 @@ #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Index { - /// 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` if the type of `value` +/// implements [`Copy`]. /// /// [`Index`]: ../../std/ops/trait.Index.html /// [`Copy`]: ../../std/marker/trait.Copy.html @@ -106,7 +105,7 @@ pub trait Index { /// /// struct Balance { /// pub left: Weight, -/// pub right:Weight, +/// pub right: Weight, /// } /// /// impl Index for Balance { @@ -131,28 +130,26 @@ pub trait Index { /// } /// } /// -/// 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: Index { - /// 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; } From 5414c856891da94e0389aace71b514c6338343a6 Mon Sep 17 00:00:00 2001 From: lukaramu Date: Mon, 7 Aug 2017 21:27:47 +0200 Subject: [PATCH 6/9] Revise `Fn`/`FnMut`/`FnOnce` documentation Part of #29365. * Moved explanations out of Examples section and expanded on them. * Made the super-/subtrait relationships more explicit. * Added links to the other traits, TRPL and the nomicon where appropriate * Changed method summaries to be in 3rd person singular * General copyediting --- src/libcore/ops/function.rs | 95 +++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 21 deletions(-) diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs index 62bf69336a398..5a61e9b68b860 100644 --- a/src/libcore/ops/function.rs +++ b/src/libcore/ops/function.rs @@ -10,24 +10,37 @@ /// A version of the call operator that takes an immutable receiver. /// -/// # Examples +/// Closures only taking immutable references to captured variables +/// automatically implement this trait, which allows them to be invoked. +/// For mutably referenced captures, see [`FnMut`], and for consuming the +/// capture, see [`FnOnce`]. +/// +/// You can use the [`Fn`] traits when you want to accept a closure as a +/// parameter. Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any +/// instance of `Fn` can be used where a [`FnMut`] or [`FnOnce`] is expected. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// more information about closures in general. /// -/// 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`]. +/// 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 +/// [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(func: F) -> usize @@ -43,17 +56,39 @@ #[rustc_paren_sugar] #[fundamental] // so that regex can rely that `&str: !FnMut` pub trait Fn : FnMut { - /// 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. /// +/// Closures that might mutably reference captured variables automatically +/// implement this trait, which allows them to be invoked. For immutably +/// referenced captures, see [`Fn`], and for consuming the captures, see +/// [`FnOnce`]. +/// +/// You can use the [`Fn`] traits when you want to accept a closure as a +/// parameter. 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. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// more information about closures in general. +/// +/// 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.Fnhtml +/// [`FnOnce`]: trait.FnOnce.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 +99,7 @@ pub trait Fn : FnMut { /// 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(mut func: F) @@ -88,17 +122,37 @@ pub trait Fn : FnMut { #[rustc_paren_sugar] #[fundamental] // so that regex can rely that `&str: !FnMut` pub trait FnMut : FnOnce { - /// 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. /// +/// Closures that might take ownership of captured variables automatically +/// implement this trait, which allows them to be invoked. For immutably +/// referenced captures, see [`Fn`], and for mutably referenced captures, +/// see [`FnMut`]. +/// +/// You can use the [`Fn`] traits when you want to accept a closure as a +/// parameter. Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any +/// instance of [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected. +/// +/// See the [chapter on closures in *The Rust Programming Language*][book] for +/// more information about closures in general. +/// +/// 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 +/// [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 +160,20 @@ pub trait FnMut : FnOnce { /// 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(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 +191,7 @@ pub trait FnOnce { #[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; } From f1cc7d6c142247de355d65d87578ccd1469b1304 Mon Sep 17 00:00:00 2001 From: lukaramu Date: Mon, 7 Aug 2017 22:55:20 +0200 Subject: [PATCH 7/9] Revised core::ops::range::* docs Part of #29365. * Strenghtened summary/explanation split, making phrasings more parallel * Added links throughout * Fixed some example formatting & removed extraneous `fn main()`s (or hid then when needed because of `#![features]`. * Emphasized note on `RangeFrom`'s `Iterator` implementation * Added summary sentences to (unstable) `contains` methods --- src/libcore/ops/range.rs | 215 ++++++++++++++++++++++----------------- 1 file changed, 120 insertions(+), 95 deletions(-) diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 33258b7a875c5..6a405cfdb9809 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], it's 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,51 @@ impl fmt::Debug for Range { #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] impl> Range { + /// 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)); - /// } + /// # 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)); + /// # } /// ``` 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 { @@ -151,38 +156,39 @@ impl fmt::Debug for RangeFrom { #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] impl> RangeFrom { + /// 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)); - /// } + /// + /// # fn main() { + /// 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 /// for i in ..5 { @@ -190,7 +196,7 @@ impl> RangeFrom { /// } /// ``` /// -/// 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 +206,10 @@ impl> RangeFrom { /// 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 { @@ -217,38 +227,42 @@ impl fmt::Debug for RangeTo { #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] impl> RangeTo { + /// 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)); - /// } + /// + /// # fn main() { + /// 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 -/// } +/// # 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 +/// # } /// ``` #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] @@ -274,43 +288,44 @@ impl fmt::Debug for RangeInclusive { #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] impl> RangeInclusive { + /// 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)); - /// } + /// # 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)); + /// # } /// ``` 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. -/// -/// See the [`contains`](#method.contains) method for its characterization. +/// A range only bounded inclusively above (`...end`). /// -/// 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 @@ -320,15 +335,22 @@ impl> RangeInclusive { /// } /// ``` /// -/// 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)] +/// +/// # fn main() { /// 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 { @@ -348,15 +370,18 @@ impl fmt::Debug for RangeToInclusive { #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] impl> RangeToInclusive { + /// 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)); - /// } + /// + /// # fn main() { + /// 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) From 99e44d8680f91e908c39ab3d5f0be2c11558af01 Mon Sep 17 00:00:00 2001 From: lukaramu Date: Mon, 7 Aug 2017 23:07:34 +0200 Subject: [PATCH 8/9] Added to core::ops module docs Part of #29365. * Added paragraph adapted from API guidelines that operator implementations should be unsurprising * Modified Point example to be more clear when just reading it --- src/libcore/ops/mod.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index a78f4fe28a6b4..b5e6912b10d6e 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")] From 6bdba82ba18fe69ac448f81b10bbbc7d0c10bce1 Mon Sep 17 00:00:00 2001 From: lukaramu Date: Tue, 8 Aug 2017 14:34:37 +0200 Subject: [PATCH 9/9] std::ops docs: incorporated changes suggested in review * fixed link typos and copy-paster errors * rewrote Fn* explanations * `RHS = Self` -> `RHS` is `Self` (added that to all applicable places as well) * fixed up some links * s/MutDeref/DerefMut * removed remaining superfluous `fn main()`s * fixed some minor phrasings and factual errors and inaccuracies std::ops docs: Fix phrasing and factual errors/inaccuracies --- src/libcore/ops/arith.rs | 14 +++--- src/libcore/ops/bit.rs | 6 +++ src/libcore/ops/deref.rs | 2 +- src/libcore/ops/function.rs | 93 ++++++++++++++++++++++++------------- src/libcore/ops/index.rs | 4 +- src/libcore/ops/range.rs | 21 +++------ 6 files changed, 82 insertions(+), 58 deletions(-) diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs index 97fd8651b047b..62007caedd3fc 100644 --- a/src/libcore/ops/arith.rs +++ b/src/libcore/ops/arith.rs @@ -10,8 +10,8 @@ /// The addition operator `+`. /// -/// Note that `RHS = Self` by default, but this is not mandatory. For example, -/// [`std::time::SystemTime`] implements `Add`, which permits +/// Note that `RHS` is `Self` by default, but this is not mandatory. For +/// example, [`std::time::SystemTime`] implements `Add`, which permits /// operations of the form `SystemTime = SystemTime + Duration`. /// /// [`std::time::SystemTime`]: ../../std/time/struct.SystemTime.html @@ -105,8 +105,8 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// The subtraction operator `-`. /// -/// Note that `RHS = Self` by default, but this is not mandatory. For example, -/// [std::time::SystemTime] implements `Sub`, which permits +/// Note that `RHS` is `Self` by default, but this is not mandatory. For +/// example, [`std::time::SystemTime`] implements `Sub`, which permits /// operations of the form `SystemTime = SystemTime - Duration`. /// /// [`std::time::SystemTime`]: ../../std/time/struct.SystemTime.html @@ -200,7 +200,7 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// The multiplication operator `*`. /// -/// Note that `RHS = Self` by default, but this is not mandatory. +/// Note that `RHS` is `Self` by default, but this is not mandatory. /// /// # Examples /// @@ -317,7 +317,7 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// The division operator `/`. /// -/// Note that `RHS = Self` by default, but this is not mandatory. +/// Note that `RHS` is `Self` by default, but this is not mandatory. /// /// # Examples /// @@ -455,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 diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs index e6fadf616b028..0bc5e554cb347 100644 --- a/src/libcore/ops/bit.rs +++ b/src/libcore/ops/bit.rs @@ -68,6 +68,8 @@ 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 /// /// An implementation of `BitAnd` for a wrapper around `bool`. @@ -147,6 +149,8 @@ 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 /// /// An implementation of `BitOr` for a wrapper around `bool`. @@ -226,6 +230,8 @@ 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 /// /// An implementation of `BitXor` that lifts `^` to a wrapper around `bool`. diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs index ac5ff1556f4de..a2e7c44cb249f 100644 --- a/src/libcore/ops/deref.rs +++ b/src/libcore/ops/deref.rs @@ -111,7 +111,7 @@ impl<'a, T: ?Sized> Deref for &'a mut T { /// /// # More on `Deref` coercion /// -/// If `T` implements `MutDeref`, and `x` is a value of type `T`, +/// If `T` implements `DerefMut`, and `x` is a value of type `T`, /// then: /// * In mutable contexts, `*x` on non-pointer types is equivalent to /// `*Deref::deref(&x)`. diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs index 5a61e9b68b860..2cc4e72817ff1 100644 --- a/src/libcore/ops/function.rs +++ b/src/libcore/ops/function.rs @@ -8,27 +8,39 @@ // 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. /// -/// Closures only taking immutable references to captured variables -/// automatically implement this trait, which allows them to be invoked. -/// For mutably referenced captures, see [`FnMut`], and for consuming the -/// capture, see [`FnOnce`]. +/// Instances of `Fn` can be called repeatedly without mutating state. /// -/// You can use the [`Fn`] traits when you want to accept a closure as a -/// parameter. Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any -/// instance of `Fn` can be used where a [`FnMut`] or [`FnOnce`] is expected. +/// *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. +/// +/// 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 -/// more information about closures in general. +/// 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]. +/// 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 @@ -61,29 +73,36 @@ pub trait Fn : FnMut { 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. /// -/// Closures that might mutably reference captured variables automatically -/// implement this trait, which allows them to be invoked. For immutably -/// referenced captures, see [`Fn`], and for consuming the captures, see -/// [`FnOnce`]. +/// `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. /// -/// You can use the [`Fn`] traits when you want to accept a closure as a -/// parameter. 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. +/// 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 -/// more information about closures in general. +/// 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]. +/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. /// /// [book]: ../../book/second-edition/ch13-01-closures.html -/// [`Fn`]: trait.Fnhtml +/// [`Fn`]: trait.Fn.html /// [`FnOnce`]: trait.FnOnce.html +/// [function pointers]: ../../std/primitive.fn.html /// [nomicon]: ../../nomicon/hrtb.html /// /// # Examples @@ -127,27 +146,35 @@ pub trait FnMut : FnOnce { 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`]). /// -/// Closures that might take ownership of captured variables automatically -/// implement this trait, which allows them to be invoked. For immutably -/// referenced captures, see [`Fn`], and for mutably referenced captures, -/// see [`FnMut`]. +/// Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any instance of +/// [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected. /// -/// You can use the [`Fn`] traits when you want to accept a closure as a -/// parameter. 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 -/// more information about closures in general. +/// 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]. +/// 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 diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs index 0652421511aaa..d65c0aba50481 100644 --- a/src/libcore/ops/index.rs +++ b/src/libcore/ops/index.rs @@ -77,11 +77,9 @@ pub trait Index { /// `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 the type of `value` -/// implements [`Copy`]. +/// allows nice things such as `v[index] = value`. /// /// [`Index`]: ../../std/ops/trait.Index.html -/// [`Copy`]: ../../std/marker/trait.Copy.html /// /// # Examples /// diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 6a405cfdb9809..463a50491a866 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -12,7 +12,7 @@ use fmt; /// An unbounded range (`..`). /// -/// `RangeFull` is primarily used as a [slicing index], it's shorthand is `..`. +/// `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 @@ -101,7 +101,6 @@ impl> Range { /// ``` /// #![feature(range_contains)] /// - /// # fn main() { /// assert!(!(3..5).contains(2)); /// assert!( (3..5).contains(3)); /// assert!( (3..5).contains(4)); @@ -109,7 +108,6 @@ impl> Range { /// /// assert!(!(3..3).contains(3)); /// assert!(!(3..2).contains(3)); - /// # } /// ``` pub fn contains(&self, item: Idx) -> bool { (self.start <= item) && (item < self.end) @@ -163,11 +161,9 @@ impl> RangeFrom { /// ``` /// #![feature(range_contains)] /// - /// # fn main() { /// 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) @@ -191,6 +187,8 @@ impl> RangeFrom { /// 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 { /// // ... /// } @@ -234,11 +232,9 @@ impl> RangeTo { /// ``` /// #![feature(range_contains)] /// - /// # fn main() { /// 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) @@ -255,14 +251,12 @@ impl> RangeTo { /// ``` /// #![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 -/// # } /// ``` #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] @@ -295,7 +289,6 @@ impl> RangeInclusive { /// ``` /// #![feature(range_contains,inclusive_range_syntax)] /// - /// # fn main() { /// assert!(!(3...5).contains(2)); /// assert!( (3...5).contains(3)); /// assert!( (3...5).contains(4)); @@ -304,7 +297,6 @@ impl> RangeInclusive { /// /// assert!( (3...3).contains(3)); /// assert!(!(3...2).contains(3)); - /// # } /// ``` pub fn contains(&self, item: Idx) -> bool { self.start <= item && item <= self.end @@ -330,6 +322,9 @@ impl> RangeInclusive { /// /// ```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 { /// // ... /// } @@ -341,11 +336,9 @@ impl> RangeInclusive { /// ``` /// #![feature(inclusive_range_syntax)] /// -/// # fn main() { /// 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 @@ -377,11 +370,9 @@ impl> RangeToInclusive { /// ``` /// #![feature(range_contains,inclusive_range_syntax)] /// - /// # fn main() { /// 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)