Auto merge of #43724 - lukaramu:std-ops-docs, r=QuietMisdreavus

Improve std::ops docs

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

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

Note: I decided to link to the second edition of the book since I think it's more appropriate now for the sections I linked, if this is not okay, please say so!
This commit is contained in:
bors 2017-08-12 19:40:49 +00:00
commit f774bced50
8 changed files with 612 additions and 526 deletions

View file

@ -10,15 +10,20 @@
/// The addition operator `+`.
///
/// Note that `RHS` is `Self` by default, but this is not mandatory. For
/// example, [`std::time::SystemTime`] implements `Add<Duration>`, which permits
/// operations of the form `SystemTime = SystemTime + Duration`.
///
/// [`std::time::SystemTime`]: ../../std/time/struct.SystemTime.html
///
/// # Examples
///
/// This example creates a `Point` struct that implements the `Add` trait, and
/// then demonstrates adding two `Point`s.
/// ## `Add`able points
///
/// ```
/// use std::ops::Add;
///
/// #[derive(Debug)]
/// #[derive(Debug, PartialEq)]
/// struct Point {
/// x: i32,
/// y: i32,
@ -35,31 +40,25 @@
/// }
/// }
///
/// impl PartialEq for Point {
/// fn eq(&self, other: &Self) -> bool {
/// self.x == other.x && self.y == other.y
/// }
/// }
///
/// fn main() {
/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
/// Point { x: 3, y: 3 });
/// }
/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
/// Point { x: 3, y: 3 });
/// ```
///
/// ## Implementing `Add` with generics
///
/// Here is an example of the same `Point` struct implementing the `Add` trait
/// using generics.
///
/// ```
/// use std::ops::Add;
///
/// #[derive(Debug)]
/// #[derive(Debug, PartialEq)]
/// struct Point<T> {
/// x: T,
/// y: T,
/// }
///
/// // Notice that the implementation uses the `Output` associated type
/// // Notice that the implementation uses the associated type `Output`.
/// impl<T: Add<Output=T>> Add for Point<T> {
/// type Output = Point<T>;
///
@ -71,32 +70,18 @@
/// }
/// }
///
/// impl<T: PartialEq> PartialEq for Point<T> {
/// fn eq(&self, other: &Self) -> bool {
/// self.x == other.x && self.y == other.y
/// }
/// }
///
/// fn main() {
/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
/// Point { x: 3, y: 3 });
/// }
/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
/// Point { x: 3, y: 3 });
/// ```
///
/// Note that `RHS = Self` by default, but this is not mandatory. For example,
/// [std::time::SystemTime] implements `Add<Duration>`, which permits
/// operations of the form `SystemTime = SystemTime + Duration`.
///
/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html
#[lang = "add"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"]
pub trait Add<RHS=Self> {
/// The resulting type after applying the `+` operator
/// The resulting type after applying the `+` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// The method for the `+` operator
/// Performs the `+` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn add(self, rhs: RHS) -> Self::Output;
}
@ -120,15 +105,20 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// The subtraction operator `-`.
///
/// Note that `RHS` is `Self` by default, but this is not mandatory. For
/// example, [`std::time::SystemTime`] implements `Sub<Duration>`, which permits
/// operations of the form `SystemTime = SystemTime - Duration`.
///
/// [`std::time::SystemTime`]: ../../std/time/struct.SystemTime.html
///
/// # Examples
///
/// This example creates a `Point` struct that implements the `Sub` trait, and
/// then demonstrates subtracting two `Point`s.
/// ## `Sub`tractable points
///
/// ```
/// use std::ops::Sub;
///
/// #[derive(Debug)]
/// #[derive(Debug, PartialEq)]
/// struct Point {
/// x: i32,
/// y: i32,
@ -145,31 +135,25 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// }
/// }
///
/// impl PartialEq for Point {
/// fn eq(&self, other: &Self) -> bool {
/// self.x == other.x && self.y == other.y
/// }
/// }
///
/// fn main() {
/// assert_eq!(Point { x: 3, y: 3 } - Point { x: 2, y: 3 },
/// Point { x: 1, y: 0 });
/// }
/// assert_eq!(Point { x: 3, y: 3 } - Point { x: 2, y: 3 },
/// Point { x: 1, y: 0 });
/// ```
///
/// ## Implementing `Sub` with generics
///
/// Here is an example of the same `Point` struct implementing the `Sub` trait
/// using generics.
///
/// ```
/// use std::ops::Sub;
///
/// #[derive(Debug)]
/// #[derive(Debug, PartialEq)]
/// struct Point<T> {
/// x: T,
/// y: T,
/// }
///
/// // Notice that the implementation uses the `Output` associated type
/// // Notice that the implementation uses the associated type `Output`.
/// impl<T: Sub<Output=T>> Sub for Point<T> {
/// type Output = Point<T>;
///
@ -181,32 +165,18 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// }
/// }
///
/// impl<T: PartialEq> PartialEq for Point<T> {
/// fn eq(&self, other: &Self) -> bool {
/// self.x == other.x && self.y == other.y
/// }
/// }
///
/// fn main() {
/// assert_eq!(Point { x: 2, y: 3 } - Point { x: 1, y: 0 },
/// Point { x: 1, y: 3 });
/// }
/// assert_eq!(Point { x: 2, y: 3 } - Point { x: 1, y: 0 },
/// Point { x: 1, y: 3 });
/// ```
///
/// Note that `RHS = Self` by default, but this is not mandatory. For example,
/// [std::time::SystemTime] implements `Sub<Duration>`, which permits
/// operations of the form `SystemTime = SystemTime - Duration`.
///
/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html
#[lang = "sub"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"]
pub trait Sub<RHS=Self> {
/// The resulting type after applying the `-` operator
/// The resulting type after applying the `-` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// The method for the `-` operator
/// Performs the `-` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn sub(self, rhs: RHS) -> Self::Output;
}
@ -230,17 +200,19 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// The multiplication operator `*`.
///
/// Note that `RHS` is `Self` by default, but this is not mandatory.
///
/// # Examples
///
/// Implementing a `Mul`tipliable rational number struct:
/// ## `Mul`tipliable rational numbers
///
/// ```
/// use std::ops::Mul;
///
/// // The uniqueness of rational numbers in lowest terms is a consequence of
/// // the fundamental theorem of arithmetic.
/// #[derive(Eq)]
/// #[derive(PartialEq, Debug)]
/// // By the fundamental theorem of arithmetic, rational numbers in lowest
/// // terms are unique. So, by keeping `Rational`s in reduced form, we can
/// // derive `Eq` and `PartialEq`.
/// #[derive(Debug, Eq, PartialEq)]
/// struct Rational {
/// nominator: usize,
/// denominator: usize,
@ -291,45 +263,37 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// Rational::new(1, 2));
/// ```
///
/// Note that `RHS = Self` by default, but this is not mandatory. Here is an
/// implementation which enables multiplication of vectors by scalars, as is
/// done in linear algebra.
/// ## Multiplying vectors by scalars as in linear algebra
///
/// ```
/// use std::ops::Mul;
///
/// struct Scalar {value: usize};
/// struct Scalar { value: usize }
///
/// #[derive(Debug)]
/// struct Vector {value: Vec<usize>};
/// #[derive(Debug, PartialEq)]
/// struct Vector { value: Vec<usize> }
///
/// impl Mul<Vector> for Scalar {
/// impl Mul<Scalar> for Vector {
/// type Output = Vector;
///
/// fn mul(self, rhs: Vector) -> Vector {
/// Vector {value: rhs.value.iter().map(|v| self.value * v).collect()}
/// fn mul(self, rhs: Scalar) -> Vector {
/// Vector { value: self.value.iter().map(|v| v * rhs.value).collect() }
/// }
/// }
///
/// impl PartialEq<Vector> for Vector {
/// fn eq(&self, other: &Self) -> bool {
/// self.value == other.value
/// }
/// }
///
/// let scalar = Scalar{value: 3};
/// let vector = Vector{value: vec![2, 4, 6]};
/// assert_eq!(scalar * vector, Vector{value: vec![6, 12, 18]});
/// let vector = Vector { value: vec![2, 4, 6] };
/// let scalar = Scalar { value: 3 };
/// assert_eq!(vector * scalar, Vector { value: vec![6, 12, 18] });
/// ```
#[lang = "mul"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"]
pub trait Mul<RHS=Self> {
/// The resulting type after applying the `*` operator
/// The resulting type after applying the `*` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// The method for the `*` operator
/// Performs the `*` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn mul(self, rhs: RHS) -> Self::Output;
}
@ -353,17 +317,19 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// The division operator `/`.
///
/// Note that `RHS` is `Self` by default, but this is not mandatory.
///
/// # Examples
///
/// Implementing a `Div`idable rational number struct:
/// ## `Div`idable rational numbers
///
/// ```
/// use std::ops::Div;
///
/// // The uniqueness of rational numbers in lowest terms is a consequence of
/// // the fundamental theorem of arithmetic.
/// #[derive(Eq)]
/// #[derive(PartialEq, Debug)]
/// // By the fundamental theorem of arithmetic, rational numbers in lowest
/// // terms are unique. So, by keeping `Rational`s in reduced form, we can
/// // derive `Eq` and `PartialEq`.
/// #[derive(Debug, Eq, PartialEq)]
/// struct Rational {
/// nominator: usize,
/// denominator: usize,
@ -413,52 +379,42 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// x
/// }
///
/// fn main() {
/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4));
/// assert_eq!(Rational::new(1, 2) / Rational::new(3, 4),
/// Rational::new(2, 3));
/// }
/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4));
/// assert_eq!(Rational::new(1, 2) / Rational::new(3, 4),
/// Rational::new(2, 3));
/// ```
///
/// Note that `RHS = Self` by default, but this is not mandatory. Here is an
/// implementation which enables division of vectors by scalars, as is done in
/// linear algebra.
/// ## Dividing vectors by scalars as in linear algebra
///
/// ```
/// use std::ops::Div;
///
/// struct Scalar {value: f32};
/// struct Scalar { value: f32 }
///
/// #[derive(Debug)]
/// struct Vector {value: Vec<f32>};
/// #[derive(Debug, PartialEq)]
/// struct Vector { value: Vec<f32> }
///
/// impl Div<Scalar> for Vector {
/// type Output = Vector;
///
/// fn div(self, rhs: Scalar) -> Vector {
/// Vector {value: self.value.iter().map(|v| v / rhs.value).collect()}
/// Vector { value: self.value.iter().map(|v| v / rhs.value).collect() }
/// }
/// }
///
/// impl PartialEq<Vector> for Vector {
/// fn eq(&self, other: &Self) -> bool {
/// self.value == other.value
/// }
/// }
///
/// let scalar = Scalar{value: 2f32};
/// let vector = Vector{value: vec![2f32, 4f32, 6f32]};
/// assert_eq!(vector / scalar, Vector{value: vec![1f32, 2f32, 3f32]});
/// let scalar = Scalar { value: 2f32 };
/// let vector = Vector { value: vec![2f32, 4f32, 6f32] };
/// assert_eq!(vector / scalar, Vector { value: vec![1f32, 2f32, 3f32] });
/// ```
#[lang = "div"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"]
pub trait Div<RHS=Self> {
/// The resulting type after applying the `/` operator
/// The resulting type after applying the `/` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// The method for the `/` operator
/// Performs the `/` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn div(self, rhs: RHS) -> Self::Output;
}
@ -499,6 +455,8 @@ div_impl_float! { f32 f64 }
/// The remainder operator `%`.
///
/// Note that `RHS` is `Self` by default, but this is not mandatory.
///
/// # Examples
///
/// This example implements `Rem` on a `SplitSlice` object. After `Rem` is
@ -526,7 +484,7 @@ div_impl_float! { f32 f64 }
/// }
///
/// // If we were to divide &[0, 1, 2, 3, 4, 5, 6, 7] into slices of size 3,
/// // the remainder would be &[6, 7]
/// // the remainder would be &[6, 7].
/// assert_eq!(SplitSlice { slice: &[0, 1, 2, 3, 4, 5, 6, 7] } % 3,
/// SplitSlice { slice: &[6, 7] });
/// ```
@ -534,11 +492,11 @@ div_impl_float! { f32 f64 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"]
pub trait Rem<RHS=Self> {
/// The resulting type after applying the `%` operator
/// The resulting type after applying the `%` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output = Self;
/// The method for the `%` operator
/// Performs the `%` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn rem(self, rhs: RHS) -> Self::Output;
}
@ -607,21 +565,21 @@ rem_impl_float! { f32 f64 }
/// }
/// }
///
/// // a negative positive is a negative
/// // A negative positive is a negative.
/// assert_eq!(-Sign::Positive, Sign::Negative);
/// // a double negative is a positive
/// // A double negative is a positive.
/// assert_eq!(-Sign::Negative, Sign::Positive);
/// // zero is its own negation
/// // Zero is its own negation.
/// assert_eq!(-Sign::Zero, Sign::Zero);
/// ```
#[lang = "neg"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Neg {
/// The resulting type after applying the `-` operator
/// The resulting type after applying the `-` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// The method for the unary `-` operator
/// Performs the unary `-` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn neg(self) -> Self::Output;
}
@ -668,7 +626,7 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
/// ```
/// use std::ops::AddAssign;
///
/// #[derive(Debug)]
/// #[derive(Debug, PartialEq)]
/// struct Point {
/// x: i32,
/// y: i32,
@ -683,12 +641,6 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
/// }
/// }
///
/// impl PartialEq for Point {
/// fn eq(&self, other: &Self) -> bool {
/// self.x == other.x && self.y == other.y
/// }
/// }
///
/// let mut point = Point { x: 1, y: 0 };
/// point += Point { x: 2, y: 3 };
/// assert_eq!(point, Point { x: 3, y: 3 });
@ -697,7 +649,7 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"]
pub trait AddAssign<Rhs=Self> {
/// The method for the `+=` operator
/// Performs the `+=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn add_assign(&mut self, rhs: Rhs);
}
@ -725,7 +677,7 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// ```
/// use std::ops::SubAssign;
///
/// #[derive(Debug)]
/// #[derive(Debug, PartialEq)]
/// struct Point {
/// x: i32,
/// y: i32,
@ -740,12 +692,6 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
/// }
/// }
///
/// impl PartialEq for Point {
/// fn eq(&self, other: &Self) -> bool {
/// self.x == other.x && self.y == other.y
/// }
/// }
///
/// let mut point = Point { x: 3, y: 3 };
/// point -= Point { x: 2, y: 3 };
/// assert_eq!(point, Point {x: 1, y: 0});
@ -754,7 +700,7 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"]
pub trait SubAssign<Rhs=Self> {
/// The method for the `-=` operator
/// Performs the `-=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn sub_assign(&mut self, rhs: Rhs);
}
@ -776,31 +722,27 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
///
/// # Examples
///
/// A trivial implementation of `MulAssign`. When `Foo *= Foo` happens, it ends up
/// calling `mul_assign`, and therefore, `main` prints `Multiplying!`.
///
/// ```
/// use std::ops::MulAssign;
///
/// struct Foo;
/// #[derive(Debug, PartialEq)]
/// struct Frequency { hertz: f64 }
///
/// impl MulAssign for Foo {
/// fn mul_assign(&mut self, _rhs: Foo) {
/// println!("Multiplying!");
/// impl MulAssign<f64> for Frequency {
/// fn mul_assign(&mut self, rhs: f64) {
/// self.hertz *= rhs;
/// }
/// }
///
/// # #[allow(unused_assignments)]
/// fn main() {
/// let mut foo = Foo;
/// foo *= Foo;
/// }
/// let mut frequency = Frequency { hertz: 50.0 };
/// frequency *= 4.0;
/// assert_eq!(Frequency { hertz: 200.0 }, frequency);
/// ```
#[lang = "mul_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"]
pub trait MulAssign<Rhs=Self> {
/// The method for the `*=` operator
/// Performs the `*=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn mul_assign(&mut self, rhs: Rhs);
}
@ -822,31 +764,27 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
///
/// # Examples
///
/// A trivial implementation of `DivAssign`. When `Foo /= Foo` happens, it ends up
/// calling `div_assign`, and therefore, `main` prints `Dividing!`.
///
/// ```
/// use std::ops::DivAssign;
///
/// struct Foo;
/// #[derive(Debug, PartialEq)]
/// struct Frequency { hertz: f64 }
///
/// impl DivAssign for Foo {
/// fn div_assign(&mut self, _rhs: Foo) {
/// println!("Dividing!");
/// impl DivAssign<f64> for Frequency {
/// fn div_assign(&mut self, rhs: f64) {
/// self.hertz /= rhs;
/// }
/// }
///
/// # #[allow(unused_assignments)]
/// fn main() {
/// let mut foo = Foo;
/// foo /= Foo;
/// }
/// let mut frequency = Frequency { hertz: 200.0 };
/// frequency /= 4.0;
/// assert_eq!(Frequency { hertz: 50.0 }, frequency);
/// ```
#[lang = "div_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"]
pub trait DivAssign<Rhs=Self> {
/// The method for the `/=` operator
/// Performs the `/=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn div_assign(&mut self, rhs: Rhs);
}
@ -867,31 +805,31 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
///
/// # Examples
///
/// A trivial implementation of `RemAssign`. When `Foo %= Foo` happens, it ends up
/// calling `rem_assign`, and therefore, `main` prints `Remainder-ing!`.
///
/// ```
/// use std::ops::RemAssign;
///
/// struct Foo;
/// struct CookieJar { cookies: u32 }
///
/// impl RemAssign for Foo {
/// fn rem_assign(&mut self, _rhs: Foo) {
/// println!("Remainder-ing!");
/// impl RemAssign<u32> for CookieJar {
/// fn rem_assign(&mut self, piles: u32) {
/// self.cookies %= piles;
/// }
/// }
///
/// # #[allow(unused_assignments)]
/// fn main() {
/// let mut foo = Foo;
/// foo %= Foo;
/// }
/// let mut jar = CookieJar { cookies: 31 };
/// let piles = 4;
///
/// println!("Splitting up {} cookies into {} even piles!", jar.cookies, piles);
///
/// jar %= piles;
///
/// println!("{} cookies remain in the cookie jar!", jar.cookies);
/// ```
#[lang = "rem_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"]
pub trait RemAssign<Rhs=Self> {
/// The method for the `%=` operator
/// Performs the `%=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn rem_assign(&mut self, rhs: Rhs);
}

View file

@ -41,11 +41,11 @@
#[lang = "not"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Not {
/// The resulting type after applying the `!` operator
/// The resulting type after applying the `!` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// The method for the unary `!` operator
/// Performs the unary `!` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn not(self) -> Self::Output;
}
@ -68,9 +68,11 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// The bitwise AND operator `&`.
///
/// Note that `RHS` is `Self` by default, but this is not mandatory.
///
/// # Examples
///
/// In this example, the `&` operator is lifted to a trivial `Scalar` type.
/// An implementation of `BitAnd` for a wrapper around `bool`.
///
/// ```
/// use std::ops::BitAnd;
@ -87,16 +89,13 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// }
/// }
///
/// fn main() {
/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true));
/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false));
/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false));
/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false));
/// }
/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true));
/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false));
/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false));
/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false));
/// ```
///
/// In this example, the `BitAnd` trait is implemented for a `BooleanVector`
/// struct.
/// An implementation of `BitAnd` for a wrapper around `Vec<bool>`.
///
/// ```
/// use std::ops::BitAnd;
@ -114,22 +113,20 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// }
/// }
///
/// fn main() {
/// let bv1 = BooleanVector(vec![true, true, false, false]);
/// let bv2 = BooleanVector(vec![true, false, true, false]);
/// let expected = BooleanVector(vec![true, false, false, false]);
/// assert_eq!(bv1 & bv2, expected);
/// }
/// let bv1 = BooleanVector(vec![true, true, false, false]);
/// let bv2 = BooleanVector(vec![true, false, true, false]);
/// let expected = BooleanVector(vec![true, false, false, false]);
/// assert_eq!(bv1 & bv2, expected);
/// ```
#[lang = "bitand"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"]
pub trait BitAnd<RHS=Self> {
/// The resulting type after applying the `&` operator
/// The resulting type after applying the `&` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// The method for the `&` operator
/// Performs the `&` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn bitand(self, rhs: RHS) -> Self::Output;
}
@ -152,9 +149,11 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// The bitwise OR operator `|`.
///
/// Note that `RHS` is `Self` by default, but this is not mandatory.
///
/// # Examples
///
/// In this example, the `|` operator is lifted to a trivial `Scalar` type.
/// An implementation of `BitOr` for a wrapper around `bool`.
///
/// ```
/// use std::ops::BitOr;
@ -171,16 +170,13 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// }
/// }
///
/// fn main() {
/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true));
/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true));
/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true));
/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false));
/// }
/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true));
/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true));
/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true));
/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false));
/// ```
///
/// In this example, the `BitOr` trait is implemented for a `BooleanVector`
/// struct.
/// An implementation of `BitOr` for a wrapper around `Vec<bool>`.
///
/// ```
/// use std::ops::BitOr;
@ -198,22 +194,20 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// }
/// }
///
/// fn main() {
/// let bv1 = BooleanVector(vec![true, true, false, false]);
/// let bv2 = BooleanVector(vec![true, false, true, false]);
/// let expected = BooleanVector(vec![true, true, true, false]);
/// assert_eq!(bv1 | bv2, expected);
/// }
/// let bv1 = BooleanVector(vec![true, true, false, false]);
/// let bv2 = BooleanVector(vec![true, false, true, false]);
/// let expected = BooleanVector(vec![true, true, true, false]);
/// assert_eq!(bv1 | bv2, expected);
/// ```
#[lang = "bitor"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"]
pub trait BitOr<RHS=Self> {
/// The resulting type after applying the `|` operator
/// The resulting type after applying the `|` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// The method for the `|` operator
/// Performs the `|` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn bitor(self, rhs: RHS) -> Self::Output;
}
@ -236,9 +230,11 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// The bitwise XOR operator `^`.
///
/// Note that `RHS` is `Self` by default, but this is not mandatory.
///
/// # Examples
///
/// In this example, the `^` operator is lifted to a trivial `Scalar` type.
/// An implementation of `BitXor` that lifts `^` to a wrapper around `bool`.
///
/// ```
/// use std::ops::BitXor;
@ -255,16 +251,13 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// }
/// }
///
/// fn main() {
/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false));
/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true));
/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true));
/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false));
/// }
/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false));
/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true));
/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true));
/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false));
/// ```
///
/// In this example, the `BitXor` trait is implemented for a `BooleanVector`
/// struct.
/// An implementation of `BitXor` trait for a wrapper around `Vec<bool>`.
///
/// ```
/// use std::ops::BitXor;
@ -285,22 +278,20 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// }
/// }
///
/// fn main() {
/// let bv1 = BooleanVector(vec![true, true, false, false]);
/// let bv2 = BooleanVector(vec![true, false, true, false]);
/// let expected = BooleanVector(vec![false, true, true, false]);
/// assert_eq!(bv1 ^ bv2, expected);
/// }
/// let bv1 = BooleanVector(vec![true, true, false, false]);
/// let bv2 = BooleanVector(vec![true, false, true, false]);
/// let expected = BooleanVector(vec![false, true, true, false]);
/// assert_eq!(bv1 ^ bv2, expected);
/// ```
#[lang = "bitxor"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"]
pub trait BitXor<RHS=Self> {
/// The resulting type after applying the `^` operator
/// The resulting type after applying the `^` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// The method for the `^` operator
/// Performs the `^` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn bitxor(self, rhs: RHS) -> Self::Output;
}
@ -326,7 +317,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// # Examples
///
/// An implementation of `Shl` that lifts the `<<` operation on integers to a
/// `Scalar` struct.
/// wrapper around `usize`.
///
/// ```
/// use std::ops::Shl;
@ -342,9 +333,8 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// Scalar(lhs << rhs)
/// }
/// }
/// fn main() {
/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16));
/// }
///
/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16));
/// ```
///
/// An implementation of `Shl` that spins a vector leftward by a given amount.
@ -361,7 +351,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// type Output = Self;
///
/// fn shl(self, rhs: usize) -> SpinVector<T> {
/// // rotate the vector by `rhs` places
/// // Rotate the vector by `rhs` places.
/// let (a, b) = self.vec.split_at(rhs);
/// let mut spun_vector: Vec<T> = vec![];
/// spun_vector.extend_from_slice(b);
@ -370,20 +360,18 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// }
/// }
///
/// fn main() {
/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2,
/// SpinVector { vec: vec![2, 3, 4, 0, 1] });
/// }
/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2,
/// SpinVector { vec: vec![2, 3, 4, 0, 1] });
/// ```
#[lang = "shl"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"]
pub trait Shl<RHS> {
/// The resulting type after applying the `<<` operator
/// The resulting type after applying the `<<` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// The method for the `<<` operator
/// Performs the `<<` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn shl(self, rhs: RHS) -> Self::Output;
}
@ -430,7 +418,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
/// # Examples
///
/// An implementation of `Shr` that lifts the `>>` operation on integers to a
/// `Scalar` struct.
/// wrapper around `usize`.
///
/// ```
/// use std::ops::Shr;
@ -446,9 +434,8 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
/// Scalar(lhs >> rhs)
/// }
/// }
/// fn main() {
/// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4));
/// }
///
/// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4));
/// ```
///
/// An implementation of `Shr` that spins a vector rightward by a given amount.
@ -465,7 +452,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
/// type Output = Self;
///
/// fn shr(self, rhs: usize) -> SpinVector<T> {
/// // rotate the vector by `rhs` places
/// // Rotate the vector by `rhs` places.
/// let (a, b) = self.vec.split_at(self.vec.len() - rhs);
/// let mut spun_vector: Vec<T> = vec![];
/// spun_vector.extend_from_slice(b);
@ -474,20 +461,18 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
/// }
/// }
///
/// fn main() {
/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2,
/// SpinVector { vec: vec![3, 4, 0, 1, 2] });
/// }
/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2,
/// SpinVector { vec: vec![3, 4, 0, 1, 2] });
/// ```
#[lang = "shr"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"]
pub trait Shr<RHS> {
/// The resulting type after applying the `>>` operator
/// The resulting type after applying the `>>` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// The method for the `>>` operator
/// Performs the `>>` operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn shr(self, rhs: RHS) -> Self::Output;
}
@ -533,7 +518,8 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
///
/// # Examples
///
/// In this example, the `&=` operator is lifted to a trivial `Scalar` type.
/// An implementation of `BitAndAssign` that lifts the `&=` operator to a
/// wrapper around `bool`.
///
/// ```
/// use std::ops::BitAndAssign;
@ -548,27 +534,25 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
/// }
/// }
///
/// fn main() {
/// let mut scalar = Scalar(true);
/// scalar &= Scalar(true);
/// assert_eq!(scalar, Scalar(true));
/// let mut scalar = Scalar(true);
/// scalar &= Scalar(true);
/// assert_eq!(scalar, Scalar(true));
///
/// let mut scalar = Scalar(true);
/// scalar &= Scalar(false);
/// assert_eq!(scalar, Scalar(false));
/// let mut scalar = Scalar(true);
/// scalar &= Scalar(false);
/// assert_eq!(scalar, Scalar(false));
///
/// let mut scalar = Scalar(false);
/// scalar &= Scalar(true);
/// assert_eq!(scalar, Scalar(false));
/// let mut scalar = Scalar(false);
/// scalar &= Scalar(true);
/// assert_eq!(scalar, Scalar(false));
///
/// let mut scalar = Scalar(false);
/// scalar &= Scalar(false);
/// assert_eq!(scalar, Scalar(false));
/// }
/// let mut scalar = Scalar(false);
/// scalar &= Scalar(false);
/// assert_eq!(scalar, Scalar(false));
/// ```
///
/// In this example, the `BitAndAssign` trait is implemented for a
/// `BooleanVector` struct.
/// Here, the `BitAndAssign` trait is implemented for a wrapper around
/// `Vec<bool>`.
///
/// ```
/// use std::ops::BitAndAssign;
@ -577,7 +561,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
/// struct BooleanVector(Vec<bool>);
///
/// impl BitAndAssign for BooleanVector {
/// // rhs is the "right-hand side" of the expression `a &= b`
/// // `rhs` is the "right-hand side" of the expression `a &= b`.
/// fn bitand_assign(&mut self, rhs: Self) {
/// assert_eq!(self.0.len(), rhs.0.len());
/// *self = BooleanVector(self.0
@ -588,18 +572,16 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
/// }
/// }
///
/// fn main() {
/// let mut bv = BooleanVector(vec![true, true, false, false]);
/// bv &= BooleanVector(vec![true, false, true, false]);
/// let expected = BooleanVector(vec![true, false, false, false]);
/// assert_eq!(bv, expected);
/// }
/// let mut bv = BooleanVector(vec![true, true, false, false]);
/// bv &= BooleanVector(vec![true, false, true, false]);
/// let expected = BooleanVector(vec![true, false, false, false]);
/// assert_eq!(bv, expected);
/// ```
#[lang = "bitand_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"]
pub trait BitAndAssign<Rhs=Self> {
/// The method for the `&=` operator
/// Performs the `&=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn bitand_assign(&mut self, rhs: Rhs);
}
@ -620,31 +602,31 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
///
/// # Examples
///
/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up
/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`.
///
/// ```
/// use std::ops::BitOrAssign;
///
/// struct Foo;
/// #[derive(Debug, PartialEq)]
/// struct PersonalPreferences {
/// likes_cats: bool,
/// likes_dogs: bool,
/// }
///
/// impl BitOrAssign for Foo {
/// fn bitor_assign(&mut self, _rhs: Foo) {
/// println!("Bitwise Or-ing!");
/// impl BitOrAssign for PersonalPreferences {
/// fn bitor_assign(&mut self, rhs: Self) {
/// self.likes_cats |= rhs.likes_cats;
/// self.likes_dogs |= rhs.likes_dogs;
/// }
/// }
///
/// # #[allow(unused_assignments)]
/// fn main() {
/// let mut foo = Foo;
/// foo |= Foo;
/// }
/// let mut prefs = PersonalPreferences { likes_cats: true, likes_dogs: false };
/// prefs |= PersonalPreferences { likes_cats: false, likes_dogs: true };
/// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true });
/// ```
#[lang = "bitor_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"]
pub trait BitOrAssign<Rhs=Self> {
/// The method for the `|=` operator
/// Performs the `|=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn bitor_assign(&mut self, rhs: Rhs);
}
@ -665,31 +647,31 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
///
/// # Examples
///
/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up
/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`.
///
/// ```
/// use std::ops::BitXorAssign;
///
/// struct Foo;
/// #[derive(Debug, PartialEq)]
/// struct Personality {
/// has_soul: bool,
/// likes_knitting: bool,
/// }
///
/// impl BitXorAssign for Foo {
/// fn bitxor_assign(&mut self, _rhs: Foo) {
/// println!("Bitwise Xor-ing!");
/// impl BitXorAssign for Personality {
/// fn bitxor_assign(&mut self, rhs: Self) {
/// self.has_soul ^= rhs.has_soul;
/// self.likes_knitting ^= rhs.likes_knitting;
/// }
/// }
///
/// # #[allow(unused_assignments)]
/// fn main() {
/// let mut foo = Foo;
/// foo ^= Foo;
/// }
/// let mut personality = Personality { has_soul: false, likes_knitting: true };
/// personality ^= Personality { has_soul: true, likes_knitting: true };
/// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false});
/// ```
#[lang = "bitxor_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"]
pub trait BitXorAssign<Rhs=Self> {
/// The method for the `^=` operator
/// Performs the `^=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn bitxor_assign(&mut self, rhs: Rhs);
}
@ -710,31 +692,29 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
///
/// # Examples
///
/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up
/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`.
/// An implementation of `ShlAssign` for a wrapper around `usize`.
///
/// ```
/// use std::ops::ShlAssign;
///
/// struct Foo;
/// #[derive(Debug, PartialEq)]
/// struct Scalar(usize);
///
/// impl ShlAssign<Foo> for Foo {
/// fn shl_assign(&mut self, _rhs: Foo) {
/// println!("Shifting left!");
/// impl ShlAssign<usize> for Scalar {
/// fn shl_assign(&mut self, rhs: usize) {
/// self.0 <<= rhs;
/// }
/// }
///
/// # #[allow(unused_assignments)]
/// fn main() {
/// let mut foo = Foo;
/// foo <<= Foo;
/// }
/// let mut scalar = Scalar(4);
/// scalar <<= 2;
/// assert_eq!(scalar, Scalar(16));
/// ```
#[lang = "shl_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"]
pub trait ShlAssign<Rhs> {
/// The method for the `<<=` operator
/// Performs the `<<=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn shl_assign(&mut self, rhs: Rhs);
}
@ -776,31 +756,29 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
///
/// # Examples
///
/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up
/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`.
/// An implementation of `ShrAssign` for a wrapper around `usize`.
///
/// ```
/// use std::ops::ShrAssign;
///
/// struct Foo;
/// #[derive(Debug, PartialEq)]
/// struct Scalar(usize);
///
/// impl ShrAssign<Foo> for Foo {
/// fn shr_assign(&mut self, _rhs: Foo) {
/// println!("Shifting right!");
/// impl ShrAssign<usize> for Scalar {
/// fn shr_assign(&mut self, rhs: usize) {
/// self.0 >>= rhs;
/// }
/// }
///
/// # #[allow(unused_assignments)]
/// fn main() {
/// let mut foo = Foo;
/// foo >>= Foo;
/// }
/// let mut scalar = Scalar(16);
/// scalar >>= 2;
/// assert_eq!(scalar, Scalar(4));
/// ```
#[lang = "shr_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"]
pub trait ShrAssign<Rhs=Self> {
/// The method for the `>>=` operator
/// Performs the `>>=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn shr_assign(&mut self, rhs: Rhs);
}

