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