Skip to main content

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            #[track_caller]
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            #[track_caller]
611            #[rustc_inherit_overflow_checks]
612            fn shr(self, other: $f) -> $t {
613                self >> other
614            }
615        }
616
617        forward_ref_binop! { impl Shr, shr for $t, $f,
618        #[stable(feature = "rust1", since = "1.0.0")]
619        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
620    };
621}
622
623macro_rules! shr_impl_all {
624    ($($t:ty)*) => ($(
625        shr_impl! { $t, u8 }
626        shr_impl! { $t, u16 }
627        shr_impl! { $t, u32 }
628        shr_impl! { $t, u64 }
629        shr_impl! { $t, u128 }
630        shr_impl! { $t, usize }
631
632        shr_impl! { $t, i8 }
633        shr_impl! { $t, i16 }
634        shr_impl! { $t, i32 }
635        shr_impl! { $t, i64 }
636        shr_impl! { $t, i128 }
637        shr_impl! { $t, isize }
638    )*)
639}
640
641shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
642
643/// The bitwise AND assignment operator `&=`.
644///
645/// # Examples
646///
647/// An implementation of `BitAndAssign` that lifts the `&=` operator to a
648/// wrapper around `bool`.
649///
650/// ```
651/// use std::ops::BitAndAssign;
652///
653/// #[derive(Debug, PartialEq)]
654/// struct Scalar(bool);
655///
656/// impl BitAndAssign for Scalar {
657///     // rhs is the "right-hand side" of the expression `a &= b`
658///     fn bitand_assign(&mut self, rhs: Self) {
659///         *self = Self(self.0 & rhs.0)
660///     }
661/// }
662///
663/// let mut scalar = Scalar(true);
664/// scalar &= Scalar(true);
665/// assert_eq!(scalar, Scalar(true));
666///
667/// let mut scalar = Scalar(true);
668/// scalar &= Scalar(false);
669/// assert_eq!(scalar, Scalar(false));
670///
671/// let mut scalar = Scalar(false);
672/// scalar &= Scalar(true);
673/// assert_eq!(scalar, Scalar(false));
674///
675/// let mut scalar = Scalar(false);
676/// scalar &= Scalar(false);
677/// assert_eq!(scalar, Scalar(false));
678/// ```
679///
680/// Here, the `BitAndAssign` trait is implemented for a wrapper around
681/// `Vec<bool>`.
682///
683/// ```
684/// use std::ops::BitAndAssign;
685///
686/// #[derive(Debug, PartialEq)]
687/// struct BooleanVector(Vec<bool>);
688///
689/// impl BitAndAssign for BooleanVector {
690///     // `rhs` is the "right-hand side" of the expression `a &= b`.
691///     fn bitand_assign(&mut self, rhs: Self) {
692///         assert_eq!(self.0.len(), rhs.0.len());
693///         *self = Self(
694///             self.0
695///                 .iter()
696///                 .zip(rhs.0.iter())
697///                 .map(|(x, y)| *x & *y)
698///                 .collect()
699///         );
700///     }
701/// }
702///
703/// let mut bv = BooleanVector(vec![true, true, false, false]);
704/// bv &= BooleanVector(vec![true, false, true, false]);
705/// let expected = BooleanVector(vec![true, false, false, false]);
706/// assert_eq!(bv, expected);
707/// ```
708#[lang = "bitand_assign"]
709#[doc(alias = "&=")]
710#[stable(feature = "op_assign_traits", since = "1.8.0")]
711#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
712#[diagnostic::on_unimplemented(
713    message = "no implementation for `{Self} &= {Rhs}`",
714    label = "no implementation for `{Self} &= {Rhs}`"
715)]
716pub const trait BitAndAssign<Rhs = Self> {
717    /// Performs the `&=` operation.
718    ///
719    /// # Examples
720    ///
721    /// ```
722    /// let mut x = true;
723    /// x &= false;
724    /// assert_eq!(x, false);
725    ///
726    /// let mut x = true;
727    /// x &= true;
728    /// assert_eq!(x, true);
729    ///
730    /// let mut x: u8 = 5;
731    /// x &= 1;
732    /// assert_eq!(x, 1);
733    ///
734    /// let mut x: u8 = 5;
735    /// x &= 2;
736    /// assert_eq!(x, 0);
737    /// ```
738    #[stable(feature = "op_assign_traits", since = "1.8.0")]
739    fn bitand_assign(&mut self, rhs: Rhs);
740}
741
742macro_rules! bitand_assign_impl {
743    ($($t:ty)+) => ($(
744        #[stable(feature = "op_assign_traits", since = "1.8.0")]
745        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
746        impl const BitAndAssign for $t {
747            #[inline]
748            fn bitand_assign(&mut self, other: $t) { *self &= other }
749        }
750
751        forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t,
752        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
753        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
754    )+)
755}
756
757bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
758
759/// The bitwise OR assignment operator `|=`.
760///
761/// # Examples
762///
763/// ```
764/// use std::ops::BitOrAssign;
765///
766/// #[derive(Debug, PartialEq)]
767/// struct PersonalPreferences {
768///     likes_cats: bool,
769///     likes_dogs: bool,
770/// }
771///
772/// impl BitOrAssign for PersonalPreferences {
773///     fn bitor_assign(&mut self, rhs: Self) {
774///         self.likes_cats |= rhs.likes_cats;
775///         self.likes_dogs |= rhs.likes_dogs;
776///     }
777/// }
778///
779/// let mut prefs = PersonalPreferences { likes_cats: true, likes_dogs: false };
780/// prefs |= PersonalPreferences { likes_cats: false, likes_dogs: true };
781/// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true });
782/// ```
783#[lang = "bitor_assign"]
784#[doc(alias = "|=")]
785#[stable(feature = "op_assign_traits", since = "1.8.0")]
786#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
787#[diagnostic::on_unimplemented(
788    message = "no implementation for `{Self} |= {Rhs}`",
789    label = "no implementation for `{Self} |= {Rhs}`"
790)]
791pub const trait BitOrAssign<Rhs = Self> {
792    /// Performs the `|=` operation.
793    ///
794    /// # Examples
795    ///
796    /// ```
797    /// let mut x = true;
798    /// x |= false;
799    /// assert_eq!(x, true);
800    ///
801    /// let mut x = false;
802    /// x |= false;
803    /// assert_eq!(x, false);
804    ///
805    /// let mut x: u8 = 5;
806    /// x |= 1;
807    /// assert_eq!(x, 5);
808    ///
809    /// let mut x: u8 = 5;
810    /// x |= 2;
811    /// assert_eq!(x, 7);
812    /// ```
813    #[stable(feature = "op_assign_traits", since = "1.8.0")]
814    fn bitor_assign(&mut self, rhs: Rhs);
815}
816
817macro_rules! bitor_assign_impl {
818    ($($t:ty)+) => ($(
819        #[stable(feature = "op_assign_traits", since = "1.8.0")]
820        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
821        impl const BitOrAssign for $t {
822            #[inline]
823            fn bitor_assign(&mut self, other: $t) { *self |= other }
824        }
825
826        forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t,
827        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
828        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
829    )+)
830}
831
832bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
833
834/// The bitwise XOR assignment operator `^=`.
835///
836/// # Examples
837///
838/// ```
839/// use std::ops::BitXorAssign;
840///
841/// #[derive(Debug, PartialEq)]
842/// struct Personality {
843///     has_soul: bool,
844///     likes_knitting: bool,
845/// }
846///
847/// impl BitXorAssign for Personality {
848///     fn bitxor_assign(&mut self, rhs: Self) {
849///         self.has_soul ^= rhs.has_soul;
850///         self.likes_knitting ^= rhs.likes_knitting;
851///     }
852/// }
853///
854/// let mut personality = Personality { has_soul: false, likes_knitting: true };
855/// personality ^= Personality { has_soul: true, likes_knitting: true };
856/// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false});
857/// ```
858#[lang = "bitxor_assign"]
859#[doc(alias = "^=")]
860#[stable(feature = "op_assign_traits", since = "1.8.0")]
861#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
862#[diagnostic::on_unimplemented(
863    message = "no implementation for `{Self} ^= {Rhs}`",
864    label = "no implementation for `{Self} ^= {Rhs}`"
865)]
866pub const trait BitXorAssign<Rhs = Self> {
867    /// Performs the `^=` operation.
868    ///
869    /// # Examples
870    ///
871    /// ```
872    /// let mut x = true;
873    /// x ^= false;
874    /// assert_eq!(x, true);
875    ///
876    /// let mut x = true;
877    /// x ^= true;
878    /// assert_eq!(x, false);
879    ///
880    /// let mut x: u8 = 5;
881    /// x ^= 1;
882    /// assert_eq!(x, 4);
883    ///
884    /// let mut x: u8 = 5;
885    /// x ^= 2;
886    /// assert_eq!(x, 7);
887    /// ```
888    #[stable(feature = "op_assign_traits", since = "1.8.0")]
889    fn bitxor_assign(&mut self, rhs: Rhs);
890}
891
892macro_rules! bitxor_assign_impl {
893    ($($t:ty)+) => ($(
894        #[stable(feature = "op_assign_traits", since = "1.8.0")]
895        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
896        impl const BitXorAssign for $t {
897            #[inline]
898            fn bitxor_assign(&mut self, other: $t) { *self ^= other }
899        }
900
901        forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t,
902        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
903        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
904    )+)
905}
906
907bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
908
909/// The left shift assignment operator `<<=`.
910///
911/// # Examples
912///
913/// An implementation of `ShlAssign` for a wrapper around `usize`.
914///
915/// ```
916/// use std::ops::ShlAssign;
917///
918/// #[derive(Debug, PartialEq)]
919/// struct Scalar(usize);
920///
921/// impl ShlAssign<usize> for Scalar {
922///     fn shl_assign(&mut self, rhs: usize) {
923///         self.0 <<= rhs;
924///     }
925/// }
926///
927/// let mut scalar = Scalar(4);
928/// scalar <<= 2;
929/// assert_eq!(scalar, Scalar(16));
930/// ```
931#[lang = "shl_assign"]
932#[doc(alias = "<<=")]
933#[stable(feature = "op_assign_traits", since = "1.8.0")]
934#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
935#[diagnostic::on_unimplemented(
936    message = "no implementation for `{Self} <<= {Rhs}`",
937    label = "no implementation for `{Self} <<= {Rhs}`"
938)]
939pub const trait ShlAssign<Rhs = Self> {
940    /// Performs the `<<=` operation.
941    ///
942    /// # Examples
943    ///
944    /// ```
945    /// let mut x: u8 = 5;
946    /// x <<= 1;
947    /// assert_eq!(x, 10);
948    ///
949    /// let mut x: u8 = 1;
950    /// x <<= 1;
951    /// assert_eq!(x, 2);
952    /// ```
953    #[stable(feature = "op_assign_traits", since = "1.8.0")]
954    fn shl_assign(&mut self, rhs: Rhs);
955}
956
957macro_rules! shl_assign_impl {
958    ($t:ty, $f:ty) => {
959        #[stable(feature = "op_assign_traits", since = "1.8.0")]
960        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
961        impl const ShlAssign<$f> for $t {
962            #[inline]
963            #[track_caller]
964            #[rustc_inherit_overflow_checks]
965            fn shl_assign(&mut self, other: $f) {
966                *self <<= other
967            }
968        }
969
970        forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f,
971        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
972        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
973    };
974}
975
976macro_rules! shl_assign_impl_all {
977    ($($t:ty)*) => ($(
978        shl_assign_impl! { $t, u8 }
979        shl_assign_impl! { $t, u16 }
980        shl_assign_impl! { $t, u32 }
981        shl_assign_impl! { $t, u64 }
982        shl_assign_impl! { $t, u128 }
983        shl_assign_impl! { $t, usize }
984
985        shl_assign_impl! { $t, i8 }
986        shl_assign_impl! { $t, i16 }
987        shl_assign_impl! { $t, i32 }
988        shl_assign_impl! { $t, i64 }
989        shl_assign_impl! { $t, i128 }
990        shl_assign_impl! { $t, isize }
991    )*)
992}
993
994shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
995
996/// The right shift assignment operator `>>=`.
997///
998/// # Examples
999///
1000/// An implementation of `ShrAssign` for a wrapper around `usize`.
1001///
1002/// ```
1003/// use std::ops::ShrAssign;
1004///
1005/// #[derive(Debug, PartialEq)]
1006/// struct Scalar(usize);
1007///
1008/// impl ShrAssign<usize> for Scalar {
1009///     fn shr_assign(&mut self, rhs: usize) {
1010///         self.0 >>= rhs;
1011///     }
1012/// }
1013///
1014/// let mut scalar = Scalar(16);
1015/// scalar >>= 2;
1016/// assert_eq!(scalar, Scalar(4));
1017/// ```
1018#[lang = "shr_assign"]
1019#[doc(alias = ">>=")]
1020#[stable(feature = "op_assign_traits", since = "1.8.0")]
1021#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
1022#[diagnostic::on_unimplemented(
1023    message = "no implementation for `{Self} >>= {Rhs}`",
1024    label = "no implementation for `{Self} >>= {Rhs}`"
1025)]
1026pub const trait ShrAssign<Rhs = Self> {
1027    /// Performs the `>>=` operation.
1028    ///
1029    /// # Examples
1030    ///
1031    /// ```
1032    /// let mut x: u8 = 5;
1033    /// x >>= 1;
1034    /// assert_eq!(x, 2);
1035    ///
1036    /// let mut x: u8 = 2;
1037    /// x >>= 1;
1038    /// assert_eq!(x, 1);
1039    /// ```
1040    #[stable(feature = "op_assign_traits", since = "1.8.0")]
1041    fn shr_assign(&mut self, rhs: Rhs);
1042}
1043
1044macro_rules! shr_assign_impl {
1045    ($t:ty, $f:ty) => {
1046        #[stable(feature = "op_assign_traits", since = "1.8.0")]
1047        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
1048        impl const ShrAssign<$f> for $t {
1049            #[inline]
1050            #[track_caller]
1051            #[rustc_inherit_overflow_checks]
1052            fn shr_assign(&mut self, other: $f) {
1053                *self >>= other
1054            }
1055        }
1056
1057        forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f,
1058        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
1059        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
1060    };
1061}
1062
1063macro_rules! shr_assign_impl_all {
1064    ($($t:ty)*) => ($(
1065        shr_assign_impl! { $t, u8 }
1066        shr_assign_impl! { $t, u16 }
1067        shr_assign_impl! { $t, u32 }
1068        shr_assign_impl! { $t, u64 }
1069        shr_assign_impl! { $t, u128 }
1070        shr_assign_impl! { $t, usize }
1071
1072        shr_assign_impl! { $t, i8 }
1073        shr_assign_impl! { $t, i16 }
1074        shr_assign_impl! { $t, i32 }
1075        shr_assign_impl! { $t, i64 }
1076        shr_assign_impl! { $t, i128 }
1077        shr_assign_impl! { $t, isize }
1078    )*)
1079}
1080
1081shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }