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