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