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