View file

@ -8,16 +8,44 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// The `Deref` trait is used to specify the functionality of dereferencing
/// operations, like `*v`.
/// Used for immutable dereferencing operations, like `*v`.
///
/// `Deref` also enables ['`Deref` coercions'][coercions].
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
///
/// [coercions]: ../../book/first-edition/deref-coercions.html
/// Implementing `Deref` for smart pointers makes accessing the data behind them
/// convenient, which is why they implement `Deref`. On the other hand, the
/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
/// accomodate smart pointers. Because of this, **`Deref` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
/// * In immutable contexts, `*x` on non-pointer types is equivalent to
/// `*Deref::deref(&x)`.
/// * Values of type `&T` are coerced to values of type `&U`
/// * `T` implicitly implements all the (immutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [the `Deref` trait][ref-deref-trait], and [type coercions].
///
/// [book]: ../../book/second-edition/ch15-02-deref.html
/// [`DerefMut`]: trait.DerefMut.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator
/// [ref-deref-trait]: ../../reference/the-deref-trait.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is accessible via dereferencing the
/// A struct with a single field which is accessible by dereferencing the
/// struct.
///
/// ```
@ -35,19 +63,17 @@
/// }
/// }
///
/// fn main() {
/// let x = DerefExample { value: 'a' };
/// assert_eq!('a', *x);
/// }
/// let x = DerefExample { value: 'a' };
/// assert_eq!('a', *x);
/// ```
#[lang = "deref"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Deref {
/// The resulting type after dereferencing
/// The resulting type after dereferencing.
#[stable(feature = "rust1", since = "1.0.0")]
type Target: ?Sized;
/// The method called to dereference a value
/// Dereferences the value.
#[stable(feature = "rust1", since = "1.0.0")]
fn deref(&self) -> &Self::Target;
}
@ -66,16 +92,46 @@ impl<'a, T: ?Sized> Deref for &'a mut T {
fn deref(&self) -> &T { *self }
}
/// The `DerefMut` trait is used to specify the functionality of dereferencing
/// mutably like `*v = 1;`
/// Used for mutable dereferencing operations, like in `*v = 1;`.
///
/// `DerefMut` also enables ['`Deref` coercions'][coercions].
/// 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.
///
/// [coercions]: ../../book/first-edition/deref-coercions.html
/// Implementing `DerefMut` for smart pointers makes mutating the data behind
/// them convenient, which is why they implement `DerefMut`. On the other hand,
/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
/// accomodate smart pointers. Because of this, **`DerefMut` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `DerefMut` is invoked
/// implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
/// then:
/// * In mutable contexts, `*x` on non-pointer types is equivalent to
/// `*Deref::deref(&x)`.
/// * Values of type `&mut T` are coerced to values of type `&mut U`
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [the `Deref` trait][ref-deref-trait], and [type coercions].
///
/// [book]: ../../book/second-edition/ch15-02-deref.html
/// [`Deref`]: trait.Deref.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator
/// [ref-deref-trait]: ../../reference/the-deref-trait.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is modifiable via dereferencing the
/// A struct with a single field which is modifiable by dereferencing the
/// struct.
///
/// ```
@ -99,16 +155,14 @@ impl<'a, T: ?Sized> Deref for &'a mut T {
/// }
/// }
///
/// fn main() {
/// let mut x = DerefMutExample { value: 'a' };
/// *x = 'b';
/// assert_eq!('b', *x);
/// }
/// let mut x = DerefMutExample { value: 'a' };
/// *x = 'b';
/// assert_eq!('b', *x);
/// ```
#[lang = "deref_mut"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DerefMut: Deref {
/// The method called to mutably dereference a value
/// Mutably dereferences the value.
#[stable(feature = "rust1", since = "1.0.0")]
fn deref_mut(&mut self) -> &mut Self::Target;
}

View file

@ -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.
///
/// When this method has been called, `self` has not yet been deallocated.
/// If it were, `self` would be a dangling reference.
///
/// After this function is over, the memory of `self` will be deallocated.
///
/// This function cannot be called explicitly. This is compiler error
/// [E0040]. However, the [`std::mem::drop`] function in the prelude can be
/// 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.
///
/// [E0040]: ../../error-index.html#E0040
/// [`std::mem::drop`]: ../../std/mem/fn.drop.html
/// When this method has been called, `self` has not yet been deallocated.
/// That only happens after the method is over.
/// If this wasn't the case, `self` would be a dangling reference.
///
/// # Panics
///
/// Given that a `panic!` will call `drop()` as it unwinds, any `panic!` in
/// a `drop()` implementation will likely abort.
/// 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
#[stable(feature = "rust1", since = "1.0.0")]
fn drop(&mut self);
}

View file

@ -8,26 +8,51 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// A version of the call operator that takes an immutable receiver.
/// The version of the call operator that takes an immutable receiver.
///
/// Instances of `Fn` can be called repeatedly without mutating state.
///
/// *This trait (`Fn`) is not to be confused with [function pointers][]
/// (`fn`).*
///
/// `Fn` is implemented automatically by closures which only take immutable
/// references to captured variables or don't capture anything at all, as well
/// as (safe) [function pointers][] (with some caveats, see their documentation
/// for more details). Additionally, for any type `F` that implements `Fn`, `&F`
/// implements `Fn`, too.
///
/// Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any
/// instance of `Fn` can be used as a parameter where a [`FnMut`] or [`FnOnce`]
/// is expected.
///
/// Use `Fn` as a bound when you want to accept a parameter of function-like
/// type and need to call it repeatedly and without mutating state (e.g. when
/// calling it concurrently). If you do not need such strict requirements, use
/// [`FnMut`] or [`FnOnce`] as bounds.
///
/// See the [chapter on closures in *The Rust Programming Language*][book] for
/// some more information on this topic.
///
/// Also of note is the special syntax for `Fn` traits (e.g.
/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
///
/// [book]: ../../book/second-edition/ch13-01-closures.html
/// [`FnMut`]: trait.FnMut.html
/// [`FnOnce`]: trait.FnOnce.html
/// [function pointers]: ../../std/primitive.fn.html
/// [nomicon]: ../../nomicon/hrtb.html
///
/// # Examples
///
/// 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`].
///
/// [`FnMut`]: trait.FnMut.html
/// [`FnOnce`]: trait.FnOnce.html
/// ## Calling a closure
///
/// ```
/// let square = |x| x * x;
/// assert_eq!(square(5), 25);
/// ```
///
/// Closures can also be passed to higher-level functions through a `Fn`
/// parameter (or a `FnMut` or `FnOnce` parameter, which are supertraits of
/// `Fn`).
/// ## Using a `Fn` parameter
///
/// ```
/// fn call_with_one<F>(func: F) -> usize
@ -43,17 +68,46 @@
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
pub trait Fn<Args> : FnMut<Args> {
/// This is called when the call operator is used.
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
/// A version of the call operator that takes a mutable receiver.
/// The version of the call operator that takes a mutable receiver.
///
/// Instances of `FnMut` can be called repeatedly and may mutate state.
///
/// `FnMut` is implemented automatically by closures which take mutable
/// references to captured variables, as well as all types that implement
/// [`Fn`], e.g. (safe) [function pointers][] (since `FnMut` is a supertrait of
/// [`Fn`]). Additionally, for any type `F` that implements `FnMut`, `&mut F`
/// implements `FnMut`, too.
///
/// Since [`FnOnce`] is a supertrait of `FnMut`, any instance of `FnMut` can be
/// used where a [`FnOnce`] is expected, and since [`Fn`] is a subtrait of
/// `FnMut`, any instance of [`Fn`] can be used where `FnMut` is expected.
///
/// Use `FnMut` as a bound when you want to accept a parameter of function-like
/// type and need to call it repeatedly, while allowing it to mutate state.
/// If you don't want the parameter to mutate state, use [`Fn`] as a
/// bound; if you don't need to call it repeatedly, use [`FnOnce`].
///
/// See the [chapter on closures in *The Rust Programming Language*][book] for
/// some more information on this topic.
///
/// Also of note is the special syntax for `Fn` traits (e.g.
/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
///
/// [book]: ../../book/second-edition/ch13-01-closures.html
/// [`Fn`]: trait.Fn.html
/// [`FnOnce`]: trait.FnOnce.html
/// [function pointers]: ../../std/primitive.fn.html
/// [nomicon]: ../../nomicon/hrtb.html
///
/// # Examples
///
/// Closures that mutably capture variables automatically implement this trait,
/// which allows them to be invoked.
/// ## Calling a mutably capturing closure
///
/// ```
/// let mut x = 5;
@ -64,8 +118,7 @@ pub trait Fn<Args> : FnMut<Args> {
/// assert_eq!(x, 25);
/// ```
///
/// Closures can also be passed to higher-level functions through a `FnMut`
/// parameter (or a `FnOnce` parameter, which is a supertrait of `FnMut`).
/// ## Using a `FnMut` parameter
///
/// ```
/// fn do_twice<F>(mut func: F)
@ -88,17 +141,45 @@ pub trait Fn<Args> : FnMut<Args> {
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
pub trait FnMut<Args> : FnOnce<Args> {
/// This is called when the call operator is used.
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
/// A version of the call operator that takes a by-value receiver.
/// The version of the call operator that takes a by-value receiver.
///
/// Instances of `FnOnce` can be called, but might not be callable multiple
/// times. Because of this, if the only thing known about a type is that it
/// implements `FnOnce`, it can only be called once.
///
/// `FnOnce` is implemented automatically by closure that might consume captured
/// variables, as well as all types that implement [`FnMut`], e.g. (safe)
/// [function pointers][] (since `FnOnce` is a supertrait of [`FnMut`]).
///
/// Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any instance of
/// [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected.
///
/// Use `FnOnce` as a bound when you want to accept a parameter of function-like
/// type and only need to call it once. If you need to call the parameter
/// repeatedly, use [`FnMut`] as a bound; if you also need it to not mutate
/// state, use [`Fn`].
///
/// See the [chapter on closures in *The Rust Programming Language*][book] for
/// some more information on this topic.
///
/// Also of note is the special syntax for `Fn` traits (e.g.
/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
///
/// [book]: ../../book/second-edition/ch13-01-closures.html
/// [`Fn`]: trait.Fn.html
/// [`FnMut`]: trait.FnMut.html
/// [function pointers]: ../../std/primitive.fn.html
/// [nomicon]: ../../nomicon/hrtb.html
///
/// # Examples
///
/// By-value closures automatically implement this trait, which allows them to
/// be invoked.
/// ## Calling a by-value closure
///
/// ```
/// let x = 5;
@ -106,21 +187,20 @@ pub trait FnMut<Args> : FnOnce<Args> {
/// assert_eq!(square_x(), 25);
/// ```
///
/// By-value Closures can also be passed to higher-level functions through a
/// `FnOnce` parameter.
/// ## Using a `FnOnce` parameter
///
/// ```
/// fn consume_with_relish<F>(func: F)
/// where F: FnOnce() -> String
/// {
/// // `func` consumes its captured variables, so it cannot be run more
/// // than once
/// // than once.
/// println!("Consumed: {}", func());
///
/// println!("Delicious!");
///
/// // Attempting to invoke `func()` again will throw a `use of moved
/// // value` error for `func`
/// // value` error for `func`.
/// }
///
/// let x = String::from("x");
@ -138,7 +218,7 @@ pub trait FnOnce<Args> {
#[stable(feature = "fn_once_output", since = "1.12.0")]
type Output;
/// This is called when the call operator is used.
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

View file

@ -8,13 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// The `Index` trait is used to specify the functionality of indexing operations
/// like `container[index]` when used in an immutable context.
/// Used for indexing operations (`container[index]`) in immutable contexts.
///
/// `container[index]` is actually syntactic sugar for `*container.index(index)`,
/// but only when used as an immutable value. If a mutable value is requested,
/// [`IndexMut`] is used instead. This allows nice things such as
/// `let value = v[index]` if `value` implements [`Copy`].
/// `let value = v[index]` if the type of `value` implements [`Copy`].
///
/// [`IndexMut`]: ../../std/ops/trait.IndexMut.html
/// [`Copy`]: ../../std/marker/trait.Copy.html
@ -64,25 +63,23 @@
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Index<Idx: ?Sized> {
/// The returned type after indexing
/// The returned type after indexing.
#[stable(feature = "rust1", since = "1.0.0")]
type Output: ?Sized;
/// The method for the indexing (`container[index]`) operation
/// Performs the indexing (`container[index]`) operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn index(&self, index: Idx) -> &Self::Output;
}
/// The `IndexMut` trait is used to specify the functionality of indexing
/// operations like `container[index]` when used in a mutable context.
/// Used for indexing operations (`container[index]`) in mutable contexts.
///
/// `container[index]` is actually syntactic sugar for
/// `*container.index_mut(index)`, but only when used as a mutable value. If
/// an immutable value is requested, the [`Index`] trait is used instead. This
/// allows nice things such as `v[index] = value` if `value` implements [`Copy`].
/// allows nice things such as `v[index] = value`.
///
/// [`Index`]: ../../std/ops/trait.Index.html
/// [`Copy`]: ../../std/marker/trait.Copy.html
///
/// # Examples
///
@ -106,7 +103,7 @@ pub trait Index<Idx: ?Sized> {
///
/// struct Balance {
/// pub left: Weight,
/// pub right:Weight,
/// pub right: Weight,
/// }
///
/// impl Index<Side> for Balance {
@ -131,28 +128,26 @@ pub trait Index<Idx: ?Sized> {
/// }
/// }
///
/// fn main() {
/// let mut balance = Balance {
/// right: Weight::Kilogram(2.5),
/// left: Weight::Pound(1.5),
/// };
/// 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));
/// // 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);
/// }
/// // However, in this case `balance[Side::Left]` is sugar for
/// // `*balance.index_mut(Side::Left)`, since we are writing
/// // `balance[Side::Left]`.
/// balance[Side::Left] = Weight::Kilogram(3.0);
/// ```
#[lang = "index_mut"]
#[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
/// The method for the mutable indexing (`container[index]`) operation
/// Performs the mutable indexing (`container[index]`) operation.
#[stable(feature = "rust1", since = "1.0.0")]
fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
}

View file

@ -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")]

View file

@ -10,10 +10,10 @@
use fmt;
/// An unbounded range. Use `..` (two dots) for its shorthand.
/// An unbounded range (`..`).
///
/// Its primary use case is slicing index. It cannot serve as an iterator
/// because it doesn't have a starting point.
/// `RangeFull` is primarily used as a [slicing index], its shorthand is `..`.
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
///
/// # Examples
///
@ -23,8 +23,8 @@ use fmt;
/// assert_eq!((..), std::ops::RangeFull);
/// ```
///
/// It does not have an `IntoIterator` implementation, so you can't use it in a
/// `for` loop directly. This won't compile:
/// It does not have an [`IntoIterator`] implementation, so you can't use it in
/// a `for` loop directly. This won't compile:
///
/// ```compile_fail,E0277
/// for i in .. {
@ -32,7 +32,7 @@ use fmt;
/// }
/// ```
///
/// Used as a slicing index, `RangeFull` produces the full array as a slice.
/// Used as a [slicing index], `RangeFull` produces the full array as a slice.
///
/// ```
/// let arr = [0, 1, 2, 3];
@ -41,6 +41,10 @@ use fmt;
/// assert_eq!(arr[1.. ], [ 1,2,3]);
/// assert_eq!(arr[1..3], [ 1,2 ]);
/// ```
///
/// [`IntoIterator`]: ../iter/trait.Iterator.html
/// [`Iterator`]: ../iter/trait.IntoIterator.html
/// [slicing index]: ../slice/trait.SliceIndex.html
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeFull;
@ -52,24 +56,23 @@ impl fmt::Debug for RangeFull {
}
}
/// A (half-open) range which is bounded at both ends: { x | start <= x < end }.
/// Use `start..end` (two dots) for its shorthand.
/// A (half-open) range bounded inclusively below and exclusively above
/// (`start..end`).
///
/// See the [`contains`](#method.contains) method for its characterization.
/// The `Range` `start..end` contains all values with `x >= start` and
/// `x < end`.
///
/// # Examples
///
/// ```
/// fn main() {
/// assert_eq!((3..5), std::ops::Range{ start: 3, end: 5 });
/// assert_eq!(3+4+5, (3..6).sum());
/// 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
/// }
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ .. ], [0,1,2,3]);
/// assert_eq!(arr[ ..3], [0,1,2 ]);
/// assert_eq!(arr[1.. ], [ 1,2,3]);
/// assert_eq!(arr[1..3], [ 1,2 ]); // Range
/// ```
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[stable(feature = "rust1", since = "1.0.0")]
@ -91,49 +94,49 @@ impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
///
/// ```
/// #![feature(range_contains)]
/// fn main() {
/// assert!( ! (3..5).contains(2));
/// assert!( (3..5).contains(3));
/// assert!( (3..5).contains(4));
/// assert!( ! (3..5).contains(5));
///
/// assert!( ! (3..3).contains(3));
/// assert!( ! (3..2).contains(3));
/// }
/// assert!(!(3..5).contains(2));
/// assert!( (3..5).contains(3));
/// assert!( (3..5).contains(4));
/// assert!(!(3..5).contains(5));
///
/// assert!(!(3..3).contains(3));
/// assert!(!(3..2).contains(3));
/// ```
pub fn contains(&self, item: Idx) -> bool {
(self.start <= item) && (item < self.end)
}
}
/// A range which is only bounded below: { x | start <= x }.
/// Use `start..` for its shorthand.
/// A range only bounded inclusively below (`start..`).
///
/// See the [`contains`](#method.contains) method for its characterization.
/// The `RangeFrom` `start..` contains all values with `x >= start`.
///
/// Note: Currently, no overflow checking is done for the iterator
/// *Note*: Currently, no overflow checking is done for the [`Iterator`]
/// implementation; if you use an integer range and the integer overflows, it
/// might panic in debug mode or create an endless loop in release mode. This
/// overflow behavior might change in the future.
/// might panic in debug mode or create an endless loop in release mode. **This
/// overflow behavior might change in the future.**
///
/// # Examples
///
/// ```
/// fn main() {
/// assert_eq!((2..), std::ops::RangeFrom{ start: 2 });
/// assert_eq!(2+3+4, (2..).take(3).sum());
/// 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 ]);
/// }
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ .. ], [0,1,2,3]);
/// assert_eq!(arr[ ..3], [0,1,2 ]);
/// assert_eq!(arr[1.. ], [ 1,2,3]); // RangeFrom
/// assert_eq!(arr[1..3], [ 1,2 ]);
/// ```
///
/// [`Iterator`]: ../iter/trait.IntoIterator.html
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeFrom<Idx> {
@ -151,46 +154,47 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
///
/// ```
/// #![feature(range_contains)]
/// fn main() {
/// assert!( ! (3..).contains(2));
/// assert!( (3..).contains(3));
/// assert!( (3..).contains(1_000_000_000));
/// }
///
/// assert!(!(3..).contains(2));
/// assert!( (3..).contains(3));
/// assert!( (3..).contains(1_000_000_000));
/// ```
pub fn contains(&self, item: Idx) -> bool {
(self.start <= item)
}
}
/// A range which is only bounded above: { x | x < end }.
/// Use `..end` (two dots) for its shorthand.
/// A range only bounded exclusively above (`..end`).
///
/// See the [`contains`](#method.contains) method for its characterization.
///
/// It cannot serve as an iterator because it doesn't have a starting point.
/// The `RangeTo` `..end` contains all values with `x < end`.
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
///
/// # Examples
///
/// The `..{integer}` syntax is a `RangeTo`:
/// The `..end` syntax is a `RangeTo`:
///
/// ```
/// assert_eq!((..5), std::ops::RangeTo{ end: 5 });
/// assert_eq!((..5), std::ops::RangeTo { end: 5 });
/// ```
///
/// It does not have an `IntoIterator` implementation, so you can't use it in a
/// `for` loop directly. This won't compile:
/// It does not have an [`IntoIterator`] implementation, so you can't use it in
/// a `for` loop directly. This won't compile:
///
/// ```compile_fail,E0277
/// // error[E0277]: the trait bound `std::ops::RangeTo<{integer}>:
/// // std::iter::Iterator` is not satisfied
/// for i in ..5 {
/// // ...
/// }
/// ```
///
/// When used as a slicing index, `RangeTo` produces a slice of all array
/// When used as a [slicing index], `RangeTo` produces a slice of all array
/// elements before the index indicated by `end`.
///
/// ```
@ -200,6 +204,10 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
/// assert_eq!(arr[1.. ], [ 1,2,3]);
/// assert_eq!(arr[1..3], [ 1,2 ]);
/// ```
///
/// [`IntoIterator`]: ../iter/trait.Iterator.html
/// [`Iterator`]: ../iter/trait.IntoIterator.html
/// [slicing index]: ../slice/trait.SliceIndex.html
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeTo<Idx> {
@ -217,38 +225,38 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
///
/// ```
/// #![feature(range_contains)]
/// fn main() {
/// assert!( (..5).contains(-1_000_000_000));
/// assert!( (..5).contains(4));
/// assert!( ! (..5).contains(5));
/// }
///
/// assert!( (..5).contains(-1_000_000_000));
/// assert!( (..5).contains(4));
/// assert!(!(..5).contains(5));
/// ```
pub fn contains(&self, item: Idx) -> bool {
(item < self.end)
}
}
/// An inclusive range which is bounded at both ends: { x | start <= x <= end }.
/// Use `start...end` (three dots) for its shorthand.
/// An range bounded inclusively below and above (`start...end`).
///
/// See the [`contains`](#method.contains) method for its characterization.
/// The `RangeInclusive` `start...end` contains all values with `x >= start`
/// and `x <= end`.
///
/// # Examples
///
/// ```
/// #![feature(inclusive_range,inclusive_range_syntax)]
/// fn main() {
/// assert_eq!((3...5), std::ops::RangeInclusive{ start: 3, end: 5 });
/// assert_eq!(3+4+5, (3...5).sum());
///
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ ...2], [0,1,2 ]);
/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive
/// }
/// assert_eq!((3...5), std::ops::RangeInclusive { start: 3, end: 5 });
/// assert_eq!(3 + 4 + 5, (3...5).sum());
///
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ ...2], [0,1,2 ]);
/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive
/// ```
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
@ -274,61 +282,68 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
///
/// ```
/// #![feature(range_contains,inclusive_range_syntax)]
/// fn main() {
/// assert!( ! (3...5).contains(2));
/// assert!( (3...5).contains(3));
/// assert!( (3...5).contains(4));
/// assert!( (3...5).contains(5));
/// assert!( ! (3...5).contains(6));
///
/// assert!( (3...3).contains(3));
/// assert!( ! (3...2).contains(3));
/// }
/// assert!(!(3...5).contains(2));
/// assert!( (3...5).contains(3));
/// assert!( (3...5).contains(4));
/// assert!( (3...5).contains(5));
/// assert!(!(3...5).contains(6));
///
/// assert!( (3...3).contains(3));
/// assert!(!(3...2).contains(3));
/// ```
pub fn contains(&self, item: Idx) -> bool {
self.start <= item && item <= self.end
}
}
/// An inclusive range which is only bounded above: { x | x <= end }.
/// Use `...end` (three dots) for its shorthand.
/// A range only bounded inclusively above (`...end`).
///
/// See the [`contains`](#method.contains) method for its characterization.
///
/// It cannot serve as an iterator because it doesn't have a starting point.
/// The `RangeToInclusive` `...end` contains all values with `x <= end`.
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
///
/// # Examples
///
/// The `...{integer}` syntax is a `RangeToInclusive`:
/// The `...end` syntax is a `RangeToInclusive`:
///
/// ```
/// #![feature(inclusive_range,inclusive_range_syntax)]
/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 });
/// ```
///
/// It does not have an `IntoIterator` implementation, so you can't use it in a
/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
/// `for` loop directly. This won't compile:
///
/// ```compile_fail,E0277
/// #![feature(inclusive_range_syntax)]
///
/// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>:
/// // std::iter::Iterator` is not satisfied
/// for i in ...5 {
/// // ...
/// }
/// ```
///
/// When used as a slicing index, `RangeToInclusive` produces a slice of all
/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
/// array elements up to and including the index indicated by `end`.
///
/// ```
/// #![feature(inclusive_range_syntax)]
///
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive
/// assert_eq!(arr[1...2], [ 1,2 ]);
/// ```
///
/// [`IntoIterator`]: ../iter/trait.Iterator.html
/// [`Iterator`]: ../iter/trait.IntoIterator.html
/// [slicing index]: ../slice/trait.SliceIndex.html
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
pub struct RangeToInclusive<Idx> {
@ -348,15 +363,16 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
///
/// ```
/// #![feature(range_contains,inclusive_range_syntax)]
/// fn main() {
/// assert!( (...5).contains(-1_000_000_000));
/// assert!( (...5).contains(5));
/// assert!( ! (...5).contains(6));
/// }
///
/// assert!( (...5).contains(-1_000_000_000));
/// assert!( (...5).contains(5));
/// assert!(!(...5).contains(6));
/// ```
pub fn contains(&self, item: Idx) -> bool {
(item <= self.end)