From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- library/core/src/ops/arith.rs | 1029 +++++++++++++++++++++++++++++++++ library/core/src/ops/bit.rs | 1044 ++++++++++++++++++++++++++++++++++ library/core/src/ops/control_flow.rs | 299 ++++++++++ library/core/src/ops/deref.rs | 199 +++++++ library/core/src/ops/drop.rs | 165 ++++++ library/core/src/ops/function.rs | 304 ++++++++++ library/core/src/ops/generator.rs | 136 +++++ library/core/src/ops/index.rs | 175 ++++++ library/core/src/ops/mod.rs | 208 +++++++ library/core/src/ops/range.rs | 991 ++++++++++++++++++++++++++++++++ library/core/src/ops/try_trait.rs | 418 ++++++++++++++ library/core/src/ops/unsize.rs | 132 +++++ 12 files changed, 5100 insertions(+) create mode 100644 library/core/src/ops/arith.rs create mode 100644 library/core/src/ops/bit.rs create mode 100644 library/core/src/ops/control_flow.rs create mode 100644 library/core/src/ops/deref.rs create mode 100644 library/core/src/ops/drop.rs create mode 100644 library/core/src/ops/function.rs create mode 100644 library/core/src/ops/generator.rs create mode 100644 library/core/src/ops/index.rs create mode 100644 library/core/src/ops/mod.rs create mode 100644 library/core/src/ops/range.rs create mode 100644 library/core/src/ops/try_trait.rs create mode 100644 library/core/src/ops/unsize.rs (limited to 'library/core/src/ops') diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs new file mode 100644 index 000000000..e367be8c1 --- /dev/null +++ b/library/core/src/ops/arith.rs @@ -0,0 +1,1029 @@ +/// The addition operator `+`. +/// +/// 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 +/// +/// # Examples +/// +/// ## `Add`able points +/// +/// ``` +/// use std::ops::Add; +/// +/// #[derive(Debug, Copy, Clone, PartialEq)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl Add for Point { +/// type Output = Self; +/// +/// fn add(self, other: Self) -> Self { +/// Self { +/// x: self.x + other.x, +/// y: self.y + other.y, +/// } +/// } +/// } +/// +/// 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, Copy, Clone, PartialEq)] +/// struct Point { +/// x: T, +/// y: T, +/// } +/// +/// // Notice that the implementation uses the associated type `Output`. +/// impl> Add for Point { +/// type Output = Self; +/// +/// fn add(self, other: Self) -> Self::Output { +/// Self { +/// x: self.x + other.x, +/// y: self.y + other.y, +/// } +/// } +/// } +/// +/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, +/// Point { x: 3, y: 3 }); +/// ``` +#[lang = "add"] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr( + bootstrap, + rustc_on_unimplemented( + on( + all(_Self = "{integer}", Rhs = "{float}"), + message = "cannot add a float to an integer", + ), + on( + all(_Self = "{float}", Rhs = "{integer}"), + message = "cannot add an integer to a float", + ), + message = "cannot add `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} + {Rhs}`" + ) +)] +#[cfg_attr( + not(bootstrap), + rustc_on_unimplemented( + on( + all(_Self = "{integer}", Rhs = "{float}"), + message = "cannot add a float to an integer", + ), + on( + all(_Self = "{float}", Rhs = "{integer}"), + message = "cannot add an integer to a float", + ), + message = "cannot add `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} + {Rhs}`", + append_const_msg, + ) +)] +#[doc(alias = "+")] +pub trait Add { + /// The resulting type after applying the `+` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `+` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 + 1, 13); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn add(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! add_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Add for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn add(self, other: $t) -> $t { self + other } + } + + forward_ref_binop! { impl const Add, add for $t, $t } + )*) +} + +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`, which permits +/// operations of the form `SystemTime = SystemTime - Duration`. +/// +/// [`std::time::SystemTime`]: ../../std/time/struct.SystemTime.html +/// +/// # Examples +/// +/// ## `Sub`tractable points +/// +/// ``` +/// use std::ops::Sub; +/// +/// #[derive(Debug, Copy, Clone, PartialEq)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl Sub for Point { +/// type Output = Self; +/// +/// fn sub(self, other: Self) -> Self::Output { +/// Self { +/// x: self.x - other.x, +/// y: self.y - other.y, +/// } +/// } +/// } +/// +/// 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, PartialEq)] +/// struct Point { +/// x: T, +/// y: T, +/// } +/// +/// // Notice that the implementation uses the associated type `Output`. +/// impl> Sub for Point { +/// type Output = Self; +/// +/// fn sub(self, other: Self) -> Self::Output { +/// Point { +/// x: self.x - other.x, +/// y: self.y - other.y, +/// } +/// } +/// } +/// +/// assert_eq!(Point { x: 2, y: 3 } - Point { x: 1, y: 0 }, +/// Point { x: 1, y: 3 }); +/// ``` +#[lang = "sub"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "cannot subtract `{Rhs}` from `{Self}`", + label = "no implementation for `{Self} - {Rhs}`" +)] +#[doc(alias = "-")] +pub trait Sub { + /// The resulting type after applying the `-` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `-` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 - 1, 11); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn sub(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! sub_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Sub for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn sub(self, other: $t) -> $t { self - other } + } + + forward_ref_binop! { impl const Sub, sub for $t, $t } + )*) +} + +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 +/// +/// ## `Mul`tipliable rational numbers +/// +/// ``` +/// use std::ops::Mul; +/// +/// // 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 { +/// numerator: usize, +/// denominator: usize, +/// } +/// +/// impl Rational { +/// fn new(numerator: usize, denominator: usize) -> Self { +/// if denominator == 0 { +/// panic!("Zero is an invalid denominator!"); +/// } +/// +/// // Reduce to lowest terms by dividing by the greatest common +/// // divisor. +/// let gcd = gcd(numerator, denominator); +/// Self { +/// numerator: numerator / gcd, +/// denominator: denominator / gcd, +/// } +/// } +/// } +/// +/// impl Mul for Rational { +/// // The multiplication of rational numbers is a closed operation. +/// type Output = Self; +/// +/// fn mul(self, rhs: Self) -> Self { +/// let numerator = self.numerator * rhs.numerator; +/// let denominator = self.denominator * rhs.denominator; +/// Self::new(numerator, denominator) +/// } +/// } +/// +/// // Euclid's two-thousand-year-old algorithm for finding the greatest common +/// // divisor. +/// fn gcd(x: usize, y: usize) -> usize { +/// let mut x = x; +/// let mut y = y; +/// while y != 0 { +/// let t = y; +/// y = x % y; +/// x = t; +/// } +/// x +/// } +/// +/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); +/// assert_eq!(Rational::new(2, 3) * Rational::new(3, 4), +/// Rational::new(1, 2)); +/// ``` +/// +/// ## Multiplying vectors by scalars as in linear algebra +/// +/// ``` +/// use std::ops::Mul; +/// +/// struct Scalar { value: usize } +/// +/// #[derive(Debug, PartialEq)] +/// struct Vector { value: Vec } +/// +/// impl Mul for Vector { +/// type Output = Self; +/// +/// fn mul(self, rhs: Scalar) -> Self::Output { +/// Self { value: self.value.iter().map(|v| v * rhs.value).collect() } +/// } +/// } +/// +/// 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( + message = "cannot multiply `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} * {Rhs}`" +)] +#[doc(alias = "*")] +pub trait Mul { + /// The resulting type after applying the `*` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `*` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 * 2, 24); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn mul(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! mul_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Mul for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn mul(self, other: $t) -> $t { self * other } + } + + forward_ref_binop! { impl const Mul, mul for $t, $t } + )*) +} + +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 +/// +/// ## `Div`idable rational numbers +/// +/// ``` +/// use std::ops::Div; +/// +/// // 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 { +/// numerator: usize, +/// denominator: usize, +/// } +/// +/// impl Rational { +/// fn new(numerator: usize, denominator: usize) -> Self { +/// if denominator == 0 { +/// panic!("Zero is an invalid denominator!"); +/// } +/// +/// // Reduce to lowest terms by dividing by the greatest common +/// // divisor. +/// let gcd = gcd(numerator, denominator); +/// Self { +/// numerator: numerator / gcd, +/// denominator: denominator / gcd, +/// } +/// } +/// } +/// +/// impl Div for Rational { +/// // The division of rational numbers is a closed operation. +/// type Output = Self; +/// +/// fn div(self, rhs: Self) -> Self::Output { +/// if rhs.numerator == 0 { +/// panic!("Cannot divide by zero-valued `Rational`!"); +/// } +/// +/// let numerator = self.numerator * rhs.denominator; +/// let denominator = self.denominator * rhs.numerator; +/// Self::new(numerator, denominator) +/// } +/// } +/// +/// // Euclid's two-thousand-year-old algorithm for finding the greatest common +/// // divisor. +/// fn gcd(x: usize, y: usize) -> usize { +/// let mut x = x; +/// let mut y = y; +/// while y != 0 { +/// let t = y; +/// y = x % y; +/// x = t; +/// } +/// x +/// } +/// +/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); +/// assert_eq!(Rational::new(1, 2) / Rational::new(3, 4), +/// Rational::new(2, 3)); +/// ``` +/// +/// ## Dividing vectors by scalars as in linear algebra +/// +/// ``` +/// use std::ops::Div; +/// +/// struct Scalar { value: f32 } +/// +/// #[derive(Debug, PartialEq)] +/// struct Vector { value: Vec } +/// +/// impl Div for Vector { +/// type Output = Self; +/// +/// fn div(self, rhs: Scalar) -> Self::Output { +/// Self { value: self.value.iter().map(|v| v / rhs.value).collect() } +/// } +/// } +/// +/// let scalar = Scalar { value: 2f32 }; +/// let vector = Vector { value: vec![2f32, 4f32, 6f32] }; +/// assert_eq!(vector / scalar, Vector { value: vec![1f32, 2f32, 3f32] }); +/// ``` +#[lang = "div"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "cannot divide `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} / {Rhs}`" +)] +#[doc(alias = "/")] +pub trait Div { + /// The resulting type after applying the `/` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `/` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 / 2, 6); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn div(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! div_impl_integer { + ($(($($t:ty)*) => $panic:expr),*) => ($($( + /// This operation rounds towards zero, truncating any + /// fractional part of the exact result. + /// + /// # Panics + /// + #[doc = $panic] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Div for $t { + type Output = $t; + + #[inline] + fn div(self, other: $t) -> $t { self / other } + } + + forward_ref_binop! { impl const Div, div for $t, $t } + )*)*) +} + +div_impl_integer! { + (usize u8 u16 u32 u64 u128) => "This operation will panic if `other == 0`.", + (isize i8 i16 i32 i64 i128) => "This operation will panic if `other == 0` or the division results in overflow." +} + +macro_rules! div_impl_float { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Div for $t { + type Output = $t; + + #[inline] + fn div(self, other: $t) -> $t { self / other } + } + + forward_ref_binop! { impl const Div, div for $t, $t } + )*) +} + +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 +/// implemented, one can use the `%` operator to find out what the remaining +/// elements of the slice would be after splitting it into equal slices of a +/// given length. +/// +/// ``` +/// use std::ops::Rem; +/// +/// #[derive(PartialEq, Debug)] +/// struct SplitSlice<'a, T: 'a> { +/// slice: &'a [T], +/// } +/// +/// impl<'a, T> Rem for SplitSlice<'a, T> { +/// type Output = Self; +/// +/// fn rem(self, modulus: usize) -> Self::Output { +/// let len = self.slice.len(); +/// let rem = len % modulus; +/// let start = len - rem; +/// Self {slice: &self.slice[start..]} +/// } +/// } +/// +/// // If we were to divide &[0, 1, 2, 3, 4, 5, 6, 7] into slices of size 3, +/// // the remainder would be &[6, 7]. +/// assert_eq!(SplitSlice { slice: &[0, 1, 2, 3, 4, 5, 6, 7] } % 3, +/// SplitSlice { slice: &[6, 7] }); +/// ``` +#[lang = "rem"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "cannot mod `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} % {Rhs}`" +)] +#[doc(alias = "%")] +pub trait Rem { + /// The resulting type after applying the `%` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `%` operation. + /// + /// # Example + /// + /// ``` + /// assert_eq!(12 % 10, 2); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn rem(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! rem_impl_integer { + ($(($($t:ty)*) => $panic:expr),*) => ($($( + /// This operation satisfies `n % d == n - (n / d) * d`. The + /// result has the same sign as the left operand. + /// + /// # Panics + /// + #[doc = $panic] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Rem for $t { + type Output = $t; + + #[inline] + fn rem(self, other: $t) -> $t { self % other } + } + + forward_ref_binop! { impl const Rem, rem for $t, $t } + )*)*) +} + +rem_impl_integer! { + (usize u8 u16 u32 u64 u128) => "This operation will panic if `other == 0`.", + (isize i8 i16 i32 i64 i128) => "This operation will panic if `other == 0` or if `self / other` results in overflow." +} + +macro_rules! rem_impl_float { + ($($t:ty)*) => ($( + + /// The remainder from the division of two floats. + /// + /// The remainder has the same sign as the dividend and is computed as: + /// `x - (x / y).trunc() * y`. + /// + /// # Examples + /// ``` + /// let x: f32 = 50.50; + /// let y: f32 = 8.125; + /// let remainder = x - (x / y).trunc() * y; + /// + /// // The answer to both operations is 1.75 + /// assert_eq!(x % y, remainder); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Rem for $t { + type Output = $t; + + #[inline] + fn rem(self, other: $t) -> $t { self % other } + } + + forward_ref_binop! { impl const Rem, rem for $t, $t } + )*) +} + +rem_impl_float! { f32 f64 } + +/// The unary negation operator `-`. +/// +/// # Examples +/// +/// An implementation of `Neg` for `Sign`, which allows the use of `-` to +/// negate its value. +/// +/// ``` +/// use std::ops::Neg; +/// +/// #[derive(Debug, PartialEq)] +/// enum Sign { +/// Negative, +/// Zero, +/// Positive, +/// } +/// +/// impl Neg for Sign { +/// type Output = Self; +/// +/// fn neg(self) -> Self::Output { +/// match self { +/// Sign::Negative => Sign::Positive, +/// Sign::Zero => Sign::Zero, +/// Sign::Positive => Sign::Negative, +/// } +/// } +/// } +/// +/// // A negative positive is a negative. +/// assert_eq!(-Sign::Positive, Sign::Negative); +/// // A double negative is a positive. +/// assert_eq!(-Sign::Negative, Sign::Positive); +/// // Zero is its own negation. +/// assert_eq!(-Sign::Zero, Sign::Zero); +/// ``` +#[lang = "neg"] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "-")] +pub trait Neg { + /// The resulting type after applying the `-` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the unary `-` operation. + /// + /// # Example + /// + /// ``` + /// let x: i32 = 12; + /// assert_eq!(-x, -12); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn neg(self) -> Self::Output; +} + +macro_rules! neg_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Neg for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn neg(self) -> $t { -self } + } + + forward_ref_unop! { impl const Neg, neg for $t } + )*) +} + +neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 } + +/// The addition assignment operator `+=`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `AddAssign` +/// trait, and then demonstrates add-assigning to a mutable `Point`. +/// +/// ``` +/// use std::ops::AddAssign; +/// +/// #[derive(Debug, Copy, Clone, PartialEq)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl AddAssign for Point { +/// fn add_assign(&mut self, other: Self) { +/// *self = Self { +/// x: self.x + other.x, +/// y: 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 }); +/// ``` +#[lang = "add_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented( + message = "cannot add-assign `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} += {Rhs}`" +)] +#[doc(alias = "+")] +#[doc(alias = "+=")] +pub trait AddAssign { + /// Performs the `+=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x += 1; + /// assert_eq!(x, 13); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn add_assign(&mut self, rhs: Rhs); +} + +macro_rules! add_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const AddAssign for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn add_assign(&mut self, other: $t) { *self += other } + } + + forward_ref_op_assign! { impl const AddAssign, add_assign for $t, $t } + )+) +} + +add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The subtraction assignment operator `-=`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `SubAssign` +/// trait, and then demonstrates sub-assigning to a mutable `Point`. +/// +/// ``` +/// use std::ops::SubAssign; +/// +/// #[derive(Debug, Copy, Clone, PartialEq)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl SubAssign for Point { +/// fn sub_assign(&mut self, other: Self) { +/// *self = Self { +/// x: self.x - other.x, +/// y: 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}); +/// ``` +#[lang = "sub_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented( + message = "cannot subtract-assign `{Rhs}` from `{Self}`", + label = "no implementation for `{Self} -= {Rhs}`" +)] +#[doc(alias = "-")] +#[doc(alias = "-=")] +pub trait SubAssign { + /// Performs the `-=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x -= 1; + /// assert_eq!(x, 11); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn sub_assign(&mut self, rhs: Rhs); +} + +macro_rules! sub_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const SubAssign for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn sub_assign(&mut self, other: $t) { *self -= other } + } + + forward_ref_op_assign! { impl const SubAssign, sub_assign for $t, $t } + )+) +} + +sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The multiplication assignment operator `*=`. +/// +/// # Examples +/// +/// ``` +/// use std::ops::MulAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Frequency { hertz: f64 } +/// +/// impl MulAssign for Frequency { +/// fn mul_assign(&mut self, rhs: f64) { +/// self.hertz *= rhs; +/// } +/// } +/// +/// 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( + message = "cannot multiply-assign `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} *= {Rhs}`" +)] +#[doc(alias = "*")] +#[doc(alias = "*=")] +pub trait MulAssign { + /// Performs the `*=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x *= 2; + /// assert_eq!(x, 24); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn mul_assign(&mut self, rhs: Rhs); +} + +macro_rules! mul_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const MulAssign for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn mul_assign(&mut self, other: $t) { *self *= other } + } + + forward_ref_op_assign! { impl const MulAssign, mul_assign for $t, $t } + )+) +} + +mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The division assignment operator `/=`. +/// +/// # Examples +/// +/// ``` +/// use std::ops::DivAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Frequency { hertz: f64 } +/// +/// impl DivAssign for Frequency { +/// fn div_assign(&mut self, rhs: f64) { +/// self.hertz /= rhs; +/// } +/// } +/// +/// 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( + message = "cannot divide-assign `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} /= {Rhs}`" +)] +#[doc(alias = "/")] +#[doc(alias = "/=")] +pub trait DivAssign { + /// Performs the `/=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x /= 2; + /// assert_eq!(x, 6); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn div_assign(&mut self, rhs: Rhs); +} + +macro_rules! div_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const DivAssign for $t { + #[inline] + fn div_assign(&mut self, other: $t) { *self /= other } + } + + forward_ref_op_assign! { impl const DivAssign, div_assign for $t, $t } + )+) +} + +div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The remainder assignment operator `%=`. +/// +/// # Examples +/// +/// ``` +/// use std::ops::RemAssign; +/// +/// struct CookieJar { cookies: u32 } +/// +/// impl RemAssign for CookieJar { +/// fn rem_assign(&mut self, piles: u32) { +/// self.cookies %= piles; +/// } +/// } +/// +/// 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( + message = "cannot mod-assign `{Self}` by `{Rhs}``", + label = "no implementation for `{Self} %= {Rhs}`" +)] +#[doc(alias = "%")] +#[doc(alias = "%=")] +pub trait RemAssign { + /// Performs the `%=` operation. + /// + /// # Example + /// + /// ``` + /// let mut x: u32 = 12; + /// x %= 10; + /// assert_eq!(x, 2); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn rem_assign(&mut self, rhs: Rhs); +} + +macro_rules! rem_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const RemAssign for $t { + #[inline] + fn rem_assign(&mut self, other: $t) { *self %= other } + } + + forward_ref_op_assign! { impl const RemAssign, rem_assign for $t, $t } + )+) +} + +rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs new file mode 100644 index 000000000..7c664226f --- /dev/null +++ b/library/core/src/ops/bit.rs @@ -0,0 +1,1044 @@ +/// The unary logical negation operator `!`. +/// +/// # Examples +/// +/// An implementation of `Not` for `Answer`, which enables the use of `!` to +/// invert its value. +/// +/// ``` +/// use std::ops::Not; +/// +/// #[derive(Debug, PartialEq)] +/// enum Answer { +/// Yes, +/// No, +/// } +/// +/// impl Not for Answer { +/// type Output = Self; +/// +/// fn not(self) -> Self::Output { +/// match self { +/// Answer::Yes => Answer::No, +/// Answer::No => Answer::Yes +/// } +/// } +/// } +/// +/// assert_eq!(!Answer::Yes, Answer::No); +/// assert_eq!(!Answer::No, Answer::Yes); +/// ``` +#[lang = "not"] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "!")] +pub trait Not { + /// The resulting type after applying the `!` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the unary `!` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(!true, false); + /// assert_eq!(!false, true); + /// assert_eq!(!1u8, 254); + /// assert_eq!(!0u8, 255); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn not(self) -> Self::Output; +} + +macro_rules! not_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Not for $t { + type Output = $t; + + #[inline] + fn not(self) -> $t { !self } + } + + forward_ref_unop! { impl const Not, not for $t } + )*) +} + +not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +#[stable(feature = "not_never", since = "1.60.0")] +#[rustc_const_unstable(feature = "const_ops", issue = "90080")] +impl const Not for ! { + type Output = !; + + #[inline] + fn not(self) -> ! { + match self {} + } +} + +/// 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`. +/// +/// ``` +/// use std::ops::BitAnd; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitAnd for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a & b` +/// fn bitand(self, rhs: Self) -> Self::Output { +/// Self(self.0 & rhs.0) +/// } +/// } +/// +/// 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)); +/// ``` +/// +/// An implementation of `BitAnd` for a wrapper around `Vec`. +/// +/// ``` +/// use std::ops::BitAnd; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitAnd for BooleanVector { +/// type Output = Self; +/// +/// fn bitand(self, Self(rhs): Self) -> Self::Output { +/// let Self(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// Self( +/// lhs.iter() +/// .zip(rhs.iter()) +/// .map(|(x, y)| *x & *y) +/// .collect() +/// ) +/// } +/// } +/// +/// 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"] +#[doc(alias = "&")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "no implementation for `{Self} & {Rhs}`", + label = "no implementation for `{Self} & {Rhs}`" +)] +pub trait BitAnd { + /// The resulting type after applying the `&` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `&` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(true & false, false); + /// assert_eq!(true & true, true); + /// assert_eq!(5u8 & 1u8, 1); + /// assert_eq!(5u8 & 2u8, 0); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn bitand(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! bitand_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitAnd for $t { + type Output = $t; + + #[inline] + fn bitand(self, rhs: $t) -> $t { self & rhs } + } + + forward_ref_binop! { impl const BitAnd, bitand for $t, $t } + )*) +} + +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`. +/// +/// ``` +/// use std::ops::BitOr; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitOr for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a | b` +/// fn bitor(self, rhs: Self) -> Self::Output { +/// Self(self.0 | rhs.0) +/// } +/// } +/// +/// 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)); +/// ``` +/// +/// An implementation of `BitOr` for a wrapper around `Vec`. +/// +/// ``` +/// use std::ops::BitOr; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitOr for BooleanVector { +/// type Output = Self; +/// +/// fn bitor(self, Self(rhs): Self) -> Self::Output { +/// let Self(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// Self( +/// lhs.iter() +/// .zip(rhs.iter()) +/// .map(|(x, y)| *x | *y) +/// .collect() +/// ) +/// } +/// } +/// +/// 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"] +#[doc(alias = "|")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "no implementation for `{Self} | {Rhs}`", + label = "no implementation for `{Self} | {Rhs}`" +)] +pub trait BitOr { + /// The resulting type after applying the `|` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `|` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(true | false, true); + /// assert_eq!(false | false, false); + /// assert_eq!(5u8 | 1u8, 5); + /// assert_eq!(5u8 | 2u8, 7); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn bitor(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! bitor_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitOr for $t { + type Output = $t; + + #[inline] + fn bitor(self, rhs: $t) -> $t { self | rhs } + } + + forward_ref_binop! { impl const BitOr, bitor for $t, $t } + )*) +} + +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`. +/// +/// ``` +/// use std::ops::BitXor; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitXor for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a ^ b` +/// fn bitxor(self, rhs: Self) -> Self::Output { +/// Self(self.0 ^ rhs.0) +/// } +/// } +/// +/// 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)); +/// ``` +/// +/// An implementation of `BitXor` trait for a wrapper around `Vec`. +/// +/// ``` +/// use std::ops::BitXor; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitXor for BooleanVector { +/// type Output = Self; +/// +/// fn bitxor(self, Self(rhs): Self) -> Self::Output { +/// let Self(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// Self( +/// lhs.iter() +/// .zip(rhs.iter()) +/// .map(|(x, y)| *x ^ *y) +/// .collect() +/// ) +/// } +/// } +/// +/// 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"] +#[doc(alias = "^")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "no implementation for `{Self} ^ {Rhs}`", + label = "no implementation for `{Self} ^ {Rhs}`" +)] +pub trait BitXor { + /// The resulting type after applying the `^` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `^` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(true ^ false, true); + /// assert_eq!(true ^ true, false); + /// assert_eq!(5u8 ^ 1u8, 4); + /// assert_eq!(5u8 ^ 2u8, 7); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn bitxor(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! bitxor_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitXor for $t { + type Output = $t; + + #[inline] + fn bitxor(self, other: $t) -> $t { self ^ other } + } + + forward_ref_binop! { impl const BitXor, bitxor for $t, $t } + )*) +} + +bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The left shift operator `<<`. Note that because this trait is implemented +/// for all integer types with multiple right-hand-side types, Rust's type +/// checker has special handling for `_ << _`, setting the result type for +/// integer operations to the type of the left-hand-side operand. This means +/// that though `a << b` and `a.shl(b)` are one and the same from an evaluation +/// standpoint, they are different when it comes to type inference. +/// +/// # Examples +/// +/// An implementation of `Shl` that lifts the `<<` operation on integers to a +/// wrapper around `usize`. +/// +/// ``` +/// use std::ops::Shl; +/// +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); +/// +/// impl Shl for Scalar { +/// type Output = Self; +/// +/// fn shl(self, Self(rhs): Self) -> Self::Output { +/// let Self(lhs) = self; +/// Self(lhs << rhs) +/// } +/// } +/// +/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16)); +/// ``` +/// +/// An implementation of `Shl` that spins a vector leftward by a given amount. +/// +/// ``` +/// use std::ops::Shl; +/// +/// #[derive(PartialEq, Debug)] +/// struct SpinVector { +/// vec: Vec, +/// } +/// +/// impl Shl for SpinVector { +/// type Output = Self; +/// +/// fn shl(self, rhs: usize) -> Self::Output { +/// // Rotate the vector by `rhs` places. +/// let (a, b) = self.vec.split_at(rhs); +/// let mut spun_vector = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// Self { vec: spun_vector } +/// } +/// } +/// +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2, +/// SpinVector { vec: vec![2, 3, 4, 0, 1] }); +/// ``` +#[lang = "shl"] +#[doc(alias = "<<")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "no implementation for `{Self} << {Rhs}`", + label = "no implementation for `{Self} << {Rhs}`" +)] +pub trait Shl { + /// The resulting type after applying the `<<` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `<<` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(5u8 << 1, 10); + /// assert_eq!(1u8 << 1, 2); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn shl(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! shl_impl { + ($t:ty, $f:ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Shl<$f> for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn shl(self, other: $f) -> $t { + self << other + } + } + + forward_ref_binop! { impl const Shl, shl for $t, $f } + }; +} + +macro_rules! shl_impl_all { + ($($t:ty)*) => ($( + shl_impl! { $t, u8 } + shl_impl! { $t, u16 } + shl_impl! { $t, u32 } + shl_impl! { $t, u64 } + shl_impl! { $t, u128 } + shl_impl! { $t, usize } + + shl_impl! { $t, i8 } + shl_impl! { $t, i16 } + shl_impl! { $t, i32 } + shl_impl! { $t, i64 } + shl_impl! { $t, i128 } + shl_impl! { $t, isize } + )*) +} + +shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } + +/// The right shift operator `>>`. Note that because this trait is implemented +/// for all integer types with multiple right-hand-side types, Rust's type +/// checker has special handling for `_ >> _`, setting the result type for +/// integer operations to the type of the left-hand-side operand. This means +/// that though `a >> b` and `a.shr(b)` are one and the same from an evaluation +/// standpoint, they are different when it comes to type inference. +/// +/// # Examples +/// +/// An implementation of `Shr` that lifts the `>>` operation on integers to a +/// wrapper around `usize`. +/// +/// ``` +/// use std::ops::Shr; +/// +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); +/// +/// impl Shr for Scalar { +/// type Output = Self; +/// +/// fn shr(self, Self(rhs): Self) -> Self::Output { +/// let Self(lhs) = self; +/// Self(lhs >> rhs) +/// } +/// } +/// +/// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4)); +/// ``` +/// +/// An implementation of `Shr` that spins a vector rightward by a given amount. +/// +/// ``` +/// use std::ops::Shr; +/// +/// #[derive(PartialEq, Debug)] +/// struct SpinVector { +/// vec: Vec, +/// } +/// +/// impl Shr for SpinVector { +/// type Output = Self; +/// +/// fn shr(self, rhs: usize) -> Self::Output { +/// // Rotate the vector by `rhs` places. +/// let (a, b) = self.vec.split_at(self.vec.len() - rhs); +/// let mut spun_vector = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// Self { vec: spun_vector } +/// } +/// } +/// +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2, +/// SpinVector { vec: vec![3, 4, 0, 1, 2] }); +/// ``` +#[lang = "shr"] +#[doc(alias = ">>")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "no implementation for `{Self} >> {Rhs}`", + label = "no implementation for `{Self} >> {Rhs}`" +)] +pub trait Shr { + /// The resulting type after applying the `>>` operator. + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// Performs the `>>` operation. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(5u8 >> 1, 2); + /// assert_eq!(2u8 >> 1, 1); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn shr(self, rhs: Rhs) -> Self::Output; +} + +macro_rules! shr_impl { + ($t:ty, $f:ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Shr<$f> for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn shr(self, other: $f) -> $t { + self >> other + } + } + + forward_ref_binop! { impl const Shr, shr for $t, $f } + }; +} + +macro_rules! shr_impl_all { + ($($t:ty)*) => ($( + shr_impl! { $t, u8 } + shr_impl! { $t, u16 } + shr_impl! { $t, u32 } + shr_impl! { $t, u64 } + shr_impl! { $t, u128 } + shr_impl! { $t, usize } + + shr_impl! { $t, i8 } + shr_impl! { $t, i16 } + shr_impl! { $t, i32 } + shr_impl! { $t, i64 } + shr_impl! { $t, i128 } + shr_impl! { $t, isize } + )*) +} + +shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } + +/// The bitwise AND assignment operator `&=`. +/// +/// # Examples +/// +/// An implementation of `BitAndAssign` that lifts the `&=` operator to a +/// wrapper around `bool`. +/// +/// ``` +/// use std::ops::BitAndAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitAndAssign for Scalar { +/// // rhs is the "right-hand side" of the expression `a &= b` +/// fn bitand_assign(&mut self, rhs: Self) { +/// *self = Self(self.0 & rhs.0) +/// } +/// } +/// +/// 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(false); +/// scalar &= Scalar(true); +/// assert_eq!(scalar, Scalar(false)); +/// +/// let mut scalar = Scalar(false); +/// scalar &= Scalar(false); +/// assert_eq!(scalar, Scalar(false)); +/// ``` +/// +/// Here, the `BitAndAssign` trait is implemented for a wrapper around +/// `Vec`. +/// +/// ``` +/// use std::ops::BitAndAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitAndAssign for BooleanVector { +/// // `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 = Self( +/// self.0 +/// .iter() +/// .zip(rhs.0.iter()) +/// .map(|(x, y)| *x & *y) +/// .collect() +/// ); +/// } +/// } +/// +/// 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"] +#[doc(alias = "&=")] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented( + message = "no implementation for `{Self} &= {Rhs}`", + label = "no implementation for `{Self} &= {Rhs}`" +)] +pub trait BitAndAssign { + /// Performs the `&=` operation. + /// + /// # Examples + /// + /// ``` + /// let mut x = true; + /// x &= false; + /// assert_eq!(x, false); + /// + /// let mut x = true; + /// x &= true; + /// assert_eq!(x, true); + /// + /// let mut x: u8 = 5; + /// x &= 1; + /// assert_eq!(x, 1); + /// + /// let mut x: u8 = 5; + /// x &= 2; + /// assert_eq!(x, 0); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitand_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitand_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitAndAssign for $t { + #[inline] + fn bitand_assign(&mut self, other: $t) { *self &= other } + } + + forward_ref_op_assign! { impl const BitAndAssign, bitand_assign for $t, $t } + )+) +} + +bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise OR assignment operator `|=`. +/// +/// # Examples +/// +/// ``` +/// use std::ops::BitOrAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct PersonalPreferences { +/// likes_cats: bool, +/// likes_dogs: bool, +/// } +/// +/// impl BitOrAssign for PersonalPreferences { +/// fn bitor_assign(&mut self, rhs: Self) { +/// self.likes_cats |= rhs.likes_cats; +/// self.likes_dogs |= rhs.likes_dogs; +/// } +/// } +/// +/// 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"] +#[doc(alias = "|=")] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented( + message = "no implementation for `{Self} |= {Rhs}`", + label = "no implementation for `{Self} |= {Rhs}`" +)] +pub trait BitOrAssign { + /// Performs the `|=` operation. + /// + /// # Examples + /// + /// ``` + /// let mut x = true; + /// x |= false; + /// assert_eq!(x, true); + /// + /// let mut x = false; + /// x |= false; + /// assert_eq!(x, false); + /// + /// let mut x: u8 = 5; + /// x |= 1; + /// assert_eq!(x, 5); + /// + /// let mut x: u8 = 5; + /// x |= 2; + /// assert_eq!(x, 7); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitor_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitor_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitOrAssign for $t { + #[inline] + fn bitor_assign(&mut self, other: $t) { *self |= other } + } + + forward_ref_op_assign! { impl const BitOrAssign, bitor_assign for $t, $t } + )+) +} + +bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise XOR assignment operator `^=`. +/// +/// # Examples +/// +/// ``` +/// use std::ops::BitXorAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Personality { +/// has_soul: bool, +/// likes_knitting: bool, +/// } +/// +/// impl BitXorAssign for Personality { +/// fn bitxor_assign(&mut self, rhs: Self) { +/// self.has_soul ^= rhs.has_soul; +/// self.likes_knitting ^= rhs.likes_knitting; +/// } +/// } +/// +/// 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"] +#[doc(alias = "^=")] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented( + message = "no implementation for `{Self} ^= {Rhs}`", + label = "no implementation for `{Self} ^= {Rhs}`" +)] +pub trait BitXorAssign { + /// Performs the `^=` operation. + /// + /// # Examples + /// + /// ``` + /// let mut x = true; + /// x ^= false; + /// assert_eq!(x, true); + /// + /// let mut x = true; + /// x ^= true; + /// assert_eq!(x, false); + /// + /// let mut x: u8 = 5; + /// x ^= 1; + /// assert_eq!(x, 4); + /// + /// let mut x: u8 = 5; + /// x ^= 2; + /// assert_eq!(x, 7); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitxor_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitxor_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const BitXorAssign for $t { + #[inline] + fn bitxor_assign(&mut self, other: $t) { *self ^= other } + } + + forward_ref_op_assign! { impl const BitXorAssign, bitxor_assign for $t, $t } + )+) +} + +bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The left shift assignment operator `<<=`. +/// +/// # Examples +/// +/// An implementation of `ShlAssign` for a wrapper around `usize`. +/// +/// ``` +/// use std::ops::ShlAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(usize); +/// +/// impl ShlAssign for Scalar { +/// fn shl_assign(&mut self, rhs: usize) { +/// self.0 <<= rhs; +/// } +/// } +/// +/// let mut scalar = Scalar(4); +/// scalar <<= 2; +/// assert_eq!(scalar, Scalar(16)); +/// ``` +#[lang = "shl_assign"] +#[doc(alias = "<<=")] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented( + message = "no implementation for `{Self} <<= {Rhs}`", + label = "no implementation for `{Self} <<= {Rhs}`" +)] +pub trait ShlAssign { + /// Performs the `<<=` operation. + /// + /// # Examples + /// + /// ``` + /// let mut x: u8 = 5; + /// x <<= 1; + /// assert_eq!(x, 10); + /// + /// let mut x: u8 = 1; + /// x <<= 1; + /// assert_eq!(x, 2); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn shl_assign(&mut self, rhs: Rhs); +} + +macro_rules! shl_assign_impl { + ($t:ty, $f:ty) => { + #[stable(feature = "op_assign_traits", since = "1.8.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const ShlAssign<$f> for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn shl_assign(&mut self, other: $f) { + *self <<= other + } + } + + forward_ref_op_assign! { impl const ShlAssign, shl_assign for $t, $f } + }; +} + +macro_rules! shl_assign_impl_all { + ($($t:ty)*) => ($( + shl_assign_impl! { $t, u8 } + shl_assign_impl! { $t, u16 } + shl_assign_impl! { $t, u32 } + shl_assign_impl! { $t, u64 } + shl_assign_impl! { $t, u128 } + shl_assign_impl! { $t, usize } + + shl_assign_impl! { $t, i8 } + shl_assign_impl! { $t, i16 } + shl_assign_impl! { $t, i32 } + shl_assign_impl! { $t, i64 } + shl_assign_impl! { $t, i128 } + shl_assign_impl! { $t, isize } + )*) +} + +shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } + +/// The right shift assignment operator `>>=`. +/// +/// # Examples +/// +/// An implementation of `ShrAssign` for a wrapper around `usize`. +/// +/// ``` +/// use std::ops::ShrAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(usize); +/// +/// impl ShrAssign for Scalar { +/// fn shr_assign(&mut self, rhs: usize) { +/// self.0 >>= rhs; +/// } +/// } +/// +/// let mut scalar = Scalar(16); +/// scalar >>= 2; +/// assert_eq!(scalar, Scalar(4)); +/// ``` +#[lang = "shr_assign"] +#[doc(alias = ">>=")] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented( + message = "no implementation for `{Self} >>= {Rhs}`", + label = "no implementation for `{Self} >>= {Rhs}`" +)] +pub trait ShrAssign { + /// Performs the `>>=` operation. + /// + /// # Examples + /// + /// ``` + /// let mut x: u8 = 5; + /// x >>= 1; + /// assert_eq!(x, 2); + /// + /// let mut x: u8 = 2; + /// x >>= 1; + /// assert_eq!(x, 1); + /// ``` + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn shr_assign(&mut self, rhs: Rhs); +} + +macro_rules! shr_assign_impl { + ($t:ty, $f:ty) => { + #[stable(feature = "op_assign_traits", since = "1.8.0")] + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const ShrAssign<$f> for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn shr_assign(&mut self, other: $f) { + *self >>= other + } + } + + forward_ref_op_assign! { impl const ShrAssign, shr_assign for $t, $f } + }; +} + +macro_rules! shr_assign_impl_all { + ($($t:ty)*) => ($( + shr_assign_impl! { $t, u8 } + shr_assign_impl! { $t, u16 } + shr_assign_impl! { $t, u32 } + shr_assign_impl! { $t, u64 } + shr_assign_impl! { $t, u128 } + shr_assign_impl! { $t, usize } + + shr_assign_impl! { $t, i8 } + shr_assign_impl! { $t, i16 } + shr_assign_impl! { $t, i32 } + shr_assign_impl! { $t, i64 } + shr_assign_impl! { $t, i128 } + shr_assign_impl! { $t, isize } + )*) +} + +shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs new file mode 100644 index 000000000..b1f5559dc --- /dev/null +++ b/library/core/src/ops/control_flow.rs @@ -0,0 +1,299 @@ +use crate::{convert, ops}; + +/// Used to tell an operation whether it should exit early or go on as usual. +/// +/// This is used when exposing things (like graph traversals or visitors) where +/// you want the user to be able to choose whether to exit early. +/// Having the enum makes it clearer -- no more wondering "wait, what did `false` +/// mean again?" -- and allows including a value. +/// +/// Similar to [`Option`] and [`Result`], this enum can be used with the `?` operator +/// to return immediately if the [`Break`] variant is present or otherwise continue normally +/// with the value inside the [`Continue`] variant. +/// +/// # Examples +/// +/// Early-exiting from [`Iterator::try_for_each`]: +/// ``` +/// use std::ops::ControlFlow; +/// +/// let r = (2..100).try_for_each(|x| { +/// if 403 % x == 0 { +/// return ControlFlow::Break(x) +/// } +/// +/// ControlFlow::Continue(()) +/// }); +/// assert_eq!(r, ControlFlow::Break(13)); +/// ``` +/// +/// A basic tree traversal: +/// ``` +/// use std::ops::ControlFlow; +/// +/// pub struct TreeNode { +/// value: T, +/// left: Option>>, +/// right: Option>>, +/// } +/// +/// impl TreeNode { +/// pub fn traverse_inorder(&self, f: &mut impl FnMut(&T) -> ControlFlow) -> ControlFlow { +/// if let Some(left) = &self.left { +/// left.traverse_inorder(f)?; +/// } +/// f(&self.value)?; +/// if let Some(right) = &self.right { +/// right.traverse_inorder(f)?; +/// } +/// ControlFlow::Continue(()) +/// } +/// fn leaf(value: T) -> Option>> { +/// Some(Box::new(Self { value, left: None, right: None })) +/// } +/// } +/// +/// let node = TreeNode { +/// value: 0, +/// left: TreeNode::leaf(1), +/// right: Some(Box::new(TreeNode { +/// value: -1, +/// left: TreeNode::leaf(5), +/// right: TreeNode::leaf(2), +/// })) +/// }; +/// let mut sum = 0; +/// +/// let res = node.traverse_inorder(&mut |val| { +/// if *val < 0 { +/// ControlFlow::Break(*val) +/// } else { +/// sum += *val; +/// ControlFlow::Continue(()) +/// } +/// }); +/// assert_eq!(res, ControlFlow::Break(-1)); +/// assert_eq!(sum, 6); +/// ``` +/// +/// [`Break`]: ControlFlow::Break +/// [`Continue`]: ControlFlow::Continue +#[stable(feature = "control_flow_enum_type", since = "1.55.0")] +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ControlFlow { + /// Move on to the next phase of the operation as normal. + #[stable(feature = "control_flow_enum_type", since = "1.55.0")] + #[lang = "Continue"] + Continue(C), + /// Exit the operation without running subsequent phases. + #[stable(feature = "control_flow_enum_type", since = "1.55.0")] + #[lang = "Break"] + Break(B), + // Yes, the order of the variants doesn't match the type parameters. + // They're in this order so that `ControlFlow` <-> `Result` + // is a no-op conversion in the `Try` implementation. +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::Try for ControlFlow { + type Output = C; + type Residual = ControlFlow; + + #[inline] + fn from_output(output: Self::Output) -> Self { + ControlFlow::Continue(output) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + ControlFlow::Continue(c) => ControlFlow::Continue(c), + ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "84277")] +impl ops::FromResidual for ControlFlow { + #[inline] + fn from_residual(residual: ControlFlow) -> Self { + match residual { + ControlFlow::Break(b) => ControlFlow::Break(b), + } + } +} + +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +impl ops::Residual for ControlFlow { + type TryType = ControlFlow; +} + +impl ControlFlow { + /// Returns `true` if this is a `Break` variant. + /// + /// # Examples + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// assert!(ControlFlow::::Break(3).is_break()); + /// assert!(!ControlFlow::::Continue(3).is_break()); + /// ``` + #[inline] + #[stable(feature = "control_flow_enum_is", since = "1.59.0")] + pub fn is_break(&self) -> bool { + matches!(*self, ControlFlow::Break(_)) + } + + /// Returns `true` if this is a `Continue` variant. + /// + /// # Examples + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// assert!(!ControlFlow::::Break(3).is_continue()); + /// assert!(ControlFlow::::Continue(3).is_continue()); + /// ``` + #[inline] + #[stable(feature = "control_flow_enum_is", since = "1.59.0")] + pub fn is_continue(&self) -> bool { + matches!(*self, ControlFlow::Continue(_)) + } + + /// Converts the `ControlFlow` into an `Option` which is `Some` if the + /// `ControlFlow` was `Break` and `None` otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_enum)] + /// use std::ops::ControlFlow; + /// + /// assert_eq!(ControlFlow::::Break(3).break_value(), Some(3)); + /// assert_eq!(ControlFlow::::Continue(3).break_value(), None); + /// ``` + #[inline] + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + pub fn break_value(self) -> Option { + match self { + ControlFlow::Continue(..) => None, + ControlFlow::Break(x) => Some(x), + } + } + + /// Maps `ControlFlow` to `ControlFlow` by applying a function + /// to the break value in case it exists. + #[inline] + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + pub fn map_break(self, f: F) -> ControlFlow + where + F: FnOnce(B) -> T, + { + match self { + ControlFlow::Continue(x) => ControlFlow::Continue(x), + ControlFlow::Break(x) => ControlFlow::Break(f(x)), + } + } + + /// Converts the `ControlFlow` into an `Option` which is `Some` if the + /// `ControlFlow` was `Continue` and `None` otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_enum)] + /// use std::ops::ControlFlow; + /// + /// assert_eq!(ControlFlow::::Break(3).continue_value(), None); + /// assert_eq!(ControlFlow::::Continue(3).continue_value(), Some(3)); + /// ``` + #[inline] + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + pub fn continue_value(self) -> Option { + match self { + ControlFlow::Continue(x) => Some(x), + ControlFlow::Break(..) => None, + } + } + + /// Maps `ControlFlow` to `ControlFlow` by applying a function + /// to the continue value in case it exists. + #[inline] + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + pub fn map_continue(self, f: F) -> ControlFlow + where + F: FnOnce(C) -> T, + { + match self { + ControlFlow::Continue(x) => ControlFlow::Continue(f(x)), + ControlFlow::Break(x) => ControlFlow::Break(x), + } + } +} + +/// These are used only as part of implementing the iterator adapters. +/// They have mediocre names and non-obvious semantics, so aren't +/// currently on a path to potential stabilization. +impl ControlFlow { + /// Create a `ControlFlow` from any type implementing `Try`. + #[inline] + pub(crate) fn from_try(r: R) -> Self { + match R::branch(r) { + ControlFlow::Continue(v) => ControlFlow::Continue(v), + ControlFlow::Break(v) => ControlFlow::Break(R::from_residual(v)), + } + } + + /// Convert a `ControlFlow` into any type implementing `Try`; + #[inline] + pub(crate) fn into_try(self) -> R { + match self { + ControlFlow::Continue(v) => R::from_output(v), + ControlFlow::Break(v) => v, + } + } +} + +impl ControlFlow { + /// It's frequently the case that there's no value needed with `Continue`, + /// so this provides a way to avoid typing `(())`, if you prefer it. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_enum)] + /// use std::ops::ControlFlow; + /// + /// let mut partial_sum = 0; + /// let last_used = (1..10).chain(20..25).try_for_each(|x| { + /// partial_sum += x; + /// if partial_sum > 100 { ControlFlow::Break(x) } + /// else { ControlFlow::CONTINUE } + /// }); + /// assert_eq!(last_used.break_value(), Some(22)); + /// ``` + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + pub const CONTINUE: Self = ControlFlow::Continue(()); +} + +impl ControlFlow<(), C> { + /// APIs like `try_for_each` don't need values with `Break`, + /// so this provides a way to avoid typing `(())`, if you prefer it. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_enum)] + /// use std::ops::ControlFlow; + /// + /// let mut partial_sum = 0; + /// (1..10).chain(20..25).try_for_each(|x| { + /// if partial_sum > 100 { ControlFlow::BREAK } + /// else { partial_sum += x; ControlFlow::CONTINUE } + /// }); + /// assert_eq!(partial_sum, 108); + /// ``` + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + pub const BREAK: Self = ControlFlow::Break(()); +} diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs new file mode 100644 index 000000000..d68932402 --- /dev/null +++ b/library/core/src/ops/deref.rs @@ -0,0 +1,199 @@ +/// Used for immutable dereferencing operations, like `*v`. +/// +/// 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. +/// +/// 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 +/// accommodate 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` (where `T` is neither a reference nor a raw pointer) +/// 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], +/// [method resolution] and [type coercions]. +/// +/// [book]: ../../book/ch15-02-deref.html +/// [more]: #more-on-deref-coercion +/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator +/// [method resolution]: ../../reference/expressions/method-call-expr.html +/// [type coercions]: ../../reference/type-coercions.html +/// +/// # Examples +/// +/// A struct with a single field which is accessible by dereferencing the +/// struct. +/// +/// ``` +/// use std::ops::Deref; +/// +/// struct DerefExample { +/// value: T +/// } +/// +/// impl Deref for DerefExample { +/// type Target = T; +/// +/// fn deref(&self) -> &Self::Target { +/// &self.value +/// } +/// } +/// +/// let x = DerefExample { value: 'a' }; +/// assert_eq!('a', *x); +/// ``` +#[lang = "deref"] +#[doc(alias = "*")] +#[doc(alias = "&*")] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Deref"] +pub trait Deref { + /// The resulting type after dereferencing. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "deref_target"] + #[lang = "deref_target"] + type Target: ?Sized; + + /// Dereferences the value. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_diagnostic_item = "deref_method"] + fn deref(&self) -> &Self::Target; +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl const Deref for &T { + type Target = T; + + #[rustc_diagnostic_item = "noop_method_deref"] + fn deref(&self) -> &T { + *self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl !DerefMut for &T {} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl const Deref for &mut T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +/// 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 +/// accommodate 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`, and `x` is a value of type `T`, +/// then: +/// +/// * In mutable contexts, `*x` (where `T` is neither a reference nor a raw pointer) +/// is equivalent to `*DerefMut::deref_mut(&mut 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], +/// [method resolution] and [type coercions]. +/// +/// [book]: ../../book/ch15-02-deref.html +/// [more]: #more-on-deref-coercion +/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator +/// [method resolution]: ../../reference/expressions/method-call-expr.html +/// [type coercions]: ../../reference/type-coercions.html +/// +/// # Examples +/// +/// A struct with a single field which is modifiable by dereferencing the +/// struct. +/// +/// ``` +/// use std::ops::{Deref, DerefMut}; +/// +/// struct DerefMutExample { +/// value: T +/// } +/// +/// impl Deref for DerefMutExample { +/// type Target = T; +/// +/// fn deref(&self) -> &Self::Target { +/// &self.value +/// } +/// } +/// +/// impl DerefMut for DerefMutExample { +/// fn deref_mut(&mut self) -> &mut Self::Target { +/// &mut self.value +/// } +/// } +/// +/// let mut x = DerefMutExample { value: 'a' }; +/// *x = 'b'; +/// assert_eq!('b', x.value); +/// ``` +#[lang = "deref_mut"] +#[doc(alias = "*")] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait DerefMut: Deref { + /// Mutably dereferences the value. + #[stable(feature = "rust1", since = "1.0.0")] + fn deref_mut(&mut self) -> &mut Self::Target; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DerefMut for &mut T { + fn deref_mut(&mut self) -> &mut T { + *self + } +} + +/// Indicates that a struct can be used as a method receiver, without the +/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box`, +/// `Rc`, `&T`, and `Pin

