diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs new file mode 100644 index 000000000000..8743be3557cc --- /dev/null +++ b/src/libcore/ops/bit.rs @@ -0,0 +1,839 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// 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 = Answer; +/// +/// fn not(self) -> Answer { +/// 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")] +pub trait Not { + /// The resulting type after applying the `!` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the unary `!` operator + #[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")] + impl Not for $t { + type Output = $t; + + #[inline] + fn not(self) -> $t { !self } + } + + forward_ref_unop! { impl Not, not for $t } + )*) +} + +not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise AND operator `&`. +/// +/// # Examples +/// +/// In this example, the `&` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// 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 { +/// Scalar(self.0 & rhs.0) +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false)); +/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false)); +/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitAnd` trait is implemented for a `BooleanVector` +/// struct. +/// +/// ``` +/// use std::ops::BitAnd; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitAnd for BooleanVector { +/// type Output = Self; +/// +/// fn bitand(self, BooleanVector(rhs): Self) -> Self { +/// let BooleanVector(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect()) +/// } +/// } +/// +/// fn main() { +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, false, false, false]); +/// assert_eq!(bv1 & bv2, expected); +/// } +/// ``` +#[lang = "bitand"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"] +pub trait BitAnd { + /// The resulting type after applying the `&` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `&` operator + #[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")] + impl BitAnd for $t { + type Output = $t; + + #[inline] + fn bitand(self, rhs: $t) -> $t { self & rhs } + } + + forward_ref_binop! { impl BitAnd, bitand for $t, $t } + )*) +} + +bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise OR operator `|`. +/// +/// # Examples +/// +/// In this example, the `|` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// 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 { +/// Scalar(self.0 | rhs.0) +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true)); +/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitOr` trait is implemented for a `BooleanVector` +/// struct. +/// +/// ``` +/// use std::ops::BitOr; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitOr for BooleanVector { +/// type Output = Self; +/// +/// fn bitor(self, BooleanVector(rhs): Self) -> Self { +/// let BooleanVector(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect()) +/// } +/// } +/// +/// fn main() { +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, true, true, false]); +/// assert_eq!(bv1 | bv2, expected); +/// } +/// ``` +#[lang = "bitor"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"] +pub trait BitOr { + /// The resulting type after applying the `|` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `|` operator + #[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")] + impl BitOr for $t { + type Output = $t; + + #[inline] + fn bitor(self, rhs: $t) -> $t { self | rhs } + } + + forward_ref_binop! { impl BitOr, bitor for $t, $t } + )*) +} + +bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise XOR operator `^`. +/// +/// # Examples +/// +/// In this example, the `^` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// 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 { +/// Scalar(self.0 ^ rhs.0) +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false)); +/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true)); +/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitXor` trait is implemented for a `BooleanVector` +/// struct. +/// +/// ``` +/// use std::ops::BitXor; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitXor for BooleanVector { +/// type Output = Self; +/// +/// fn bitxor(self, BooleanVector(rhs): Self) -> Self { +/// let BooleanVector(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// BooleanVector(lhs.iter() +/// .zip(rhs.iter()) +/// .map(|(x, y)| (*x || *y) && !(*x && *y)) +/// .collect()) +/// } +/// } +/// +/// fn main() { +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![false, true, true, false]); +/// assert_eq!(bv1 ^ bv2, expected); +/// } +/// ``` +#[lang = "bitxor"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"] +pub trait BitXor { + /// The resulting type after applying the `^` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `^` operator + #[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")] + impl BitXor for $t { + type Output = $t; + + #[inline] + fn bitxor(self, other: $t) -> $t { self ^ other } + } + + forward_ref_binop! { impl BitXor, bitxor for $t, $t } + )*) +} + +bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The left shift operator `<<`. +/// +/// # Examples +/// +/// An implementation of `Shl` that lifts the `<<` operation on integers to a +/// `Scalar` struct. +/// +/// ``` +/// use std::ops::Shl; +/// +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); +/// +/// impl Shl for Scalar { +/// type Output = Self; +/// +/// fn shl(self, Scalar(rhs): Self) -> Scalar { +/// let Scalar(lhs) = self; +/// Scalar(lhs << rhs) +/// } +/// } +/// fn main() { +/// 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) -> SpinVector { +/// // rotate the vector by `rhs` places +/// let (a, b) = self.vec.split_at(rhs); +/// let mut spun_vector: Vec = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// SpinVector { vec: spun_vector } +/// } +/// } +/// +/// fn main() { +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2, +/// SpinVector { vec: vec![2, 3, 4, 0, 1] }); +/// } +/// ``` +#[lang = "shl"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"] +pub trait Shl { + /// The resulting type after applying the `<<` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `<<` operator + #[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")] + impl Shl<$f> for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn shl(self, other: $f) -> $t { + self << other + } + } + + forward_ref_binop! { impl 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 `>>`. +/// +/// # Examples +/// +/// An implementation of `Shr` that lifts the `>>` operation on integers to a +/// `Scalar` struct. +/// +/// ``` +/// use std::ops::Shr; +/// +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); +/// +/// impl Shr for Scalar { +/// type Output = Self; +/// +/// fn shr(self, Scalar(rhs): Self) -> Scalar { +/// let Scalar(lhs) = self; +/// Scalar(lhs >> rhs) +/// } +/// } +/// fn main() { +/// 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) -> SpinVector { +/// // rotate the vector by `rhs` places +/// let (a, b) = self.vec.split_at(self.vec.len() - rhs); +/// let mut spun_vector: Vec = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// SpinVector { vec: spun_vector } +/// } +/// } +/// +/// fn main() { +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2, +/// SpinVector { vec: vec![3, 4, 0, 1, 2] }); +/// } +/// ``` +#[lang = "shr"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"] +pub trait Shr { + /// The resulting type after applying the `>>` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `>>` operator + #[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")] + impl Shr<$f> for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn shr(self, other: $f) -> $t { + self >> other + } + } + + forward_ref_binop! { impl 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 +/// +/// In this example, the `&=` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// 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 = Scalar(self.0 & rhs.0) +/// } +/// } +/// +/// fn main() { +/// 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)); +/// } +/// ``` +/// +/// In this example, the `BitAndAssign` trait is implemented for a +/// `BooleanVector` struct. +/// +/// ``` +/// 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 = BooleanVector(self.0 +/// .iter() +/// .zip(rhs.0.iter()) +/// .map(|(x, y)| *x && *y) +/// .collect()); +/// } +/// } +/// +/// fn main() { +/// let mut bv = BooleanVector(vec![true, true, false, false]); +/// bv &= BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, false, false, false]); +/// assert_eq!(bv, expected); +/// } +/// ``` +#[lang = "bitand_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"] +pub trait BitAndAssign { + /// The method for the `&=` operator + #[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")] + impl BitAndAssign for $t { + #[inline] + fn bitand_assign(&mut self, other: $t) { *self &= other } + } + )+) +} + +bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise OR assignment operator `|=`. +/// +/// # Examples +/// +/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up +/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`. +/// +/// ``` +/// use std::ops::BitOrAssign; +/// +/// struct Foo; +/// +/// impl BitOrAssign for Foo { +/// fn bitor_assign(&mut self, _rhs: Foo) { +/// println!("Bitwise Or-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo |= Foo; +/// } +/// ``` +#[lang = "bitor_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"] +pub trait BitOrAssign { + /// The method for the `|=` operator + #[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")] + impl BitOrAssign for $t { + #[inline] + fn bitor_assign(&mut self, other: $t) { *self |= other } + } + )+) +} + +bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise XOR assignment operator `^=`. +/// +/// # Examples +/// +/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up +/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`. +/// +/// ``` +/// use std::ops::BitXorAssign; +/// +/// struct Foo; +/// +/// impl BitXorAssign for Foo { +/// fn bitxor_assign(&mut self, _rhs: Foo) { +/// println!("Bitwise Xor-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo ^= Foo; +/// } +/// ``` +#[lang = "bitxor_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"] +pub trait BitXorAssign { + /// The method for the `^=` operator + #[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")] + impl BitXorAssign for $t { + #[inline] + fn bitxor_assign(&mut self, other: $t) { *self ^= other } + } + )+) +} + +bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The left shift assignment operator `<<=`. +/// +/// # Examples +/// +/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up +/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`. +/// +/// ``` +/// use std::ops::ShlAssign; +/// +/// struct Foo; +/// +/// impl ShlAssign for Foo { +/// fn shl_assign(&mut self, _rhs: Foo) { +/// println!("Shifting left!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo <<= Foo; +/// } +/// ``` +#[lang = "shl_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"] +pub trait ShlAssign { + /// The method for the `<<=` operator + #[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")] + impl ShlAssign<$f> for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn shl_assign(&mut self, other: $f) { + *self <<= other + } + } + ) +} + +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 +/// +/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up +/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`. +/// +/// ``` +/// use std::ops::ShrAssign; +/// +/// struct Foo; +/// +/// impl ShrAssign for Foo { +/// fn shr_assign(&mut self, _rhs: Foo) { +/// println!("Shifting right!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo >>= Foo; +/// } +/// ``` +#[lang = "shr_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"] +pub trait ShrAssign { + /// The method for the `>>=` operator + #[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")] + impl ShrAssign<$f> for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn shr_assign(&mut self, other: $f) { + *self >>= other + } + } + ) +} + +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/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index 7d10c35d5e0b..fdc1b5fc2359 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -148,6 +148,7 @@ #![stable(feature = "rust1", since = "1.0.0")] mod arith; +mod bit; mod function; mod range; @@ -157,6 +158,12 @@ pub use self::arith::{Add, Sub, Mul, Div, Rem, Neg}; #[stable(feature = "op_assign_traits", since = "1.8.0")] pub use self::arith::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::bit::{Not, BitAnd, BitOr, BitXor, 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::function::{Fn, FnMut, FnOnce}; @@ -258,836 +265,6 @@ pub trait Drop { fn drop(&mut self); } -/// 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 = Answer; -/// -/// fn not(self) -> Answer { -/// 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")] -pub trait Not { - /// The resulting type after applying the `!` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the unary `!` operator - #[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")] - impl Not for $t { - type Output = $t; - - #[inline] - fn not(self) -> $t { !self } - } - - forward_ref_unop! { impl Not, not for $t } - )*) -} - -not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise AND operator `&`. -/// -/// # Examples -/// -/// In this example, the `&` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// 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 { -/// Scalar(self.0 & rhs.0) -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false)); -/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false)); -/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false)); -/// } -/// ``` -/// -/// In this example, the `BitAnd` trait is implemented for a `BooleanVector` -/// struct. -/// -/// ``` -/// use std::ops::BitAnd; -/// -/// #[derive(Debug, PartialEq)] -/// struct BooleanVector(Vec); -/// -/// impl BitAnd for BooleanVector { -/// type Output = Self; -/// -/// fn bitand(self, BooleanVector(rhs): Self) -> Self { -/// let BooleanVector(lhs) = self; -/// assert_eq!(lhs.len(), rhs.len()); -/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect()) -/// } -/// } -/// -/// fn main() { -/// let bv1 = BooleanVector(vec![true, true, false, false]); -/// let bv2 = BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![true, false, false, false]); -/// assert_eq!(bv1 & bv2, expected); -/// } -/// ``` -#[lang = "bitand"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"] -pub trait BitAnd { - /// The resulting type after applying the `&` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `&` operator - #[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")] - impl BitAnd for $t { - type Output = $t; - - #[inline] - fn bitand(self, rhs: $t) -> $t { self & rhs } - } - - forward_ref_binop! { impl BitAnd, bitand for $t, $t } - )*) -} - -bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise OR operator `|`. -/// -/// # Examples -/// -/// In this example, the `|` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// 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 { -/// Scalar(self.0 | rhs.0) -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true)); -/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false)); -/// } -/// ``` -/// -/// In this example, the `BitOr` trait is implemented for a `BooleanVector` -/// struct. -/// -/// ``` -/// use std::ops::BitOr; -/// -/// #[derive(Debug, PartialEq)] -/// struct BooleanVector(Vec); -/// -/// impl BitOr for BooleanVector { -/// type Output = Self; -/// -/// fn bitor(self, BooleanVector(rhs): Self) -> Self { -/// let BooleanVector(lhs) = self; -/// assert_eq!(lhs.len(), rhs.len()); -/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect()) -/// } -/// } -/// -/// fn main() { -/// let bv1 = BooleanVector(vec![true, true, false, false]); -/// let bv2 = BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![true, true, true, false]); -/// assert_eq!(bv1 | bv2, expected); -/// } -/// ``` -#[lang = "bitor"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"] -pub trait BitOr { - /// The resulting type after applying the `|` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `|` operator - #[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")] - impl BitOr for $t { - type Output = $t; - - #[inline] - fn bitor(self, rhs: $t) -> $t { self | rhs } - } - - forward_ref_binop! { impl BitOr, bitor for $t, $t } - )*) -} - -bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise XOR operator `^`. -/// -/// # Examples -/// -/// In this example, the `^` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// 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 { -/// Scalar(self.0 ^ rhs.0) -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false)); -/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true)); -/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false)); -/// } -/// ``` -/// -/// In this example, the `BitXor` trait is implemented for a `BooleanVector` -/// struct. -/// -/// ``` -/// use std::ops::BitXor; -/// -/// #[derive(Debug, PartialEq)] -/// struct BooleanVector(Vec); -/// -/// impl BitXor for BooleanVector { -/// type Output = Self; -/// -/// fn bitxor(self, BooleanVector(rhs): Self) -> Self { -/// let BooleanVector(lhs) = self; -/// assert_eq!(lhs.len(), rhs.len()); -/// BooleanVector(lhs.iter() -/// .zip(rhs.iter()) -/// .map(|(x, y)| (*x || *y) && !(*x && *y)) -/// .collect()) -/// } -/// } -/// -/// fn main() { -/// let bv1 = BooleanVector(vec![true, true, false, false]); -/// let bv2 = BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![false, true, true, false]); -/// assert_eq!(bv1 ^ bv2, expected); -/// } -/// ``` -#[lang = "bitxor"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"] -pub trait BitXor { - /// The resulting type after applying the `^` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `^` operator - #[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")] - impl BitXor for $t { - type Output = $t; - - #[inline] - fn bitxor(self, other: $t) -> $t { self ^ other } - } - - forward_ref_binop! { impl BitXor, bitxor for $t, $t } - )*) -} - -bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The left shift operator `<<`. -/// -/// # Examples -/// -/// An implementation of `Shl` that lifts the `<<` operation on integers to a -/// `Scalar` struct. -/// -/// ``` -/// use std::ops::Shl; -/// -/// #[derive(PartialEq, Debug)] -/// struct Scalar(usize); -/// -/// impl Shl for Scalar { -/// type Output = Self; -/// -/// fn shl(self, Scalar(rhs): Self) -> Scalar { -/// let Scalar(lhs) = self; -/// Scalar(lhs << rhs) -/// } -/// } -/// fn main() { -/// 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) -> SpinVector { -/// // rotate the vector by `rhs` places -/// let (a, b) = self.vec.split_at(rhs); -/// let mut spun_vector: Vec = vec![]; -/// spun_vector.extend_from_slice(b); -/// spun_vector.extend_from_slice(a); -/// SpinVector { vec: spun_vector } -/// } -/// } -/// -/// fn main() { -/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2, -/// SpinVector { vec: vec![2, 3, 4, 0, 1] }); -/// } -/// ``` -#[lang = "shl"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"] -pub trait Shl { - /// The resulting type after applying the `<<` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `<<` operator - #[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")] - impl Shl<$f> for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn shl(self, other: $f) -> $t { - self << other - } - } - - forward_ref_binop! { impl 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 `>>`. -/// -/// # Examples -/// -/// An implementation of `Shr` that lifts the `>>` operation on integers to a -/// `Scalar` struct. -/// -/// ``` -/// use std::ops::Shr; -/// -/// #[derive(PartialEq, Debug)] -/// struct Scalar(usize); -/// -/// impl Shr for Scalar { -/// type Output = Self; -/// -/// fn shr(self, Scalar(rhs): Self) -> Scalar { -/// let Scalar(lhs) = self; -/// Scalar(lhs >> rhs) -/// } -/// } -/// fn main() { -/// 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) -> SpinVector { -/// // rotate the vector by `rhs` places -/// let (a, b) = self.vec.split_at(self.vec.len() - rhs); -/// let mut spun_vector: Vec = vec![]; -/// spun_vector.extend_from_slice(b); -/// spun_vector.extend_from_slice(a); -/// SpinVector { vec: spun_vector } -/// } -/// } -/// -/// fn main() { -/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2, -/// SpinVector { vec: vec![3, 4, 0, 1, 2] }); -/// } -/// ``` -#[lang = "shr"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"] -pub trait Shr { - /// The resulting type after applying the `>>` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `>>` operator - #[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")] - impl Shr<$f> for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn shr(self, other: $f) -> $t { - self >> other - } - } - - forward_ref_binop! { impl 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 -/// -/// In this example, the `&=` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// 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 = Scalar(self.0 & rhs.0) -/// } -/// } -/// -/// fn main() { -/// 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)); -/// } -/// ``` -/// -/// In this example, the `BitAndAssign` trait is implemented for a -/// `BooleanVector` struct. -/// -/// ``` -/// 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 = BooleanVector(self.0 -/// .iter() -/// .zip(rhs.0.iter()) -/// .map(|(x, y)| *x && *y) -/// .collect()); -/// } -/// } -/// -/// fn main() { -/// let mut bv = BooleanVector(vec![true, true, false, false]); -/// bv &= BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![true, false, false, false]); -/// assert_eq!(bv, expected); -/// } -/// ``` -#[lang = "bitand_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"] -pub trait BitAndAssign { - /// The method for the `&=` operator - #[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")] - impl BitAndAssign for $t { - #[inline] - fn bitand_assign(&mut self, other: $t) { *self &= other } - } - )+) -} - -bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise OR assignment operator `|=`. -/// -/// # Examples -/// -/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up -/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`. -/// -/// ``` -/// use std::ops::BitOrAssign; -/// -/// struct Foo; -/// -/// impl BitOrAssign for Foo { -/// fn bitor_assign(&mut self, _rhs: Foo) { -/// println!("Bitwise Or-ing!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo |= Foo; -/// } -/// ``` -#[lang = "bitor_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"] -pub trait BitOrAssign { - /// The method for the `|=` operator - #[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")] - impl BitOrAssign for $t { - #[inline] - fn bitor_assign(&mut self, other: $t) { *self |= other } - } - )+) -} - -bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise XOR assignment operator `^=`. -/// -/// # Examples -/// -/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up -/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`. -/// -/// ``` -/// use std::ops::BitXorAssign; -/// -/// struct Foo; -/// -/// impl BitXorAssign for Foo { -/// fn bitxor_assign(&mut self, _rhs: Foo) { -/// println!("Bitwise Xor-ing!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo ^= Foo; -/// } -/// ``` -#[lang = "bitxor_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"] -pub trait BitXorAssign { - /// The method for the `^=` operator - #[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")] - impl BitXorAssign for $t { - #[inline] - fn bitxor_assign(&mut self, other: $t) { *self ^= other } - } - )+) -} - -bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The left shift assignment operator `<<=`. -/// -/// # Examples -/// -/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up -/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`. -/// -/// ``` -/// use std::ops::ShlAssign; -/// -/// struct Foo; -/// -/// impl ShlAssign for Foo { -/// fn shl_assign(&mut self, _rhs: Foo) { -/// println!("Shifting left!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo <<= Foo; -/// } -/// ``` -#[lang = "shl_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"] -pub trait ShlAssign { - /// The method for the `<<=` operator - #[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")] - impl ShlAssign<$f> for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn shl_assign(&mut self, other: $f) { - *self <<= other - } - } - ) -} - -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 -/// -/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up -/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`. -/// -/// ``` -/// use std::ops::ShrAssign; -/// -/// struct Foo; -/// -/// impl ShrAssign for Foo { -/// fn shr_assign(&mut self, _rhs: Foo) { -/// println!("Shifting right!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo >>= Foo; -/// } -/// ``` -#[lang = "shr_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"] -pub trait ShrAssign { - /// The method for the `>>=` operator - #[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")] - impl ShrAssign<$f> for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn shr_assign(&mut self, other: $f) { - *self >>= other - } - } - ) -} - -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 } - /// The `Index` trait is used to specify the functionality of indexing operations /// like `container[index]` when used in an immutable context. ///