#
core/ops/
bit.rs

    1/// The unary logical negation operator `!`.
    2///
    3/// # Examples
    4///
    5/// An implementation of `Not` for `Answer`, which enables the use of `!` to
    6/// invert its value.
    7///
    8/// ```
    9/// use std::ops::Not;
    10///
    11/// #[derive(Debug, PartialEq)]
    12/// enum Answer {
    13///     Yes,
    14///     No,
    15/// }
    16///
    17/// impl Not for Answer {
    18///     type Output = Self;
    19///
    20///     fn not(self) -> Self::Output {
    21///         match self {
    22///             Answer::Yes => Answer::No,
    23///             Answer::No => Answer::Yes
    24///         }
    25///     }
    26/// }
    27///
    28/// assert_eq!(!Answer::Yes, Answer::No);
    29/// assert_eq!(!Answer::No, Answer::Yes);
    30/// ```
    31#[lang = "not"]
    32#[stable(feature = "rust1", since = "1.0.0")]
    33#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    34#[doc(alias = "!")]
    35#[const_trait]
    36pub trait Not {
    37    /// The resulting type after applying the `!` operator.
    38    #[stable(feature = "rust1", since = "1.0.0")]
    39    type Output;
    40
    41    /// Performs the unary `!` operation.
    42    ///
    43    /// # Examples
    44    ///
    45    /// ```
    46    /// assert_eq!(!true, false);
    47    /// assert_eq!(!false, true);
    48    /// assert_eq!(!1u8, 254);
    49    /// assert_eq!(!0u8, 255);
    50    /// ```
    51    #[must_use]
    52    #[stable(feature = "rust1", since = "1.0.0")]
    53    fn not(self) -> Self::Output;
    54}
    55
    56macro_rules! not_impl {
    57    ($($t:ty)*) => ($(
    58        #[stable(feature = "rust1", since = "1.0.0")]
    59        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    60        impl const Not for $t {
    61            type Output = $t;
    62
    63            #[inline]
    64            fn not(self) -> $t { !self }
    65        }
    66
    67        forward_ref_unop! { impl Not, not for $t,
    68        #[stable(feature = "rust1", since = "1.0.0")]
    69        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    70    )*)
    71}
    72
    73not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
    74
    75#[stable(feature = "not_never", since = "1.60.0")]
    76#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    77impl const Not for ! {
    78    type Output = !;
    79
    80    #[inline]
    81    fn not(self) -> ! {
    82        match self {}
    83    }
    84}
    85
    86/// The bitwise AND operator `&`.
    87///
    88/// Note that `Rhs` is `Self` by default, but this is not mandatory.
    89///
    90/// # Examples
    91///
    92/// An implementation of `BitAnd` for a wrapper around `bool`.
    93///
    94/// ```
    95/// use std::ops::BitAnd;
    96///
    97/// #[derive(Debug, PartialEq)]
    98/// struct Scalar(bool);
    99///
    100/// impl BitAnd for Scalar {
    101///     type Output = Self;
    102///
    103///     // rhs is the "right-hand side" of the expression `a & b`
    104///     fn bitand(self, rhs: Self) -> Self::Output {
    105///         Self(self.0 & rhs.0)
    106///     }
    107/// }
    108///
    109/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true));
    110/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false));
    111/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false));
    112/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false));
    113/// ```
    114///
    115/// An implementation of `BitAnd` for a wrapper around `Vec<bool>`.
    116///
    117/// ```
    118/// use std::ops::BitAnd;
    119///
    120/// #[derive(Debug, PartialEq)]
    121/// struct BooleanVector(Vec<bool>);
    122///
    123/// impl BitAnd for BooleanVector {
    124///     type Output = Self;
    125///
    126///     fn bitand(self, Self(rhs): Self) -> Self::Output {
    127///         let Self(lhs) = self;
    128///         assert_eq!(lhs.len(), rhs.len());
    129///         Self(
    130///             lhs.iter()
    131///                 .zip(rhs.iter())
    132///                 .map(|(x, y)| *x & *y)
    133///                 .collect()
    134///         )
    135///     }
    136/// }
    137///
    138/// let bv1 = BooleanVector(vec![true, true, false, false]);
    139/// let bv2 = BooleanVector(vec![true, false, true, false]);
    140/// let expected = BooleanVector(vec![true, false, false, false]);
    141/// assert_eq!(bv1 & bv2, expected);
    142/// ```
    143#[lang = "bitand"]
    144#[doc(alias = "&")]
    145#[stable(feature = "rust1", since = "1.0.0")]
    146#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    147#[diagnostic::on_unimplemented(
    148    message = "no implementation for `{Self} & {Rhs}`",
    149    label = "no implementation for `{Self} & {Rhs}`"
    150)]
    151#[const_trait]
    152pub trait BitAnd<Rhs = Self> {
    153    /// The resulting type after applying the `&` operator.
    154    #[stable(feature = "rust1", since = "1.0.0")]
    155    type Output;
    156
    157    /// Performs the `&` operation.
    158    ///
    159    /// # Examples
    160    ///
    161    /// ```
    162    /// assert_eq!(true & false, false);
    163    /// assert_eq!(true & true, true);
    164    /// assert_eq!(5u8 & 1u8, 1);
    165    /// assert_eq!(5u8 & 2u8, 0);
    166    /// ```
    167    #[must_use]
    168    #[stable(feature = "rust1", since = "1.0.0")]
    169    fn bitand(self, rhs: Rhs) -> Self::Output;
    170}
    171
    172macro_rules! bitand_impl {
    173    ($($t:ty)*) => ($(
    174        #[stable(feature = "rust1", since = "1.0.0")]
    175        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    176        impl const BitAnd for $t {
    177            type Output = $t;
    178
    179            #[inline]
    180            fn bitand(self, rhs: $t) -> $t { self & rhs }
    181        }
    182
    183        forward_ref_binop! { impl BitAnd, bitand for $t, $t,
    184        #[stable(feature = "rust1", since = "1.0.0")]
    185        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    186    )*)
    187}
    188
    189bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
    190
    191/// The bitwise OR operator `|`.
    192///
    193/// Note that `Rhs` is `Self` by default, but this is not mandatory.
    194///
    195/// # Examples
    196///
    197/// An implementation of `BitOr` for a wrapper around `bool`.
    198///
    199/// ```
    200/// use std::ops::BitOr;
    201///
    202/// #[derive(Debug, PartialEq)]
    203/// struct Scalar(bool);
    204///
    205/// impl BitOr for Scalar {
    206///     type Output = Self;
    207///
    208///     // rhs is the "right-hand side" of the expression `a | b`
    209///     fn bitor(self, rhs: Self) -> Self::Output {
    210///         Self(self.0 | rhs.0)
    211///     }
    212/// }
    213///
    214/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true));
    215/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true));
    216/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true));
    217/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false));
    218/// ```
    219///
    220/// An implementation of `BitOr` for a wrapper around `Vec<bool>`.
    221///
    222/// ```
    223/// use std::ops::BitOr;
    224///
    225/// #[derive(Debug, PartialEq)]
    226/// struct BooleanVector(Vec<bool>);
    227///
    228/// impl BitOr for BooleanVector {
    229///     type Output = Self;
    230///
    231///     fn bitor(self, Self(rhs): Self) -> Self::Output {
    232///         let Self(lhs) = self;
    233///         assert_eq!(lhs.len(), rhs.len());
    234///         Self(
    235///             lhs.iter()
    236///                 .zip(rhs.iter())
    237///                 .map(|(x, y)| *x | *y)
    238///                 .collect()
    239///         )
    240///     }
    241/// }
    242///
    243/// let bv1 = BooleanVector(vec![true, true, false, false]);
    244/// let bv2 = BooleanVector(vec![true, false, true, false]);
    245/// let expected = BooleanVector(vec![true, true, true, false]);
    246/// assert_eq!(bv1 | bv2, expected);
    247/// ```
    248#[lang = "bitor"]
    249#[doc(alias = "|")]
    250#[stable(feature = "rust1", since = "1.0.0")]
    251#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    252#[diagnostic::on_unimplemented(
    253    message = "no implementation for `{Self} | {Rhs}`",
    254    label = "no implementation for `{Self} | {Rhs}`"
    255)]
    256#[const_trait]
    257pub trait BitOr<Rhs = Self> {
    258    /// The resulting type after applying the `|` operator.
    259    #[stable(feature = "rust1", since = "1.0.0")]
    260    type Output;
    261
    262    /// Performs the `|` operation.
    263    ///
    264    /// # Examples
    265    ///
    266    /// ```
    267    /// assert_eq!(true | false, true);
    268    /// assert_eq!(false | false, false);
    269    /// assert_eq!(5u8 | 1u8, 5);
    270    /// assert_eq!(5u8 | 2u8, 7);
    271    /// ```
    272    #[must_use]
    273    #[stable(feature = "rust1", since = "1.0.0")]
    274    fn bitor(self, rhs: Rhs) -> Self::Output;
    275}
    276
    277macro_rules! bitor_impl {
    278    ($($t:ty)*) => ($(
    279        #[stable(feature = "rust1", since = "1.0.0")]
    280        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    281        impl const BitOr for $t {
    282            type Output = $t;
    283
    284            #[inline]
    285            fn bitor(self, rhs: $t) -> $t { self | rhs }
    286        }
    287
    288        forward_ref_binop! { impl BitOr, bitor for $t, $t,
    289        #[stable(feature = "rust1", since = "1.0.0")]
    290        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    291    )*)
    292}
    293
    294bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
    295
    296/// The bitwise XOR operator `^`.
    297///
    298/// Note that `Rhs` is `Self` by default, but this is not mandatory.
    299///
    300/// # Examples
    301///
    302/// An implementation of `BitXor` that lifts `^` to a wrapper around `bool`.
    303///
    304/// ```
    305/// use std::ops::BitXor;
    306///
    307/// #[derive(Debug, PartialEq)]
    308/// struct Scalar(bool);
    309///
    310/// impl BitXor for Scalar {
    311///     type Output = Self;
    312///
    313///     // rhs is the "right-hand side" of the expression `a ^ b`
    314///     fn bitxor(self, rhs: Self) -> Self::Output {
    315///         Self(self.0 ^ rhs.0)
    316///     }
    317/// }
    318///
    319/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false));
    320/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true));
    321/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true));
    322/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false));
    323/// ```
    324///
    325/// An implementation of `BitXor` trait for a wrapper around `Vec<bool>`.
    326///
    327/// ```
    328/// use std::ops::BitXor;
    329///
    330/// #[derive(Debug, PartialEq)]
    331/// struct BooleanVector(Vec<bool>);
    332///
    333/// impl BitXor for BooleanVector {
    334///     type Output = Self;
    335///
    336///     fn bitxor(self, Self(rhs): Self) -> Self::Output {
    337///         let Self(lhs) = self;
    338///         assert_eq!(lhs.len(), rhs.len());
    339///         Self(
    340///             lhs.iter()
    341///                 .zip(rhs.iter())
    342///                 .map(|(x, y)| *x ^ *y)
    343///                 .collect()
    344///         )
    345///     }
    346/// }
    347///
    348/// let bv1 = BooleanVector(vec![true, true, false, false]);
    349/// let bv2 = BooleanVector(vec![true, false, true, false]);
    350/// let expected = BooleanVector(vec![false, true, true, false]);
    351/// assert_eq!(bv1 ^ bv2, expected);
    352/// ```
    353#[lang = "bitxor"]
    354#[doc(alias = "^")]
    355#[stable(feature = "rust1", since = "1.0.0")]
    356#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    357#[diagnostic::on_unimplemented(
    358    message = "no implementation for `{Self} ^ {Rhs}`",
    359    label = "no implementation for `{Self} ^ {Rhs}`"
    360)]
    361#[const_trait]
    362pub trait BitXor<Rhs = Self> {
    363    /// The resulting type after applying the `^` operator.
    364    #[stable(feature = "rust1", since = "1.0.0")]
    365    type Output;
    366
    367    /// Performs the `^` operation.
    368    ///
    369    /// # Examples
    370    ///
    371    /// ```
    372    /// assert_eq!(true ^ false, true);
    373    /// assert_eq!(true ^ true, false);
    374    /// assert_eq!(5u8 ^ 1u8, 4);
    375    /// assert_eq!(5u8 ^ 2u8, 7);
    376    /// ```
    377    #[must_use]
    378    #[stable(feature = "rust1", since = "1.0.0")]
    379    fn bitxor(self, rhs: Rhs) -> Self::Output;
    380}
    381
    382macro_rules! bitxor_impl {
    383    ($($t:ty)*) => ($(
    384        #[stable(feature = "rust1", since = "1.0.0")]
    385        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    386        impl const BitXor for $t {
    387            type Output = $t;
    388
    389            #[inline]
    390            fn bitxor(self, other: $t) -> $t { self ^ other }
    391        }
    392
    393        forward_ref_binop! { impl BitXor, bitxor for $t, $t,
    394        #[stable(feature = "rust1", since = "1.0.0")]
    395        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    396    )*)
    397}
    398
    399bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
    400
    401/// The left shift operator `<<`. Note that because this trait is implemented
    402/// for all integer types with multiple right-hand-side types, Rust's type
    403/// checker has special handling for `_ << _`, setting the result type for
    404/// integer operations to the type of the left-hand-side operand. This means
    405/// that though `a << b` and `a.shl(b)` are one and the same from an evaluation
    406/// standpoint, they are different when it comes to type inference.
    407///
    408/// # Examples
    409///
    410/// An implementation of `Shl` that lifts the `<<` operation on integers to a
    411/// wrapper around `usize`.
    412///
    413/// ```
    414/// use std::ops::Shl;
    415///
    416/// #[derive(PartialEq, Debug)]
    417/// struct Scalar(usize);
    418///
    419/// impl Shl<Scalar> for Scalar {
    420///     type Output = Self;
    421///
    422///     fn shl(self, Self(rhs): Self) -> Self::Output {
    423///         let Self(lhs) = self;
    424///         Self(lhs << rhs)
    425///     }
    426/// }
    427///
    428/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16));
    429/// ```
    430///
    431/// An implementation of `Shl` that spins a vector leftward by a given amount.
    432///
    433/// ```
    434/// use std::ops::Shl;
    435///
    436/// #[derive(PartialEq, Debug)]
    437/// struct SpinVector<T: Clone> {
    438///     vec: Vec<T>,
    439/// }
    440///
    441/// impl<T: Clone> Shl<usize> for SpinVector<T> {
    442///     type Output = Self;
    443///
    444///     fn shl(self, rhs: usize) -> Self::Output {
    445///         // Rotate the vector by `rhs` places.
    446///         let (a, b) = self.vec.split_at(rhs);
    447///         let mut spun_vector = vec![];
    448///         spun_vector.extend_from_slice(b);
    449///         spun_vector.extend_from_slice(a);
    450///         Self { vec: spun_vector }
    451///     }
    452/// }
    453///
    454/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2,
    455///            SpinVector { vec: vec![2, 3, 4, 0, 1] });
    456/// ```
    457#[lang = "shl"]
    458#[doc(alias = "<<")]
    459#[stable(feature = "rust1", since = "1.0.0")]
    460#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    461#[diagnostic::on_unimplemented(
    462    message = "no implementation for `{Self} << {Rhs}`",
    463    label = "no implementation for `{Self} << {Rhs}`"
    464)]
    465#[const_trait]
    466pub trait Shl<Rhs = Self> {
    467    /// The resulting type after applying the `<<` operator.
    468    #[stable(feature = "rust1", since = "1.0.0")]
    469    type Output;
    470
    471    /// Performs the `<<` operation.
    472    ///
    473    /// # Examples
    474    ///
    475    /// ```
    476    /// assert_eq!(5u8 << 1, 10);
    477    /// assert_eq!(1u8 << 1, 2);
    478    /// ```
    479    #[must_use]
    480    #[stable(feature = "rust1", since = "1.0.0")]
    481    fn shl(self, rhs: Rhs) -> Self::Output;
    482}
    483
    484macro_rules! shl_impl {
    485    ($t:ty, $f:ty) => {
    486        #[stable(feature = "rust1", since = "1.0.0")]
    487        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    488        impl const Shl<$f> for $t {
    489            type Output = $t;
    490
    491            #[inline]
    492            #[rustc_inherit_overflow_checks]
    493            fn shl(self, other: $f) -> $t {
    494                self << other
    495            }
    496        }
    497
    498        forward_ref_binop! { impl Shl, shl for $t, $f,
    499        #[stable(feature = "rust1", since = "1.0.0")]
    500        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    501    };
    502}
    503
    504macro_rules! shl_impl_all {
    505    ($($t:ty)*) => ($(
    506        shl_impl! { $t, u8 }
    507        shl_impl! { $t, u16 }
    508        shl_impl! { $t, u32 }
    509        shl_impl! { $t, u64 }
    510        shl_impl! { $t, u128 }
    511        shl_impl! { $t, usize }
    512
    513        shl_impl! { $t, i8 }
    514        shl_impl! { $t, i16 }
    515        shl_impl! { $t, i32 }
    516        shl_impl! { $t, i64 }
    517        shl_impl! { $t, i128 }
    518        shl_impl! { $t, isize }
    519    )*)
    520}
    521
    522shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    523
    524/// The right shift operator `>>`. Note that because this trait is implemented
    525/// for all integer types with multiple right-hand-side types, Rust's type
    526/// checker has special handling for `_ >> _`, setting the result type for
    527/// integer operations to the type of the left-hand-side operand. This means
    528/// that though `a >> b` and `a.shr(b)` are one and the same from an evaluation
    529/// standpoint, they are different when it comes to type inference.
    530///
    531/// # Examples
    532///
    533/// An implementation of `Shr` that lifts the `>>` operation on integers to a
    534/// wrapper around `usize`.
    535///
    536/// ```
    537/// use std::ops::Shr;
    538///
    539/// #[derive(PartialEq, Debug)]
    540/// struct Scalar(usize);
    541///
    542/// impl Shr<Scalar> for Scalar {
    543///     type Output = Self;
    544///
    545///     fn shr(self, Self(rhs): Self) -> Self::Output {
    546///         let Self(lhs) = self;
    547///         Self(lhs >> rhs)
    548///     }
    549/// }
    550///
    551/// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4));
    552/// ```
    553///
    554/// An implementation of `Shr` that spins a vector rightward by a given amount.
    555///
    556/// ```
    557/// use std::ops::Shr;
    558///
    559/// #[derive(PartialEq, Debug)]
    560/// struct SpinVector<T: Clone> {
    561///     vec: Vec<T>,
    562/// }
    563///
    564/// impl<T: Clone> Shr<usize> for SpinVector<T> {
    565///     type Output = Self;
    566///
    567///     fn shr(self, rhs: usize) -> Self::Output {
    568///         // Rotate the vector by `rhs` places.
    569///         let (a, b) = self.vec.split_at(self.vec.len() - rhs);
    570///         let mut spun_vector = vec![];
    571///         spun_vector.extend_from_slice(b);
    572///         spun_vector.extend_from_slice(a);
    573///         Self { vec: spun_vector }
    574///     }
    575/// }
    576///
    577/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2,
    578///            SpinVector { vec: vec![3, 4, 0, 1, 2] });
    579/// ```
    580#[lang = "shr"]
    581#[doc(alias = ">>")]
    582#[stable(feature = "rust1", since = "1.0.0")]
    583#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    584#[diagnostic::on_unimplemented(
    585    message = "no implementation for `{Self} >> {Rhs}`",
    586    label = "no implementation for `{Self} >> {Rhs}`"
    587)]
    588#[const_trait]
    589pub trait Shr<Rhs = Self> {
    590    /// The resulting type after applying the `>>` operator.
    591    #[stable(feature = "rust1", since = "1.0.0")]
    592    type Output;
    593
    594    /// Performs the `>>` operation.
    595    ///
    596    /// # Examples
    597    ///
    598    /// ```
    599    /// assert_eq!(5u8 >> 1, 2);
    600    /// assert_eq!(2u8 >> 1, 1);
    601    /// ```
    602    #[must_use]
    603    #[stable(feature = "rust1", since = "1.0.0")]
    604    fn shr(self, rhs: Rhs) -> Self::Output;
    605}
    606
    607macro_rules! shr_impl {
    608    ($t:ty, $f:ty) => {
    609        #[stable(feature = "rust1", since = "1.0.0")]
    610        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    611        impl const Shr<$f> for $t {
    612            type Output = $t;
    613
    614            #[inline]
    615            #[rustc_inherit_overflow_checks]
    616            fn shr(self, other: $f) -> $t {
    617                self >> other
    618            }
    619        }
    620
    621        forward_ref_binop! { impl Shr, shr for $t, $f,
    622        #[stable(feature = "rust1", since = "1.0.0")]
    623        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    624    };
    625}
    626
    627macro_rules! shr_impl_all {
    628    ($($t:ty)*) => ($(
    629        shr_impl! { $t, u8 }
    630        shr_impl! { $t, u16 }
    631        shr_impl! { $t, u32 }
    632        shr_impl! { $t, u64 }
    633        shr_impl! { $t, u128 }
    634        shr_impl! { $t, usize }
    635
    636        shr_impl! { $t, i8 }
    637        shr_impl! { $t, i16 }
    638        shr_impl! { $t, i32 }
    639        shr_impl! { $t, i64 }
    640        shr_impl! { $t, i128 }
    641        shr_impl! { $t, isize }
    642    )*)
    643}
    644
    645shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    646
    647/// The bitwise AND assignment operator `&=`.
    648///
    649/// # Examples
    650///
    651/// An implementation of `BitAndAssign` that lifts the `&=` operator to a
    652/// wrapper around `bool`.
    653///
    654/// ```
    655/// use std::ops::BitAndAssign;
    656///
    657/// #[derive(Debug, PartialEq)]
    658/// struct Scalar(bool);
    659///
    660/// impl BitAndAssign for Scalar {
    661///     // rhs is the "right-hand side" of the expression `a &= b`
    662///     fn bitand_assign(&mut self, rhs: Self) {
    663///         *self = Self(self.0 & rhs.0)
    664///     }
    665/// }
    666///
    667/// let mut scalar = Scalar(true);
    668/// scalar &= Scalar(true);
    669/// assert_eq!(scalar, Scalar(true));
    670///
    671/// let mut scalar = Scalar(true);
    672/// scalar &= Scalar(false);
    673/// assert_eq!(scalar, Scalar(false));
    674///
    675/// let mut scalar = Scalar(false);
    676/// scalar &= Scalar(true);
    677/// assert_eq!(scalar, Scalar(false));
    678///
    679/// let mut scalar = Scalar(false);
    680/// scalar &= Scalar(false);
    681/// assert_eq!(scalar, Scalar(false));
    682/// ```
    683///
    684/// Here, the `BitAndAssign` trait is implemented for a wrapper around
    685/// `Vec<bool>`.
    686///
    687/// ```
    688/// use std::ops::BitAndAssign;
    689///
    690/// #[derive(Debug, PartialEq)]
    691/// struct BooleanVector(Vec<bool>);
    692///
    693/// impl BitAndAssign for BooleanVector {
    694///     // `rhs` is the "right-hand side" of the expression `a &= b`.
    695///     fn bitand_assign(&mut self, rhs: Self) {
    696///         assert_eq!(self.0.len(), rhs.0.len());
    697///         *self = Self(
    698///             self.0
    699///                 .iter()
    700///                 .zip(rhs.0.iter())
    701///                 .map(|(x, y)| *x & *y)
    702///                 .collect()
    703///         );
    704///     }
    705/// }
    706///
    707/// let mut bv = BooleanVector(vec![true, true, false, false]);
    708/// bv &= BooleanVector(vec![true, false, true, false]);
    709/// let expected = BooleanVector(vec![true, false, false, false]);
    710/// assert_eq!(bv, expected);
    711/// ```
    712#[lang = "bitand_assign"]
    713#[doc(alias = "&=")]
    714#[stable(feature = "op_assign_traits", since = "1.8.0")]
    715#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    716#[diagnostic::on_unimplemented(
    717    message = "no implementation for `{Self} &= {Rhs}`",
    718    label = "no implementation for `{Self} &= {Rhs}`"
    719)]
    720#[const_trait]
    721pub trait BitAndAssign<Rhs = Self> {
    722    /// Performs the `&=` operation.
    723    ///
    724    /// # Examples
    725    ///
    726    /// ```
    727    /// let mut x = true;
    728    /// x &= false;
    729    /// assert_eq!(x, false);
    730    ///
    731    /// let mut x = true;
    732    /// x &= true;
    733    /// assert_eq!(x, true);
    734    ///
    735    /// let mut x: u8 = 5;
    736    /// x &= 1;
    737    /// assert_eq!(x, 1);
    738    ///
    739    /// let mut x: u8 = 5;
    740    /// x &= 2;
    741    /// assert_eq!(x, 0);
    742    /// ```
    743    #[stable(feature = "op_assign_traits", since = "1.8.0")]
    744    fn bitand_assign(&mut self, rhs: Rhs);
    745}
    746
    747macro_rules! bitand_assign_impl {
    748    ($($t:ty)+) => ($(
    749        #[stable(feature = "op_assign_traits", since = "1.8.0")]
    750        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    751        impl const BitAndAssign for $t {
    752            #[inline]
    753            fn bitand_assign(&mut self, other: $t) { *self &= other }
    754        }
    755
    756        forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t,
    757        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
    758        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    759    )+)
    760}
    761
    762bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
    763
    764/// The bitwise OR assignment operator `|=`.
    765///
    766/// # Examples
    767///
    768/// ```
    769/// use std::ops::BitOrAssign;
    770///
    771/// #[derive(Debug, PartialEq)]
    772/// struct PersonalPreferences {
    773///     likes_cats: bool,
    774///     likes_dogs: bool,
    775/// }
    776///
    777/// impl BitOrAssign for PersonalPreferences {
    778///     fn bitor_assign(&mut self, rhs: Self) {
    779///         self.likes_cats |= rhs.likes_cats;
    780///         self.likes_dogs |= rhs.likes_dogs;
    781///     }
    782/// }
    783///
    784/// let mut prefs = PersonalPreferences { likes_cats: true, likes_dogs: false };
    785/// prefs |= PersonalPreferences { likes_cats: false, likes_dogs: true };
    786/// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true });
    787/// ```
    788#[lang = "bitor_assign"]
    789#[doc(alias = "|=")]
    790#[stable(feature = "op_assign_traits", since = "1.8.0")]
    791#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    792#[diagnostic::on_unimplemented(
    793    message = "no implementation for `{Self} |= {Rhs}`",
    794    label = "no implementation for `{Self} |= {Rhs}`"
    795)]
    796#[const_trait]
    797pub trait BitOrAssign<Rhs = Self> {
    798    /// Performs the `|=` operation.
    799    ///
    800    /// # Examples
    801    ///
    802    /// ```
    803    /// let mut x = true;
    804    /// x |= false;
    805    /// assert_eq!(x, true);
    806    ///
    807    /// let mut x = false;
    808    /// x |= false;
    809    /// assert_eq!(x, false);
    810    ///
    811    /// let mut x: u8 = 5;
    812    /// x |= 1;
    813    /// assert_eq!(x, 5);
    814    ///
    815    /// let mut x: u8 = 5;
    816    /// x |= 2;
    817    /// assert_eq!(x, 7);
    818    /// ```
    819    #[stable(feature = "op_assign_traits", since = "1.8.0")]
    820    fn bitor_assign(&mut self, rhs: Rhs);
    821}
    822
    823macro_rules! bitor_assign_impl {
    824    ($($t:ty)+) => ($(
    825        #[stable(feature = "op_assign_traits", since = "1.8.0")]
    826        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    827        impl const BitOrAssign for $t {
    828            #[inline]
    829            fn bitor_assign(&mut self, other: $t) { *self |= other }
    830        }
    831
    832        forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t,
    833        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
    834        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    835    )+)
    836}
    837
    838bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
    839
    840/// The bitwise XOR assignment operator `^=`.
    841///
    842/// # Examples
    843///
    844/// ```
    845/// use std::ops::BitXorAssign;
    846///
    847/// #[derive(Debug, PartialEq)]
    848/// struct Personality {
    849///     has_soul: bool,
    850///     likes_knitting: bool,
    851/// }
    852///
    853/// impl BitXorAssign for Personality {
    854///     fn bitxor_assign(&mut self, rhs: Self) {
    855///         self.has_soul ^= rhs.has_soul;
    856///         self.likes_knitting ^= rhs.likes_knitting;
    857///     }
    858/// }
    859///
    860/// let mut personality = Personality { has_soul: false, likes_knitting: true };
    861/// personality ^= Personality { has_soul: true, likes_knitting: true };
    862/// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false});
    863/// ```
    864#[lang = "bitxor_assign"]
    865#[doc(alias = "^=")]
    866#[stable(feature = "op_assign_traits", since = "1.8.0")]
    867#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    868#[diagnostic::on_unimplemented(
    869    message = "no implementation for `{Self} ^= {Rhs}`",
    870    label = "no implementation for `{Self} ^= {Rhs}`"
    871)]
    872#[const_trait]
    873pub trait BitXorAssign<Rhs = Self> {
    874    /// Performs the `^=` operation.
    875    ///
    876    /// # Examples
    877    ///
    878    /// ```
    879    /// let mut x = true;
    880    /// x ^= false;
    881    /// assert_eq!(x, true);
    882    ///
    883    /// let mut x = true;
    884    /// x ^= true;
    885    /// assert_eq!(x, false);
    886    ///
    887    /// let mut x: u8 = 5;
    888    /// x ^= 1;
    889    /// assert_eq!(x, 4);
    890    ///
    891    /// let mut x: u8 = 5;
    892    /// x ^= 2;
    893    /// assert_eq!(x, 7);
    894    /// ```
    895    #[stable(feature = "op_assign_traits", since = "1.8.0")]
    896    fn bitxor_assign(&mut self, rhs: Rhs);
    897}
    898
    899macro_rules! bitxor_assign_impl {
    900    ($($t:ty)+) => ($(
    901        #[stable(feature = "op_assign_traits", since = "1.8.0")]
    902        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    903        impl const BitXorAssign for $t {
    904            #[inline]
    905            fn bitxor_assign(&mut self, other: $t) { *self ^= other }
    906        }
    907
    908        forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t,
    909        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
    910        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    911    )+)
    912}
    913
    914bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
    915
    916/// The left shift assignment operator `<<=`.
    917///
    918/// # Examples
    919///
    920/// An implementation of `ShlAssign` for a wrapper around `usize`.
    921///
    922/// ```
    923/// use std::ops::ShlAssign;
    924///
    925/// #[derive(Debug, PartialEq)]
    926/// struct Scalar(usize);
    927///
    928/// impl ShlAssign<usize> for Scalar {
    929///     fn shl_assign(&mut self, rhs: usize) {
    930///         self.0 <<= rhs;
    931///     }
    932/// }
    933///
    934/// let mut scalar = Scalar(4);
    935/// scalar <<= 2;
    936/// assert_eq!(scalar, Scalar(16));
    937/// ```
    938#[lang = "shl_assign"]
    939#[doc(alias = "<<=")]
    940#[stable(feature = "op_assign_traits", since = "1.8.0")]
    941#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    942#[diagnostic::on_unimplemented(
    943    message = "no implementation for `{Self} <<= {Rhs}`",
    944    label = "no implementation for `{Self} <<= {Rhs}`"
    945)]
    946#[const_trait]
    947pub trait ShlAssign<Rhs = Self> {
    948    /// Performs the `<<=` operation.
    949    ///
    950    /// # Examples
    951    ///
    952    /// ```
    953    /// let mut x: u8 = 5;
    954    /// x <<= 1;
    955    /// assert_eq!(x, 10);
    956    ///
    957    /// let mut x: u8 = 1;
    958    /// x <<= 1;
    959    /// assert_eq!(x, 2);
    960    /// ```
    961    #[stable(feature = "op_assign_traits", since = "1.8.0")]
    962    fn shl_assign(&mut self, rhs: Rhs);
    963}
    964
    965macro_rules! shl_assign_impl {
    966    ($t:ty, $f:ty) => {
    967        #[stable(feature = "op_assign_traits", since = "1.8.0")]
    968        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    969        impl const ShlAssign<$f> for $t {
    970            #[inline]
    971            #[rustc_inherit_overflow_checks]
    972            fn shl_assign(&mut self, other: $f) {
    973                *self <<= other
    974            }
    975        }
    976
    977        forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f,
    978        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
    979        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    980    };
    981}
    982
    983macro_rules! shl_assign_impl_all {
    984    ($($t:ty)*) => ($(
    985        shl_assign_impl! { $t, u8 }
    986        shl_assign_impl! { $t, u16 }
    987        shl_assign_impl! { $t, u32 }
    988        shl_assign_impl! { $t, u64 }
    989        shl_assign_impl! { $t, u128 }
    990        shl_assign_impl! { $t, usize }
    991
    992        shl_assign_impl! { $t, i8 }
    993        shl_assign_impl! { $t, i16 }
    994        shl_assign_impl! { $t, i32 }
    995        shl_assign_impl! { $t, i64 }
    996        shl_assign_impl! { $t, i128 }
    997        shl_assign_impl! { $t, isize }
    998    )*)
    999}
    1000
    1001shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    1002
    1003/// The right shift assignment operator `>>=`.
    1004///
    1005/// # Examples
    1006///
    1007/// An implementation of `ShrAssign` for a wrapper around `usize`.
    1008///
    1009/// ```
    1010/// use std::ops::ShrAssign;
    1011///
    1012/// #[derive(Debug, PartialEq)]
    1013/// struct Scalar(usize);
    1014///
    1015/// impl ShrAssign<usize> for Scalar {
    1016///     fn shr_assign(&mut self, rhs: usize) {
    1017///         self.0 >>= rhs;
    1018///     }
    1019/// }
    1020///
    1021/// let mut scalar = Scalar(16);
    1022/// scalar >>= 2;
    1023/// assert_eq!(scalar, Scalar(4));
    1024/// ```
    1025#[lang = "shr_assign"]
    1026#[doc(alias = ">>=")]
    1027#[stable(feature = "op_assign_traits", since = "1.8.0")]
    1028#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    1029#[diagnostic::on_unimplemented(
    1030    message = "no implementation for `{Self} >>= {Rhs}`",
    1031    label = "no implementation for `{Self} >>= {Rhs}`"
    1032)]
    1033#[const_trait]
    1034pub trait ShrAssign<Rhs = Self> {
    1035    /// Performs the `>>=` operation.
    1036    ///
    1037    /// # Examples
    1038    ///
    1039    /// ```
    1040    /// let mut x: u8 = 5;
    1041    /// x >>= 1;
    1042    /// assert_eq!(x, 2);
    1043    ///
    1044    /// let mut x: u8 = 2;
    1045    /// x >>= 1;
    1046    /// assert_eq!(x, 1);
    1047    /// ```
    1048    #[stable(feature = "op_assign_traits", since = "1.8.0")]
    1049    fn shr_assign(&mut self, rhs: Rhs);
    1050}
    1051
    1052macro_rules! shr_assign_impl {
    1053    ($t:ty, $f:ty) => {
    1054        #[stable(feature = "op_assign_traits", since = "1.8.0")]
    1055        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
    1056        impl const ShrAssign<$f> for $t {
    1057            #[inline]
    1058            #[rustc_inherit_overflow_checks]
    1059            fn shr_assign(&mut self, other: $f) {
    1060                *self >>= other
    1061            }
    1062        }
    1063
    1064        forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f,
    1065        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
    1066        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    1067    };
    1068}
    1069
    1070macro_rules! shr_assign_impl_all {
    1071    ($($t:ty)*) => ($(
    1072        shr_assign_impl! { $t, u8 }
    1073        shr_assign_impl! { $t, u16 }
    1074        shr_assign_impl! { $t, u32 }
    1075        shr_assign_impl! { $t, u64 }
    1076        shr_assign_impl! { $t, u128 }
    1077        shr_assign_impl! { $t, usize }
    1078
    1079        shr_assign_impl! { $t, i8 }
    1080        shr_assign_impl! { $t, i16 }
    1081        shr_assign_impl! { $t, i32 }
    1082        shr_assign_impl! { $t, i64 }
    1083        shr_assign_impl! { $t, i128 }
    1084        shr_assign_impl! { $t, isize }
    1085    )*)
    1086}
    1087
    1088shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }