Skip to main content

core/ops/
bit.rs

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