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