`. +#[lang = "receiver"] +#[unstable(feature = "receiver_trait", issue = "none")] +#[doc(hidden)] +pub trait Receiver { + // Empty. +} + +#[unstable(feature = "receiver_trait", issue = "none")] +impl Receiver for &T {} + +#[unstable(feature = "receiver_trait", issue = "none")] +impl Receiver for &mut T {} diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs new file mode 100644 index 000000000..aa654aa55 --- /dev/null +++ b/library/core/src/ops/drop.rs @@ -0,0 +1,165 @@ +/// Custom code within the destructor. +/// +/// When a value is no longer needed, Rust will run a "destructor" on that value. +/// The most common way that a value is no longer needed is when it goes out of +/// scope. Destructors may still run in other circumstances, but we're going to +/// focus on scope for the examples here. To learn about some of those other cases, +/// please see [the reference] section on destructors. +/// +/// [the reference]: https://doc.rust-lang.org/reference/destructors.html +/// +/// This destructor consists of two components: +/// - A call to `Drop::drop` for that value, if this special `Drop` trait is implemented for its type. +/// - The automatically generated "drop glue" which recursively calls the destructors +/// of all the fields of this value. +/// +/// As Rust automatically calls the destructors of all contained fields, +/// you don't have to implement `Drop` in most cases. But there are some cases where +/// it is useful, for example for types which directly manage a resource. +/// That resource may be memory, it may be a file descriptor, it may be a network socket. +/// Once a value of that type is no longer going to be used, it should "clean up" its +/// resource by freeing the memory or closing the file or socket. This is +/// the job of a destructor, and therefore the job of `Drop::drop`. +/// +/// ## Examples +/// +/// To see destructors in action, let's take a look at the following program: +/// +/// ```rust +/// struct HasDrop; +/// +/// impl Drop for HasDrop { +/// fn drop(&mut self) { +/// println!("Dropping HasDrop!"); +/// } +/// } +/// +/// struct HasTwoDrops { +/// one: HasDrop, +/// two: HasDrop, +/// } +/// +/// impl Drop for HasTwoDrops { +/// fn drop(&mut self) { +/// println!("Dropping HasTwoDrops!"); +/// } +/// } +/// +/// fn main() { +/// let _x = HasTwoDrops { one: HasDrop, two: HasDrop }; +/// println!("Running!"); +/// } +/// ``` +/// +/// Rust will first call `Drop::drop` for `_x` and then for both `_x.one` and `_x.two`, +/// meaning that running this will print +/// +/// ```text +/// Running! +/// Dropping HasTwoDrops! +/// Dropping HasDrop! +/// Dropping HasDrop! +/// ``` +/// +/// Even if we remove the implementation of `Drop` for `HasTwoDrop`, the destructors of its fields are still called. +/// This would result in +/// +/// ```test +/// Running! +/// Dropping HasDrop! +/// Dropping HasDrop! +/// ``` +/// +/// ## You cannot call `Drop::drop` yourself +/// +/// Because `Drop::drop` is used to clean up a value, it may be dangerous to use this value after +/// the method has been called. As `Drop::drop` does not take ownership of its input, +/// Rust prevents misuse by not allowing you to call `Drop::drop` directly. +/// +/// In other words, if you tried to explicitly call `Drop::drop` in the above example, you'd get a compiler error. +/// +/// If you'd like to explicitly call the destructor of a value, [`mem::drop`] can be used instead. +/// +/// [`mem::drop`]: drop +/// +/// ## Drop order +/// +/// Which of our two `HasDrop` drops first, though? For structs, it's the same +/// order that they're declared: first `one`, then `two`. If you'd like to try +/// this yourself, you can modify `HasDrop` above to contain some data, like an +/// integer, and then use it in the `println!` inside of `Drop`. This behavior is +/// guaranteed by the language. +/// +/// Unlike for structs, local variables are dropped in reverse order: +/// +/// ```rust +/// struct Foo; +/// +/// impl Drop for Foo { +/// fn drop(&mut self) { +/// println!("Dropping Foo!") +/// } +/// } +/// +/// struct Bar; +/// +/// impl Drop for Bar { +/// fn drop(&mut self) { +/// println!("Dropping Bar!") +/// } +/// } +/// +/// fn main() { +/// let _foo = Foo; +/// let _bar = Bar; +/// } +/// ``` +/// +/// This will print +/// +/// ```text +/// Dropping Bar! +/// Dropping Foo! +/// ``` +/// +/// Please see [the reference] for the full rules. +/// +/// [the reference]: https://doc.rust-lang.org/reference/destructors.html +/// +/// ## `Copy` and `Drop` are exclusive +/// +/// You cannot implement both [`Copy`] and `Drop` on the same type. Types that +/// are `Copy` get implicitly duplicated by the compiler, making it very +/// hard to predict when, and how often destructors will be executed. As such, +/// these types cannot have destructors. +#[lang = "drop"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Drop { + /// Executes the destructor for this type. + /// + /// This method is called implicitly when the value goes out of scope, + /// and cannot be called explicitly (this is compiler error [E0040]). + /// However, the [`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. + /// 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. + /// + /// Note that even if this panics, the value is considered to be dropped; + /// you must not cause `drop` to be called again. This is normally automatically + /// handled by the compiler, but when using unsafe code, can sometimes occur + /// unintentionally, particularly when using [`ptr::drop_in_place`]. + /// + /// [E0040]: ../../error-index.html#E0040 + /// [`panic!`]: crate::panic! + /// [`mem::drop`]: drop + /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place + #[stable(feature = "rust1", since = "1.0.0")] + fn drop(&mut self); +} diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs new file mode 100644 index 000000000..c5a194b7d --- /dev/null +++ b/library/core/src/ops/function.rs @@ -0,0 +1,304 @@ +/// 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/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## Calling a closure +/// +/// ``` +/// let square = |x| x * x; +/// assert_eq!(square(5), 25); +/// ``` +/// +/// ## Using a `Fn` parameter +/// +/// ``` +/// fn call_with_one(func: F) -> usize +/// where F: Fn(usize) -> usize { +/// func(1) +/// } +/// +/// let double = |x| x * 2; +/// assert_eq!(call_with_one(double), 2); +/// ``` +#[lang = "fn"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Fn"] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{Fn}<{Args}>` closure, found `{Self}`", + label = "expected an `Fn<{Args}>` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +pub trait Fn: FnMut { + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + +/// 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/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## Calling a mutably capturing closure +/// +/// ``` +/// let mut x = 5; +/// { +/// let mut square_x = || x *= x; +/// square_x(); +/// } +/// assert_eq!(x, 25); +/// ``` +/// +/// ## Using a `FnMut` parameter +/// +/// ``` +/// fn do_twice(mut func: F) +/// where F: FnMut() +/// { +/// func(); +/// func(); +/// } +/// +/// let mut x: usize = 1; +/// { +/// let add_two_to_x = || x += 2; +/// do_twice(add_two_to_x); +/// } +/// +/// assert_eq!(x, 5); +/// ``` +#[lang = "fn_mut"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "FnMut"] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`", + label = "expected an `FnMut<{Args}>` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +pub trait FnMut: FnOnce { + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +/// 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 closures 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/ch13-01-closures.html +/// [function pointers]: fn +/// [nomicon]: ../../nomicon/hrtb.html +/// +/// # Examples +/// +/// ## 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. +/// println!("Consumed: {}", func()); +/// +/// println!("Delicious!"); +/// +/// // Attempting to invoke `func()` again will throw a `use of moved +/// // value` error for `func`. +/// } +/// +/// let x = String::from("x"); +/// let consume_and_return_x = move || x; +/// consume_with_relish(consume_and_return_x); +/// +/// // `consume_and_return_x` can no longer be invoked at this point +/// ``` +#[lang = "fn_once"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "FnOnce"] +#[rustc_paren_sugar] +#[rustc_on_unimplemented( + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" + ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), + message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`", + label = "expected an `FnOnce<{Args}>` closure, found `{Self}`" +)] +#[fundamental] // so that regex can rely that `&str: !FnMut` +#[must_use = "closures are lazy and do nothing unless called"] +pub trait FnOnce { + /// The returned type after the call operator is used. + #[lang = "fn_once_output"] + #[stable(feature = "fn_once_output", since = "1.12.0")] + type Output; + + /// Performs the call operation. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +mod impls { + #[stable(feature = "rust1", since = "1.0.0")] + impl Fn for &F + where + F: Fn, + { + extern "rust-call" fn call(&self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnMut for &F + where + F: Fn, + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnOnce for &F + where + F: Fn, + { + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnMut for &mut F + where + F: FnMut, + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (*self).call_mut(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl FnOnce for &mut F + where + F: FnMut, + { + type Output = F::Output; + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call_mut(args) + } + } +} diff --git a/library/core/src/ops/generator.rs b/library/core/src/ops/generator.rs new file mode 100644 index 000000000..b651b7b23 --- /dev/null +++ b/library/core/src/ops/generator.rs @@ -0,0 +1,136 @@ +use crate::marker::Unpin; +use crate::pin::Pin; + +/// The result of a generator resumption. +/// +/// This enum is returned from the `Generator::resume` method and indicates the +/// possible return values of a generator. Currently this corresponds to either +/// a suspension point (`Yielded`) or a termination point (`Complete`). +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +#[lang = "generator_state"] +#[unstable(feature = "generator_trait", issue = "43122")] +pub enum GeneratorState { + /// The generator suspended with a value. + /// + /// This state indicates that a generator has been suspended, and typically + /// corresponds to a `yield` statement. The value provided in this variant + /// corresponds to the expression passed to `yield` and allows generators to + /// provide a value each time they yield. + Yielded(Y), + + /// The generator completed with a return value. + /// + /// This state indicates that a generator has finished execution with the + /// provided value. Once a generator has returned `Complete` it is + /// considered a programmer error to call `resume` again. + Complete(R), +} + +/// The trait implemented by builtin generator types. +/// +/// Generators, also commonly referred to as coroutines, are currently an +/// experimental language feature in Rust. Added in [RFC 2033] generators are +/// currently intended to primarily provide a building block for async/await +/// syntax but will likely extend to also providing an ergonomic definition for +/// iterators and other primitives. +/// +/// The syntax and semantics for generators is unstable and will require a +/// further RFC for stabilization. At this time, though, the syntax is +/// closure-like: +/// +/// ```rust +/// #![feature(generators, generator_trait)] +/// +/// use std::ops::{Generator, GeneratorState}; +/// use std::pin::Pin; +/// +/// fn main() { +/// let mut generator = || { +/// yield 1; +/// "foo" +/// }; +/// +/// match Pin::new(&mut generator).resume(()) { +/// GeneratorState::Yielded(1) => {} +/// _ => panic!("unexpected return from resume"), +/// } +/// match Pin::new(&mut generator).resume(()) { +/// GeneratorState::Complete("foo") => {} +/// _ => panic!("unexpected return from resume"), +/// } +/// } +/// ``` +/// +/// More documentation of generators can be found in the [unstable book]. +/// +/// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033 +/// [unstable book]: ../../unstable-book/language-features/generators.html +#[lang = "generator"] +#[unstable(feature = "generator_trait", issue = "43122")] +#[fundamental] +pub trait Generator { + /// The type of value this generator yields. + /// + /// This associated type corresponds to the `yield` expression and the + /// values which are allowed to be returned each time a generator yields. + /// For example an iterator-as-a-generator would likely have this type as + /// `T`, the type being iterated over. + type Yield; + + /// The type of value this generator returns. + /// + /// This corresponds to the type returned from a generator either with a + /// `return` statement or implicitly as the last expression of a generator + /// literal. For example futures would use this as `Result` as it + /// represents a completed future. + #[lang = "generator_return"] + type Return; + + /// Resumes the execution of this generator. + /// + /// This function will resume execution of the generator or start execution + /// if it hasn't already. This call will return back into the generator's + /// last suspension point, resuming execution from the latest `yield`. The + /// generator will continue executing until it either yields or returns, at + /// which point this function will return. + /// + /// # Return value + /// + /// The `GeneratorState` enum returned from this function indicates what + /// state the generator is in upon returning. If the `Yielded` variant is + /// returned then the generator has reached a suspension point and a value + /// has been yielded out. Generators in this state are available for + /// resumption at a later point. + /// + /// If `Complete` is returned then the generator has completely finished + /// with the value provided. It is invalid for the generator to be resumed + /// again. + /// + /// # Panics + /// + /// This function may panic if it is called after the `Complete` variant has + /// been returned previously. While generator literals in the language are + /// guaranteed to panic on resuming after `Complete`, this is not guaranteed + /// for all implementations of the `Generator` trait. + fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState; +} + +#[unstable(feature = "generator_trait", issue = "43122")] +impl, R> Generator for Pin<&mut G> { + type Yield = G::Yield; + type Return = G::Return; + + fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState { + G::resume((*self).as_mut(), arg) + } +} + +#[unstable(feature = "generator_trait", issue = "43122")] +impl + Unpin, R> Generator for &mut G { + type Yield = G::Yield; + type Return = G::Return; + + fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState { + G::resume(Pin::new(&mut *self), arg) + } +} diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs new file mode 100644 index 000000000..e2e569cb7 --- /dev/null +++ b/library/core/src/ops/index.rs @@ -0,0 +1,175 @@ +/// 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 the type of `value` implements [`Copy`]. +/// +/// # Examples +/// +/// The following example implements `Index` on a read-only `NucleotideCount` +/// container, enabling individual counts to be retrieved with index syntax. +/// +/// ``` +/// use std::ops::Index; +/// +/// enum Nucleotide { +/// A, +/// C, +/// G, +/// T, +/// } +/// +/// struct NucleotideCount { +/// a: usize, +/// c: usize, +/// g: usize, +/// t: usize, +/// } +/// +/// impl Index for NucleotideCount { +/// type Output = usize; +/// +/// fn index(&self, nucleotide: Nucleotide) -> &Self::Output { +/// match nucleotide { +/// Nucleotide::A => &self.a, +/// Nucleotide::C => &self.c, +/// Nucleotide::G => &self.g, +/// Nucleotide::T => &self.t, +/// } +/// } +/// } +/// +/// let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12}; +/// assert_eq!(nucleotide_count[Nucleotide::A], 14); +/// assert_eq!(nucleotide_count[Nucleotide::C], 9); +/// assert_eq!(nucleotide_count[Nucleotide::G], 10); +/// assert_eq!(nucleotide_count[Nucleotide::T], 12); +/// ``` +#[lang = "index"] +#[rustc_on_unimplemented( + message = "the type `{Self}` cannot be indexed by `{Idx}`", + label = "`{Self}` cannot be indexed by `{Idx}`" +)] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "]")] +#[doc(alias = "[")] +#[doc(alias = "[]")] +pub trait Index { + /// The returned type after indexing. + #[stable(feature = "rust1", since = "1.0.0")] + type Output: ?Sized; + + /// Performs the indexing (`container[index]`) operation. + /// + /// # Panics + /// + /// May panic if the index is out of bounds. + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + fn index(&self, index: Idx) -> &Self::Output; +} + +/// 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`. +/// +/// # Examples +/// +/// A very simple implementation of a `Balance` struct that has two sides, where +/// each can be indexed mutably and immutably. +/// +/// ``` +/// use std::ops::{Index, IndexMut}; +/// +/// #[derive(Debug)] +/// enum Side { +/// Left, +/// Right, +/// } +/// +/// #[derive(Debug, PartialEq)] +/// enum Weight { +/// Kilogram(f32), +/// Pound(f32), +/// } +/// +/// struct Balance { +/// pub left: Weight, +/// pub right: Weight, +/// } +/// +/// impl Index for Balance { +/// type Output = Weight; +/// +/// fn index(&self, index: Side) -> &Self::Output { +/// println!("Accessing {index:?}-side of balance immutably"); +/// match index { +/// Side::Left => &self.left, +/// Side::Right => &self.right, +/// } +/// } +/// } +/// +/// impl IndexMut for Balance { +/// fn index_mut(&mut self, index: Side) -> &mut Self::Output { +/// println!("Accessing {index:?}-side of balance mutably"); +/// match index { +/// Side::Left => &mut self.left, +/// Side::Right => &mut self.right, +/// } +/// } +/// } +/// +/// 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( + on( + _Self = "&str", + note = "you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), + on( + _Self = "str", + note = "you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), + on( + _Self = "std::string::String", + note = "you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), + message = "the type `{Self}` cannot be mutably indexed by `{Idx}`", + label = "`{Self}` cannot be mutably indexed by `{Idx}`" +)] +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "[")] +#[doc(alias = "]")] +#[doc(alias = "[]")] +pub trait IndexMut: Index { + /// Performs the mutable indexing (`container[index]`) operation. + /// + /// # Panics + /// + /// May panic if the index is out of bounds. + #[stable(feature = "rust1", since = "1.0.0")] + #[track_caller] + fn index_mut(&mut self, index: Idx) -> &mut Self::Output; +} diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs new file mode 100644 index 000000000..31c1a1d09 --- /dev/null +++ b/library/core/src/ops/mod.rs @@ -0,0 +1,208 @@ +//! Overloadable operators. +//! +//! Implementing these traits allows you to overload certain operators. +//! +//! Some of these traits are imported by the prelude, so they are available in +//! every Rust program. Only operators backed by traits can be overloaded. For +//! example, the addition operator (`+`) can be overloaded through the [`Add`] +//! trait, but since the assignment operator (`=`) has no backing trait, there +//! is no way of overloading its semantics. Additionally, this module does not +//! provide any mechanism to create new operators. If traitless overloading or +//! 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 +//! overloadable operators. +//! +//! Many of the operators take their operands by value. In non-generic +//! contexts involving built-in types, this is usually not a problem. +//! However, using these operators in generic code, requires some +//! attention if values have to be reused as opposed to letting the operators +//! consume them. One option is to occasionally use [`clone`]. +//! Another option is to rely on the types involved providing additional +//! operator implementations for references. For example, for a user-defined +//! type `T` which is supposed to support addition, it is probably a good +//! idea to have both `T` and `&T` implement the traits [`Add`][`Add`] and +//! [`Add<&T>`][`Add`] so that generic code can be written without unnecessary +//! cloning. +//! +//! # Examples +//! +//! This example creates a `Point` struct that implements [`Add`] and [`Sub`], +//! and then demonstrates adding and subtracting two `Point`s. +//! +//! ```rust +//! use std::ops::{Add, Sub}; +//! +//! #[derive(Debug, Copy, Clone, PartialEq)] +//! struct Point { +//! x: i32, +//! y: i32, +//! } +//! +//! impl Add for Point { +//! type Output = Self; +//! +//! fn add(self, other: Self) -> Self { +//! Self {x: self.x + other.x, y: self.y + other.y} +//! } +//! } +//! +//! impl Sub for Point { +//! type Output = Self; +//! +//! fn sub(self, other: Self) -> Self { +//! Self {x: self.x - other.x, y: self.y - other.y} +//! } +//! } +//! +//! 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. +//! +//! The [`Fn`], [`FnMut`], and [`FnOnce`] traits are implemented by types that can be +//! invoked like functions. Note that [`Fn`] takes `&self`, [`FnMut`] takes `&mut +//! self` and [`FnOnce`] takes `self`. These correspond to the three kinds of +//! methods that can be invoked on an instance: call-by-reference, +//! call-by-mutable-reference, and call-by-value. The most common use of these +//! traits is to act as bounds to higher-level functions that take functions or +//! closures as arguments. +//! +//! Taking a [`Fn`] as a parameter: +//! +//! ```rust +//! fn call_with_one(func: F) -> usize +//! where F: Fn(usize) -> usize +//! { +//! func(1) +//! } +//! +//! let double = |x| x * 2; +//! assert_eq!(call_with_one(double), 2); +//! ``` +//! +//! Taking a [`FnMut`] as a parameter: +//! +//! ```rust +//! fn do_twice(mut func: F) +//! where F: FnMut() +//! { +//! func(); +//! func(); +//! } +//! +//! let mut x: usize = 1; +//! { +//! let add_two_to_x = || x += 2; +//! do_twice(add_two_to_x); +//! } +//! +//! assert_eq!(x, 5); +//! ``` +//! +//! Taking a [`FnOnce`] as a parameter: +//! +//! ```rust +//! fn consume_with_relish(func: F) +//! where F: FnOnce() -> String +//! { +//! // `func` consumes its captured variables, so it cannot be run more +//! // than once +//! println!("Consumed: {}", func()); +//! +//! println!("Delicious!"); +//! +//! // Attempting to invoke `func()` again will throw a `use of moved +//! // value` error for `func` +//! } +//! +//! let x = String::from("x"); +//! let consume_and_return_x = move || x; +//! consume_with_relish(consume_and_return_x); +//! +//! // `consume_and_return_x` can no longer be invoked at this point +//! ``` +//! +//! [`clone`]: Clone::clone +//! [operator precedence]: ../../reference/expressions.html#expression-precedence + +#![stable(feature = "rust1", since = "1.0.0")] + +mod arith; +mod bit; +mod control_flow; +mod deref; +mod drop; +mod function; +mod generator; +mod index; +mod range; +mod try_trait; +mod unsize; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::arith::{Add, Div, Mul, Neg, Rem, Sub}; +#[stable(feature = "op_assign_traits", since = "1.8.0")] +pub use self::arith::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::bit::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; +#[stable(feature = "op_assign_traits", since = "1.8.0")] +pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::deref::{Deref, DerefMut}; + +#[unstable(feature = "receiver_trait", issue = "none")] +pub use self::deref::Receiver; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::drop::Drop; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::function::{Fn, FnMut, FnOnce}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::index::{Index, IndexMut}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; + +#[stable(feature = "inclusive_range", since = "1.26.0")] +pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; + +#[unstable(feature = "one_sided_range", issue = "69780")] +pub use self::range::OneSidedRange; + +#[unstable(feature = "try_trait_v2", issue = "84277")] +pub use self::try_trait::{FromResidual, Try}; + +#[unstable(feature = "try_trait_v2_yeet", issue = "96374")] +pub use self::try_trait::Yeet; + +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +pub use self::try_trait::Residual; + +pub(crate) use self::try_trait::{ChangeOutputType, NeverShortCircuit}; + +#[unstable(feature = "generator_trait", issue = "43122")] +pub use self::generator::{Generator, GeneratorState}; + +#[unstable(feature = "coerce_unsized", issue = "27732")] +pub use self::unsize::CoerceUnsized; + +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +pub use self::unsize::DispatchFromDyn; + +#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] +pub use self::control_flow::ControlFlow; diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs new file mode 100644 index 000000000..a3b148473 --- /dev/null +++ b/library/core/src/ops/range.rs @@ -0,0 +1,991 @@ +use crate::fmt; +use crate::hash::Hash; + +/// An unbounded range (`..`). +/// +/// `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 +/// +/// The `..` syntax is a `RangeFull`: +/// +/// ``` +/// 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: +/// +/// ```compile_fail,E0277 +/// for i in .. { +/// // ... +/// } +/// ``` +/// +/// Used as a [slicing index], `RangeFull` produces the full array as a slice. +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); // This is the `RangeFull` +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +/// +/// [slicing index]: crate::slice::SliceIndex +#[lang = "RangeFull"] +#[doc(alias = "..")] +#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeFull; + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeFull { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "..") + } +} + +/// A (half-open) range bounded inclusively below and exclusively above +/// (`start..end`). +/// +/// The range `start..end` contains all values with `start <= x < end`. +/// It is empty if `start >= end`. +/// +/// # Examples +/// +/// The `start..end` syntax is a `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, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); // This is a `Range` +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +#[lang = "Range"] +#[doc(alias = "..")] +#[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Range { + /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub start: Idx, + /// The upper bound of the range (exclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub end: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Range { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..")?; + self.end.fmt(fmt)?; + Ok(()) + } +} + +impl> Range { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// 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!( (0.0..1.0).contains(&0.5)); + /// assert!(!(0.0..1.0).contains(&f32::NAN)); + /// assert!(!(0.0..f32::NAN).contains(&0.5)); + /// assert!(!(f32::NAN..1.0).contains(&0.5)); + /// ``` + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } + + /// Returns `true` if the range contains no items. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..5).is_empty()); + /// assert!( (3..3).is_empty()); + /// assert!( (3..2).is_empty()); + /// ``` + /// + /// The range is empty if either side is incomparable: + /// + /// ``` + /// assert!(!(3.0..5.0).is_empty()); + /// assert!( (3.0..f32::NAN).is_empty()); + /// assert!( (f32::NAN..5.0).is_empty()); + /// ``` + #[stable(feature = "range_is_empty", since = "1.47.0")] + pub fn is_empty(&self) -> bool { + !(self.start < self.end) + } +} + +/// A range only bounded inclusively below (`start..`). +/// +/// The `RangeFrom` `start..` contains all values with `x >= start`. +/// +/// *Note*: Overflow in the [`Iterator`] implementation (when the contained +/// data type reaches its numerical limit) is allowed to panic, wrap, or +/// saturate. This behavior is defined by the implementation of the [`Step`] +/// trait. For primitive integers, this follows the normal rules, and respects +/// the overflow checks profile (panic in debug, wrap in release). Note also +/// that overflow happens earlier than you might assume: the overflow happens +/// in the call to `next` that yields the maximum value, as the range must be +/// set to a state to yield the next value. +/// +/// [`Step`]: crate::iter::Step +/// +/// # Examples +/// +/// The `start..` syntax is a `RangeFrom`: +/// +/// ``` +/// assert_eq!((2..), std::ops::RangeFrom { start: 2 }); +/// assert_eq!(2 + 3 + 4, (2..).take(3).sum()); +/// ``` +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); // This is a `RangeFrom` +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +#[lang = "RangeFrom"] +#[doc(alias = "..")] +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeFrom { + /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub start: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeFrom { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..")?; + Ok(()) + } +} + +impl> RangeFrom { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..).contains(&2)); + /// assert!( (3..).contains(&3)); + /// assert!( (3..).contains(&1_000_000_000)); + /// + /// assert!( (0.0..).contains(&0.5)); + /// assert!(!(0.0..).contains(&f32::NAN)); + /// assert!(!(f32::NAN..).contains(&0.5)); + /// ``` + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } +} + +/// A range only bounded exclusively above (`..end`). +/// +/// 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 `..end` syntax is a `RangeTo`: +/// +/// ``` +/// 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: +/// +/// ```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 +/// elements before the index indicated by `end`. +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); // This is a `RangeTo` +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +/// +/// [slicing index]: crate::slice::SliceIndex +#[lang = "RangeTo"] +#[doc(alias = "..")] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeTo { + /// The upper bound of the range (exclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub end: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeTo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "..")?; + self.end.fmt(fmt)?; + Ok(()) + } +} + +impl> RangeTo { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!( (..5).contains(&-1_000_000_000)); + /// assert!( (..5).contains(&4)); + /// assert!(!(..5).contains(&5)); + /// + /// assert!( (..1.0).contains(&0.5)); + /// assert!(!(..1.0).contains(&f32::NAN)); + /// assert!(!(..f32::NAN).contains(&0.5)); + /// ``` + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } +} + +/// A range bounded inclusively below and above (`start..=end`). +/// +/// The `RangeInclusive` `start..=end` contains all values with `x >= start` +/// and `x <= end`. It is empty unless `start <= end`. +/// +/// This iterator is [fused], but the specific values of `start` and `end` after +/// iteration has finished are **unspecified** other than that [`.is_empty()`] +/// will return `true` once no more values will be produced. +/// +/// [fused]: crate::iter::FusedIterator +/// [`.is_empty()`]: RangeInclusive::is_empty +/// +/// # Examples +/// +/// The `start..=end` syntax is a `RangeInclusive`: +/// +/// ``` +/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5)); +/// assert_eq!(3 + 4 + 5, (3..=5).sum()); +/// ``` +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); // This is a `RangeInclusive` +/// ``` +#[lang = "RangeInclusive"] +#[doc(alias = "..=")] +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "inclusive_range", since = "1.26.0")] +pub struct RangeInclusive { + // Note that the fields here are not public to allow changing the + // representation in the future; in particular, while we could plausibly + // expose start/end, modifying them without changing (future/current) + // private fields may lead to incorrect behavior, so we don't want to + // support that mode. + pub(crate) start: Idx, + pub(crate) end: Idx, + + // This field is: + // - `false` upon construction + // - `false` when iteration has yielded an element and the iterator is not exhausted + // - `true` when iteration has been used to exhaust the iterator + // + // This is required to support PartialEq and Hash without a PartialOrd bound or specialization. + pub(crate) exhausted: bool, +} + +impl RangeInclusive { + /// Creates a new inclusive range. Equivalent to writing `start..=end`. + /// + /// # Examples + /// + /// ``` + /// use std::ops::RangeInclusive; + /// + /// assert_eq!(3..=5, RangeInclusive::new(3, 5)); + /// ``` + #[lang = "range_inclusive_new"] + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[inline] + #[rustc_promotable] + #[rustc_const_stable(feature = "const_range_new", since = "1.32.0")] + pub const fn new(start: Idx, end: Idx) -> Self { + Self { start, end, exhausted: false } + } + + /// Returns the lower bound of the range (inclusive). + /// + /// When using an inclusive range for iteration, the values of `start()` and + /// [`end()`] are unspecified after the iteration ended. To determine + /// whether the inclusive range is empty, use the [`is_empty()`] method + /// instead of comparing `start() > end()`. + /// + /// Note: the value returned by this method is unspecified after the range + /// has been iterated to exhaustion. + /// + /// [`end()`]: RangeInclusive::end + /// [`is_empty()`]: RangeInclusive::is_empty + /// + /// # Examples + /// + /// ``` + /// assert_eq!((3..=5).start(), &3); + /// ``` + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")] + #[inline] + pub const fn start(&self) -> &Idx { + &self.start + } + + /// Returns the upper bound of the range (inclusive). + /// + /// When using an inclusive range for iteration, the values of [`start()`] + /// and `end()` are unspecified after the iteration ended. To determine + /// whether the inclusive range is empty, use the [`is_empty()`] method + /// instead of comparing `start() > end()`. + /// + /// Note: the value returned by this method is unspecified after the range + /// has been iterated to exhaustion. + /// + /// [`start()`]: RangeInclusive::start + /// [`is_empty()`]: RangeInclusive::is_empty + /// + /// # Examples + /// + /// ``` + /// assert_eq!((3..=5).end(), &5); + /// ``` + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")] + #[inline] + pub const fn end(&self) -> &Idx { + &self.end + } + + /// Destructures the `RangeInclusive` into (lower bound, upper (inclusive) bound). + /// + /// Note: the value returned by this method is unspecified after the range + /// has been iterated to exhaustion. + /// + /// # Examples + /// + /// ``` + /// assert_eq!((3..=5).into_inner(), (3, 5)); + /// ``` + #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[inline] + pub fn into_inner(self) -> (Idx, Idx) { + (self.start, self.end) + } +} + +impl RangeInclusive { + /// Converts to an exclusive `Range` for `SliceIndex` implementations. + /// The caller is responsible for dealing with `end == usize::MAX`. + #[inline] + pub(crate) const fn into_slice_range(self) -> Range { + // If we're not exhausted, we want to simply slice `start..end + 1`. + // If we are exhausted, then slicing with `end + 1..end + 1` gives us an + // empty range that is still subject to bounds-checks for that endpoint. + let exclusive_end = self.end + 1; + let start = if self.exhausted { exclusive_end } else { self.start }; + start..exclusive_end + } +} + +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl fmt::Debug for RangeInclusive { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + self.start.fmt(fmt)?; + write!(fmt, "..=")?; + self.end.fmt(fmt)?; + if self.exhausted { + write!(fmt, " (exhausted)")?; + } + Ok(()) + } +} + +impl> RangeInclusive { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// 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!( (0.0..=1.0).contains(&1.0)); + /// assert!(!(0.0..=1.0).contains(&f32::NAN)); + /// assert!(!(0.0..=f32::NAN).contains(&0.0)); + /// assert!(!(f32::NAN..=1.0).contains(&1.0)); + /// ``` + /// + /// This method always returns `false` after iteration has finished: + /// + /// ``` + /// let mut r = 3..=5; + /// assert!(r.contains(&3) && r.contains(&5)); + /// for _ in r.by_ref() {} + /// // Precise field values are unspecified here + /// assert!(!r.contains(&3) && !r.contains(&5)); + /// ``` + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } + + /// Returns `true` if the range contains no items. + /// + /// # Examples + /// + /// ``` + /// assert!(!(3..=5).is_empty()); + /// assert!(!(3..=3).is_empty()); + /// assert!( (3..=2).is_empty()); + /// ``` + /// + /// The range is empty if either side is incomparable: + /// + /// ``` + /// assert!(!(3.0..=5.0).is_empty()); + /// assert!( (3.0..=f32::NAN).is_empty()); + /// assert!( (f32::NAN..=5.0).is_empty()); + /// ``` + /// + /// This method returns `true` after iteration has finished: + /// + /// ``` + /// let mut r = 3..=5; + /// for _ in r.by_ref() {} + /// // Precise field values are unspecified here + /// assert!(r.is_empty()); + /// ``` + #[stable(feature = "range_is_empty", since = "1.47.0")] + #[inline] + pub fn is_empty(&self) -> bool { + self.exhausted || !(self.start <= self.end) + } +} + +/// A range only bounded inclusively above (`..=end`). +/// +/// 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 `..=end` syntax is a `RangeToInclusive`: +/// +/// ``` +/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 }); +/// ``` +/// +/// 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::RangeToInclusive<{integer}>: +/// // std::iter::Iterator` is not satisfied +/// for i in ..=5 { +/// // ... +/// } +/// ``` +/// +/// When used as a [slicing index], `RangeToInclusive` produces a slice of all +/// array elements up to and including the index indicated by `end`. +/// +/// ``` +/// let arr = [0, 1, 2, 3, 4]; +/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); +/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); // This is a `RangeToInclusive` +/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); +/// assert_eq!(arr[1.. 3], [ 1, 2 ]); +/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); +/// ``` +/// +/// [slicing index]: crate::slice::SliceIndex +#[lang = "RangeToInclusive"] +#[doc(alias = "..=")] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[stable(feature = "inclusive_range", since = "1.26.0")] +pub struct RangeToInclusive { + /// The upper bound of the range (inclusive) + #[stable(feature = "inclusive_range", since = "1.26.0")] + pub end: Idx, +} + +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl fmt::Debug for RangeToInclusive { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "..=")?; + self.end.fmt(fmt)?; + Ok(()) + } +} + +impl> RangeToInclusive { + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!( (..=5).contains(&-1_000_000_000)); + /// assert!( (..=5).contains(&5)); + /// assert!(!(..=5).contains(&6)); + /// + /// assert!( (..=1.0).contains(&1.0)); + /// assert!(!(..=1.0).contains(&f32::NAN)); + /// assert!(!(..=f32::NAN).contains(&0.5)); + /// ``` + #[stable(feature = "range_contains", since = "1.35.0")] + pub fn contains(&self, item: &U) -> bool + where + Idx: PartialOrd, + U: ?Sized + PartialOrd, + { + >::contains(self, item) + } +} + +// RangeToInclusive cannot impl From> +// because underflow would be possible with (..0).into() + +/// An endpoint of a range of keys. +/// +/// # Examples +/// +/// `Bound`s are range endpoints: +/// +/// ``` +/// use std::ops::Bound::*; +/// use std::ops::RangeBounds; +/// +/// assert_eq!((..100).start_bound(), Unbounded); +/// assert_eq!((1..12).start_bound(), Included(&1)); +/// assert_eq!((1..12).end_bound(), Excluded(&12)); +/// ``` +/// +/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. +/// Note that in most cases, it's better to use range syntax (`1..5`) instead. +/// +/// ``` +/// use std::collections::BTreeMap; +/// use std::ops::Bound::{Excluded, Included, Unbounded}; +/// +/// let mut map = BTreeMap::new(); +/// map.insert(3, "a"); +/// map.insert(5, "b"); +/// map.insert(8, "c"); +/// +/// for (key, value) in map.range((Excluded(3), Included(8))) { +/// println!("{key}: {value}"); +/// } +/// +/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); +/// ``` +/// +/// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range +#[stable(feature = "collections_bound", since = "1.17.0")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included(#[stable(feature = "collections_bound", since = "1.17.0")] T), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, +} + +impl Bound { + /// Converts from `&Bound` to `Bound<&T>`. + #[inline] + #[unstable(feature = "bound_as_ref", issue = "80996")] + pub fn as_ref(&self) -> Bound<&T> { + match *self { + Included(ref x) => Included(x), + Excluded(ref x) => Excluded(x), + Unbounded => Unbounded, + } + } + + /// Converts from `&mut Bound` to `Bound<&mut T>`. + #[inline] + #[unstable(feature = "bound_as_ref", issue = "80996")] + pub fn as_mut(&mut self) -> Bound<&mut T> { + match *self { + Included(ref mut x) => Included(x), + Excluded(ref mut x) => Excluded(x), + Unbounded => Unbounded, + } + } + + /// Maps a `Bound` to a `Bound` by applying a function to the contained value (including + /// both `Included` and `Excluded`), returning a `Bound` of the same kind. + /// + /// # Examples + /// + /// ``` + /// #![feature(bound_map)] + /// use std::ops::Bound::*; + /// + /// let bound_string = Included("Hello, World!"); + /// + /// assert_eq!(bound_string.map(|s| s.len()), Included(13)); + /// ``` + /// + /// ``` + /// #![feature(bound_map)] + /// use std::ops::Bound; + /// use Bound::*; + /// + /// let unbounded_string: Bound = Unbounded; + /// + /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded); + /// ``` + #[inline] + #[unstable(feature = "bound_map", issue = "86026")] + pub fn map U>(self, f: F) -> Bound { + match self { + Unbounded => Unbounded, + Included(x) => Included(f(x)), + Excluded(x) => Excluded(f(x)), + } + } +} + +impl Bound<&T> { + /// Map a `Bound<&T>` to a `Bound` by cloning the contents of the bound. + /// + /// # Examples + /// + /// ``` + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((1..12).start_bound(), Included(&1)); + /// assert_eq!((1..12).start_bound().cloned(), Included(1)); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "bound_cloned", since = "1.55.0")] + pub fn cloned(self) -> Bound { + match self { + Bound::Unbounded => Bound::Unbounded, + Bound::Included(x) => Bound::Included(x.clone()), + Bound::Excluded(x) => Bound::Excluded(x.clone()), + } + } +} + +/// `RangeBounds` is implemented by Rust's built-in range types, produced +/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. +#[stable(feature = "collections_range", since = "1.28.0")] +pub trait RangeBounds { + /// Start index bound. + /// + /// Returns the start value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// # fn main() { + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((..10).start_bound(), Unbounded); + /// assert_eq!((3..10).start_bound(), Included(&3)); + /// # } + /// ``` + #[stable(feature = "collections_range", since = "1.28.0")] + fn start_bound(&self) -> Bound<&T>; + + /// End index bound. + /// + /// Returns the end value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// # fn main() { + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((3..).end_bound(), Unbounded); + /// assert_eq!((3..10).end_bound(), Excluded(&10)); + /// # } + /// ``` + #[stable(feature = "collections_range", since = "1.28.0")] + fn end_bound(&self) -> Bound<&T>; + + /// Returns `true` if `item` is contained in the range. + /// + /// # Examples + /// + /// ``` + /// assert!( (3..5).contains(&4)); + /// assert!(!(3..5).contains(&2)); + /// + /// assert!( (0.0..1.0).contains(&0.5)); + /// assert!(!(0.0..1.0).contains(&f32::NAN)); + /// assert!(!(0.0..f32::NAN).contains(&0.5)); + /// assert!(!(f32::NAN..1.0).contains(&0.5)); + #[stable(feature = "range_contains", since = "1.35.0")] + fn contains(&self, item: &U) -> bool + where + T: PartialOrd, + U: ?Sized + PartialOrd, + { + (match self.start_bound() { + Included(start) => start <= item, + Excluded(start) => start < item, + Unbounded => true, + }) && (match self.end_bound() { + Included(end) => item <= end, + Excluded(end) => item < end, + Unbounded => true, + }) + } +} + +use self::Bound::{Excluded, Included, Unbounded}; + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeFull { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeFrom { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeTo { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for Range { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeInclusive { + fn start_bound(&self) -> Bound<&T> { + Included(&self.start) + } + fn end_bound(&self) -> Bound<&T> { + if self.exhausted { + // When the iterator is exhausted, we usually have start == end, + // but we want the range to appear empty, containing nothing. + Excluded(&self.end) + } else { + Included(&self.end) + } + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeToInclusive { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Included(&self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for (Bound, Bound) { + fn start_bound(&self) -> Bound<&T> { + match *self { + (Included(ref start), _) => Included(start), + (Excluded(ref start), _) => Excluded(start), + (Unbounded, _) => Unbounded, + } + } + + fn end_bound(&self) -> Bound<&T> { + match *self { + (_, Included(ref end)) => Included(end), + (_, Excluded(ref end)) => Excluded(end), + (_, Unbounded) => Unbounded, + } + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl<'a, T: ?Sized + 'a> RangeBounds for (Bound<&'a T>, Bound<&'a T>) { + fn start_bound(&self) -> Bound<&T> { + self.0 + } + + fn end_bound(&self) -> Bound<&T> { + self.1 + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeFrom<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Unbounded + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeTo<&T> { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Excluded(self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for Range<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Excluded(self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeInclusive<&T> { + fn start_bound(&self) -> Bound<&T> { + Included(self.start) + } + fn end_bound(&self) -> Bound<&T> { + Included(self.end) + } +} + +#[stable(feature = "collections_range", since = "1.28.0")] +impl RangeBounds for RangeToInclusive<&T> { + fn start_bound(&self) -> Bound<&T> { + Unbounded + } + fn end_bound(&self) -> Bound<&T> { + Included(self.end) + } +} + +/// `OneSidedRange` is implemented for built-in range types that are unbounded +/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`, +/// but `..`, `d..e`, and `f..=g` do not. +/// +/// Types that implement `OneSidedRange` must return `Bound::Unbounded` +/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`. +#[unstable(feature = "one_sided_range", issue = "69780")] +pub trait OneSidedRange: RangeBounds {} + +#[unstable(feature = "one_sided_range", issue = "69780")] +impl OneSidedRange for RangeTo where Self: RangeBounds {} + +#[unstable(feature = "one_sided_range", issue = "69780")] +impl OneSidedRange for RangeFrom where Self: RangeBounds {} + +#[unstable(feature = "one_sided_range", issue = "69780")] +impl OneSidedRange for RangeToInclusive where Self: RangeBounds {} diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs new file mode 100644 index 000000000..02f7f62bf --- /dev/null +++ b/library/core/src/ops/try_trait.rs @@ -0,0 +1,418 @@ +use crate::ops::ControlFlow; + +/// The `?` operator and `try {}` blocks. +/// +/// `try_*` methods typically involve a type implementing this trait. For +/// example, the closures passed to [`Iterator::try_fold`] and +/// [`Iterator::try_for_each`] must return such a type. +/// +/// `Try` types are typically those containing two or more categories of values, +/// some subset of which are so commonly handled via early returns that it's +/// worth providing a terse (but still visible) syntax to make that easy. +/// +/// This is most often seen for error handling with [`Result`] and [`Option`]. +/// The quintessential implementation of this trait is on [`ControlFlow`]. +/// +/// # Using `Try` in Generic Code +/// +/// `Iterator::try_fold` was stabilized to call back in Rust 1.27, but +/// this trait is much newer. To illustrate the various associated types and +/// methods, let's implement our own version. +/// +/// As a reminder, an infallible version of a fold looks something like this: +/// ``` +/// fn simple_fold( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> A, +/// ) -> A { +/// for x in iter { +/// accum = f(accum, x); +/// } +/// accum +/// } +/// ``` +/// +/// So instead of `f` returning just an `A`, we'll need it to return some other +/// type that produces an `A` in the "don't short circuit" path. Conveniently, +/// that's also the type we need to return from the function. +/// +/// Let's add a new generic parameter `R` for that type, and bound it to the +/// output type that we want: +/// ``` +/// # #![feature(try_trait_v2)] +/// # use std::ops::Try; +/// fn simple_try_fold_1>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// todo!() +/// } +/// ``` +/// +/// If we get through the entire iterator, we need to wrap up the accumulator +/// into the return type using [`Try::from_output`]: +/// ``` +/// # #![feature(try_trait_v2)] +/// # use std::ops::{ControlFlow, Try}; +/// fn simple_try_fold_2>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// for x in iter { +/// let cf = f(accum, x).branch(); +/// match cf { +/// ControlFlow::Continue(a) => accum = a, +/// ControlFlow::Break(_) => todo!(), +/// } +/// } +/// R::from_output(accum) +/// } +/// ``` +/// +/// We'll also need [`FromResidual::from_residual`] to turn the residual back +/// into the original type. But because it's a supertrait of `Try`, we don't +/// need to mention it in the bounds. All types which implement `Try` can be +/// recreated from their corresponding residual, so we'll just call it: +/// ``` +/// # #![feature(try_trait_v2)] +/// # use std::ops::{ControlFlow, Try}; +/// pub fn simple_try_fold_3>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// for x in iter { +/// let cf = f(accum, x).branch(); +/// match cf { +/// ControlFlow::Continue(a) => accum = a, +/// ControlFlow::Break(r) => return R::from_residual(r), +/// } +/// } +/// R::from_output(accum) +/// } +/// ``` +/// +/// But this "call `branch`, then `match` on it, and `return` if it was a +/// `Break`" is exactly what happens inside the `?` operator. So rather than +/// do all this manually, we can just use `?` instead: +/// ``` +/// # #![feature(try_trait_v2)] +/// # use std::ops::Try; +/// fn simple_try_fold>( +/// iter: impl Iterator, +/// mut accum: A, +/// mut f: impl FnMut(A, T) -> R, +/// ) -> R { +/// for x in iter { +/// accum = f(accum, x)?; +/// } +/// R::from_output(accum) +/// } +/// ``` +#[unstable(feature = "try_trait_v2", issue = "84277")] +#[rustc_on_unimplemented( + on( + all(from_desugaring = "TryBlock"), + message = "a `try` block must return `Result` or `Option` \ + (or another type that implements `{Try}`)", + label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`", + ), + on( + all(from_desugaring = "QuestionMark"), + message = "the `?` operator can only be applied to values that implement `{Try}`", + label = "the `?` operator cannot be applied to type `{Self}`" + ) +)] +#[doc(alias = "?")] +#[lang = "Try"] +pub trait Try: FromResidual { + /// The type of the value produced by `?` when *not* short-circuiting. + #[unstable(feature = "try_trait_v2", issue = "84277")] + type Output; + + /// The type of the value passed to [`FromResidual::from_residual`] + /// as part of `?` when short-circuiting. + /// + /// This represents the possible values of the `Self` type which are *not* + /// represented by the `Output` type. + /// + /// # Note to Implementors + /// + /// The choice of this type is critical to interconversion. + /// Unlike the `Output` type, which will often be a raw generic type, + /// this type is typically a newtype of some sort to "color" the type + /// so that it's distinguishable from the residuals of other types. + /// + /// This is why `Result::Residual` is not `E`, but `Result`. + /// That way it's distinct from `ControlFlow::Residual`, for example, + /// and thus `?` on `ControlFlow` cannot be used in a method returning `Result`. + /// + /// If you're making a generic type `Foo` that implements `Try`, + /// then typically you can use `Foo` as its `Residual` + /// type: that type will have a "hole" in the correct place, and will maintain the + /// "foo-ness" of the residual so other types need to opt-in to interconversion. + #[unstable(feature = "try_trait_v2", issue = "84277")] + type Residual; + + /// Constructs the type from its `Output` type. + /// + /// This should be implemented consistently with the `branch` method + /// such that applying the `?` operator will get back the original value: + /// `Try::from_output(x).branch() --> ControlFlow::Continue(x)`. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_trait_v2)] + /// use std::ops::Try; + /// + /// assert_eq!( as Try>::from_output(3), Ok(3)); + /// assert_eq!( as Try>::from_output(4), Some(4)); + /// assert_eq!( + /// as Try>::from_output(5), + /// std::ops::ControlFlow::Continue(5), + /// ); + /// + /// # fn make_question_mark_work() -> Option<()> { + /// assert_eq!(Option::from_output(4)?, 4); + /// # None } + /// # make_question_mark_work(); + /// + /// // This is used, for example, on the accumulator in `try_fold`: + /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() }); + /// assert_eq!(r, Some(4)); + /// ``` + #[lang = "from_output"] + #[unstable(feature = "try_trait_v2", issue = "84277")] + fn from_output(output: Self::Output) -> Self; + + /// Used in `?` to decide whether the operator should produce a value + /// (because this returned [`ControlFlow::Continue`]) + /// or propagate a value back to the caller + /// (because this returned [`ControlFlow::Break`]). + /// + /// # Examples + /// + /// ``` + /// #![feature(try_trait_v2)] + /// use std::ops::{ControlFlow, Try}; + /// + /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3)); + /// assert_eq!(Err::(3).branch(), ControlFlow::Break(Err(3))); + /// + /// assert_eq!(Some(3).branch(), ControlFlow::Continue(3)); + /// assert_eq!(None::.branch(), ControlFlow::Break(None)); + /// + /// assert_eq!(ControlFlow::::Continue(3).branch(), ControlFlow::Continue(3)); + /// assert_eq!( + /// ControlFlow::<_, String>::Break(3).branch(), + /// ControlFlow::Break(ControlFlow::Break(3)), + /// ); + /// ``` + #[lang = "branch"] + #[unstable(feature = "try_trait_v2", issue = "84277")] + fn branch(self) -> ControlFlow; +} + +/// Used to specify which residuals can be converted into which [`crate::ops::Try`] types. +/// +/// Every `Try` type needs to be recreatable from its own associated +/// `Residual` type, but can also have additional `FromResidual` implementations +/// to support interconversion with other `Try` types. +#[rustc_on_unimplemented( + on( + all( + from_desugaring = "QuestionMark", + _Self = "std::result::Result", + R = "std::option::Option" + ), + message = "the `?` operator can only be used on `Result`s, not `Option`s, \ + in {ItemContext} that returns `Result`", + label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`", + enclosing_scope = "this function returns a `Result`" + ), + on( + all( + from_desugaring = "QuestionMark", + _Self = "std::result::Result", + ), + // There's a special error message in the trait selection code for + // `From` in `?`, so this is not shown for result-in-result errors, + // and thus it can be phrased more strongly than `ControlFlow`'s. + message = "the `?` operator can only be used on `Result`s \ + in {ItemContext} that returns `Result`", + label = "this `?` produces `{R}`, which is incompatible with `{Self}`", + enclosing_scope = "this function returns a `Result`" + ), + on( + all( + from_desugaring = "QuestionMark", + _Self = "std::option::Option", + R = "std::result::Result", + ), + message = "the `?` operator can only be used on `Option`s, not `Result`s, \ + in {ItemContext} that returns `Option`", + label = "use `.ok()?` if you want to discard the `{R}` error information", + enclosing_scope = "this function returns an `Option`" + ), + on( + all( + from_desugaring = "QuestionMark", + _Self = "std::option::Option", + ), + // `Option`-in-`Option` always works, as there's only one possible + // residual, so this can also be phrased strongly. + message = "the `?` operator can only be used on `Option`s \ + in {ItemContext} that returns `Option`", + label = "this `?` produces `{R}`, which is incompatible with `{Self}`", + enclosing_scope = "this function returns an `Option`" + ), + on( + all( + from_desugaring = "QuestionMark", + _Self = "std::ops::ControlFlow", + R = "std::ops::ControlFlow", + ), + message = "the `?` operator in {ItemContext} that returns `ControlFlow` \ + can only be used on other `ControlFlow`s (with the same Break type)", + label = "this `?` produces `{R}`, which is incompatible with `{Self}`", + enclosing_scope = "this function returns a `ControlFlow`", + note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`" + ), + on( + all( + from_desugaring = "QuestionMark", + _Self = "std::ops::ControlFlow", + // `R` is not a `ControlFlow`, as that case was matched previously + ), + message = "the `?` operator can only be used on `ControlFlow`s \ + in {ItemContext} that returns `ControlFlow`", + label = "this `?` produces `{R}`, which is incompatible with `{Self}`", + enclosing_scope = "this function returns a `ControlFlow`", + ), + on( + all(from_desugaring = "QuestionMark"), + message = "the `?` operator can only be used in {ItemContext} \ + that returns `Result` or `Option` \ + (or another type that implements `{FromResidual}`)", + label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", + enclosing_scope = "this function should return `Result` or `Option` to accept `?`" + ), +)] +#[rustc_diagnostic_item = "FromResidual"] +#[unstable(feature = "try_trait_v2", issue = "84277")] +pub trait FromResidual::Residual> { + /// Constructs the type from a compatible `Residual` type. + /// + /// This should be implemented consistently with the `branch` method such + /// that applying the `?` operator will get back an equivalent residual: + /// `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`. + /// (It must not be an *identical* residual when interconversion is involved.) + /// + /// # Examples + /// + /// ``` + /// #![feature(try_trait_v2)] + /// use std::ops::{ControlFlow, FromResidual}; + /// + /// assert_eq!(Result::::from_residual(Err(3_u8)), Err(3)); + /// assert_eq!(Option::::from_residual(None), None); + /// assert_eq!( + /// ControlFlow::<_, String>::from_residual(ControlFlow::Break(5)), + /// ControlFlow::Break(5), + /// ); + /// ``` + #[lang = "from_residual"] + #[unstable(feature = "try_trait_v2", issue = "84277")] + fn from_residual(residual: R) -> Self; +} + +#[unstable( + feature = "yeet_desugar_details", + issue = "none", + reason = "just here to simplify the desugaring; will never be stabilized" +)] +#[inline] +#[track_caller] // because `Result::from_residual` has it +#[lang = "from_yeet"] +pub fn from_yeet(yeeted: Y) -> T +where + T: FromResidual>, +{ + FromResidual::from_residual(Yeet(yeeted)) +} + +/// Allows retrieving the canonical type implementing [`Try`] that has this type +/// as its residual and allows it to hold an `O` as its output. +/// +/// If you think of the `Try` trait as splitting a type into its [`Try::Output`] +/// and [`Try::Residual`] components, this allows putting them back together. +/// +/// For example, +/// `Result: Try>`, +/// and in the other direction, +/// ` as Residual>::TryType = Result`. +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +pub trait Residual { + /// The "return" type of this meta-function. + #[unstable(feature = "try_trait_v2_residual", issue = "91285")] + type TryType: Try; +} + +#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")] +pub(crate) type ChangeOutputType = <::Residual as Residual>::TryType; + +/// An adapter for implementing non-try methods via the `Try` implementation. +/// +/// Conceptually the same as `Result`, but requiring less work in trait +/// solving and inhabited-ness checking and such, by being an obvious newtype +/// and not having `From` bounds lying around. +/// +/// Not currently planned to be exposed publicly, so just `pub(crate)`. +#[repr(transparent)] +pub(crate) struct NeverShortCircuit(pub T); + +impl NeverShortCircuit { + /// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`. + #[inline] + pub fn wrap_mut_2(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self { + move |a, b| NeverShortCircuit(f(a, b)) + } +} + +pub(crate) enum NeverShortCircuitResidual {} + +impl Try for NeverShortCircuit { + type Output = T; + type Residual = NeverShortCircuitResidual; + + #[inline] + fn branch(self) -> ControlFlow { + ControlFlow::Continue(self.0) + } + + #[inline] + fn from_output(x: T) -> Self { + NeverShortCircuit(x) + } +} + +impl FromResidual for NeverShortCircuit { + #[inline] + fn from_residual(never: NeverShortCircuitResidual) -> Self { + match never {} + } +} + +impl Residual for NeverShortCircuitResidual { + type TryType = NeverShortCircuit; +} + +/// Implement `FromResidual>` on your type to enable +/// `do yeet expr` syntax in functions returning your type. +#[unstable(feature = "try_trait_v2_yeet", issue = "96374")] +#[derive(Debug)] +pub struct Yeet(pub T); diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs new file mode 100644 index 000000000..a920b9165 --- /dev/null +++ b/library/core/src/ops/unsize.rs @@ -0,0 +1,132 @@ +use crate::marker::Unsize; + +/// Trait that indicates that this is a pointer or a wrapper for one, +/// where unsizing can be performed on the pointee. +/// +/// See the [DST coercion RFC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce] +/// for more details. +/// +/// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize` +/// by converting from a thin pointer to a fat pointer. +/// +/// For custom types, the coercion here works by coercing `Foo` to `Foo` +/// provided an impl of `CoerceUnsized> for Foo` exists. +/// Such an impl can only be written if `Foo` has only a single non-phantomdata +/// field involving `T`. If the type of that field is `Bar`, an implementation +/// of `CoerceUnsized> for Bar` must exist. The coercion will work by +/// coercing the `Bar` field into `Bar` and filling in the rest of the fields +/// from `Foo` to create a `Foo`. This will effectively drill down to a pointer +/// field and coerce that. +/// +/// Generally, for smart pointers you will implement +/// `CoerceUnsized> for Ptr where T: Unsize, U: ?Sized`, with an +/// optional `?Sized` bound on `T` itself. For wrapper types that directly embed `T` +/// like `Cell` and `RefCell`, you +/// can directly implement `CoerceUnsized> for Wrap where T: CoerceUnsized`. +/// This will let coercions of types like `Cell>` work. +/// +/// [`Unsize`][unsize] is used to mark types which can be coerced to DSTs if behind +/// pointers. It is implemented automatically by the compiler. +/// +/// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md +/// [unsize]: crate::marker::Unsize +/// [nomicon-coerce]: ../../nomicon/coercions.html +#[unstable(feature = "coerce_unsized", issue = "27732")] +#[lang = "coerce_unsized"] +pub trait CoerceUnsized { + // Empty. +} + +// &mut T -> &mut U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} +// &mut T -> &U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} +// &mut T -> *mut U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} +// &mut T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} + +// &T -> &U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +// &T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} + +// *mut T -> *mut U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} +// *mut T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} + +// *const T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} + +/// `DispatchFromDyn` is used in the implementation of object safety checks (specifically allowing +/// arbitrary self types), to guarantee that a method's receiver type can be dispatched on. +/// +/// Note: `DispatchFromDyn` was briefly named `CoerceSized` (and had a slightly different +/// interpretation). +/// +/// Imagine we have a trait object `t` with type `&dyn Tr`, where `Tr` is some trait with a method +/// `m` defined as `fn m(&self);`. When calling `t.m()`, the receiver `t` is a wide pointer, but an +/// implementation of `m` will expect a narrow pointer as `&self` (a reference to the concrete +/// type). The compiler must generate an implicit conversion from the trait object/wide pointer to +/// the concrete reference/narrow pointer. Implementing `DispatchFromDyn` indicates that that +/// conversion is allowed and thus that the type implementing `DispatchFromDyn` is safe to use as +/// the self type in an object-safe method. (in the above example, the compiler will require +/// `DispatchFromDyn` is implemented for `&'a U`). +/// +/// `DispatchFromDyn` does not specify the conversion from wide pointer to narrow pointer; the +/// conversion is hard-wired into the compiler. For the conversion to work, the following +/// properties must hold (i.e., it is only safe to implement `DispatchFromDyn` for types which have +/// these properties, these are also checked by the compiler): +/// +/// * EITHER `Self` and `T` are either both references or both raw pointers; in either case, with +/// the same mutability. +/// * OR, all of the following hold +/// - `Self` and `T` must have the same type constructor, and only vary in a single type parameter +/// formal (the *coerced type*, e.g., `impl DispatchFromDyn> for Rc` is ok and the +/// single type parameter (instantiated with `T` or `U`) is the coerced type, +/// `impl DispatchFromDyn> for Rc` is not ok). +/// - The definition for `Self` must be a struct. +/// - The definition for `Self` must not be `#[repr(packed)]` or `#[repr(C)]`. +/// - Other than one-aligned, zero-sized fields, the definition for `Self` must have exactly one +/// field and that field's type must be the coerced type. Furthermore, `Self`'s field type must +/// implement `DispatchFromDyn` where `F` is the type of `T`'s field type. +/// +/// An example implementation of the trait: +/// +/// ``` +/// # #![feature(dispatch_from_dyn, unsize)] +/// # use std::{ops::DispatchFromDyn, marker::Unsize}; +/// # struct Rc(std::rc::Rc); +/// impl DispatchFromDyn> for Rc +/// where +/// T: Unsize, +/// {} +/// ``` +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +#[lang = "dispatch_from_dyn"] +pub trait DispatchFromDyn { + // Empty. +} + +// &T -> &U +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} +// &mut T -> &mut U +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {} +// *const T -> *const U +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {} +// *mut T -> *mut U +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {} -- cgit v1.2.3