]> git.lizzy.rs Git - rust.git/blob - src/libcore/ops/bit.rs
Rollup merge of #47922 - zackmdavis:and_the_case_of_the_unused_field_pattern, r=estebank
[rust.git] / src / libcore / ops / bit.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /// The unary logical negation operator `!`.
12 ///
13 /// # Examples
14 ///
15 /// An implementation of `Not` for `Answer`, which enables the use of `!` to
16 /// invert its value.
17 ///
18 /// ```
19 /// use std::ops::Not;
20 ///
21 /// #[derive(Debug, PartialEq)]
22 /// enum Answer {
23 ///     Yes,
24 ///     No,
25 /// }
26 ///
27 /// impl Not for Answer {
28 ///     type Output = Answer;
29 ///
30 ///     fn not(self) -> Answer {
31 ///         match self {
32 ///             Answer::Yes => Answer::No,
33 ///             Answer::No => Answer::Yes
34 ///         }
35 ///     }
36 /// }
37 ///
38 /// assert_eq!(!Answer::Yes, Answer::No);
39 /// assert_eq!(!Answer::No, Answer::Yes);
40 /// ```
41 #[lang = "not"]
42 #[stable(feature = "rust1", since = "1.0.0")]
43 pub trait Not {
44     /// The resulting type after applying the `!` operator.
45     #[stable(feature = "rust1", since = "1.0.0")]
46     type Output;
47
48     /// Performs the unary `!` operation.
49     #[stable(feature = "rust1", since = "1.0.0")]
50     fn not(self) -> Self::Output;
51 }
52
53 macro_rules! not_impl {
54     ($($t:ty)*) => ($(
55         #[stable(feature = "rust1", since = "1.0.0")]
56         impl Not for $t {
57             type Output = $t;
58
59             #[inline]
60             fn not(self) -> $t { !self }
61         }
62
63         forward_ref_unop! { impl Not, not for $t }
64     )*)
65 }
66
67 not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
68
69 /// The bitwise AND operator `&`.
70 ///
71 /// Note that `RHS` is `Self` by default, but this is not mandatory.
72 ///
73 /// # Examples
74 ///
75 /// An implementation of `BitAnd` for a wrapper around `bool`.
76 ///
77 /// ```
78 /// use std::ops::BitAnd;
79 ///
80 /// #[derive(Debug, PartialEq)]
81 /// struct Scalar(bool);
82 ///
83 /// impl BitAnd for Scalar {
84 ///     type Output = Self;
85 ///
86 ///     // rhs is the "right-hand side" of the expression `a & b`
87 ///     fn bitand(self, rhs: Self) -> Self {
88 ///         Scalar(self.0 & rhs.0)
89 ///     }
90 /// }
91 ///
92 /// assert_eq!(Scalar(true) & Scalar(true), Scalar(true));
93 /// assert_eq!(Scalar(true) & Scalar(false), Scalar(false));
94 /// assert_eq!(Scalar(false) & Scalar(true), Scalar(false));
95 /// assert_eq!(Scalar(false) & Scalar(false), Scalar(false));
96 /// ```
97 ///
98 /// An implementation of `BitAnd` for a wrapper around `Vec<bool>`.
99 ///
100 /// ```
101 /// use std::ops::BitAnd;
102 ///
103 /// #[derive(Debug, PartialEq)]
104 /// struct BooleanVector(Vec<bool>);
105 ///
106 /// impl BitAnd for BooleanVector {
107 ///     type Output = Self;
108 ///
109 ///     fn bitand(self, BooleanVector(rhs): Self) -> Self {
110 ///         let BooleanVector(lhs) = self;
111 ///         assert_eq!(lhs.len(), rhs.len());
112 ///         BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect())
113 ///     }
114 /// }
115 ///
116 /// let bv1 = BooleanVector(vec![true, true, false, false]);
117 /// let bv2 = BooleanVector(vec![true, false, true, false]);
118 /// let expected = BooleanVector(vec![true, false, false, false]);
119 /// assert_eq!(bv1 & bv2, expected);
120 /// ```
121 #[lang = "bitand"]
122 #[stable(feature = "rust1", since = "1.0.0")]
123 #[rustc_on_unimplemented(message="no implementation for `{Self} & {RHS}`",
124                          label="no implementation for `{Self} & {RHS}`")]
125 pub trait BitAnd<RHS=Self> {
126     /// The resulting type after applying the `&` operator.
127     #[stable(feature = "rust1", since = "1.0.0")]
128     type Output;
129
130     /// Performs the `&` operation.
131     #[stable(feature = "rust1", since = "1.0.0")]
132     fn bitand(self, rhs: RHS) -> Self::Output;
133 }
134
135 macro_rules! bitand_impl {
136     ($($t:ty)*) => ($(
137         #[stable(feature = "rust1", since = "1.0.0")]
138         impl BitAnd for $t {
139             type Output = $t;
140
141             #[inline]
142             fn bitand(self, rhs: $t) -> $t { self & rhs }
143         }
144
145         forward_ref_binop! { impl BitAnd, bitand for $t, $t }
146     )*)
147 }
148
149 bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
150
151 /// The bitwise OR operator `|`.
152 ///
153 /// Note that `RHS` is `Self` by default, but this is not mandatory.
154 ///
155 /// # Examples
156 ///
157 /// An implementation of `BitOr` for a wrapper around `bool`.
158 ///
159 /// ```
160 /// use std::ops::BitOr;
161 ///
162 /// #[derive(Debug, PartialEq)]
163 /// struct Scalar(bool);
164 ///
165 /// impl BitOr for Scalar {
166 ///     type Output = Self;
167 ///
168 ///     // rhs is the "right-hand side" of the expression `a | b`
169 ///     fn bitor(self, rhs: Self) -> Self {
170 ///         Scalar(self.0 | rhs.0)
171 ///     }
172 /// }
173 ///
174 /// assert_eq!(Scalar(true) | Scalar(true), Scalar(true));
175 /// assert_eq!(Scalar(true) | Scalar(false), Scalar(true));
176 /// assert_eq!(Scalar(false) | Scalar(true), Scalar(true));
177 /// assert_eq!(Scalar(false) | Scalar(false), Scalar(false));
178 /// ```
179 ///
180 /// An implementation of `BitOr` for a wrapper around `Vec<bool>`.
181 ///
182 /// ```
183 /// use std::ops::BitOr;
184 ///
185 /// #[derive(Debug, PartialEq)]
186 /// struct BooleanVector(Vec<bool>);
187 ///
188 /// impl BitOr for BooleanVector {
189 ///     type Output = Self;
190 ///
191 ///     fn bitor(self, BooleanVector(rhs): Self) -> Self {
192 ///         let BooleanVector(lhs) = self;
193 ///         assert_eq!(lhs.len(), rhs.len());
194 ///         BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect())
195 ///     }
196 /// }
197 ///
198 /// let bv1 = BooleanVector(vec![true, true, false, false]);
199 /// let bv2 = BooleanVector(vec![true, false, true, false]);
200 /// let expected = BooleanVector(vec![true, true, true, false]);
201 /// assert_eq!(bv1 | bv2, expected);
202 /// ```
203 #[lang = "bitor"]
204 #[stable(feature = "rust1", since = "1.0.0")]
205 #[rustc_on_unimplemented(message="no implementation for `{Self} | {RHS}`",
206                          label="no implementation for `{Self} | {RHS}`")]
207 pub trait BitOr<RHS=Self> {
208     /// The resulting type after applying the `|` operator.
209     #[stable(feature = "rust1", since = "1.0.0")]
210     type Output;
211
212     /// Performs the `|` operation.
213     #[stable(feature = "rust1", since = "1.0.0")]
214     fn bitor(self, rhs: RHS) -> Self::Output;
215 }
216
217 macro_rules! bitor_impl {
218     ($($t:ty)*) => ($(
219         #[stable(feature = "rust1", since = "1.0.0")]
220         impl BitOr for $t {
221             type Output = $t;
222
223             #[inline]
224             fn bitor(self, rhs: $t) -> $t { self | rhs }
225         }
226
227         forward_ref_binop! { impl BitOr, bitor for $t, $t }
228     )*)
229 }
230
231 bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
232
233 /// The bitwise XOR operator `^`.
234 ///
235 /// Note that `RHS` is `Self` by default, but this is not mandatory.
236 ///
237 /// # Examples
238 ///
239 /// An implementation of `BitXor` that lifts `^` to a wrapper around `bool`.
240 ///
241 /// ```
242 /// use std::ops::BitXor;
243 ///
244 /// #[derive(Debug, PartialEq)]
245 /// struct Scalar(bool);
246 ///
247 /// impl BitXor for Scalar {
248 ///     type Output = Self;
249 ///
250 ///     // rhs is the "right-hand side" of the expression `a ^ b`
251 ///     fn bitxor(self, rhs: Self) -> Self {
252 ///         Scalar(self.0 ^ rhs.0)
253 ///     }
254 /// }
255 ///
256 /// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false));
257 /// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true));
258 /// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true));
259 /// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false));
260 /// ```
261 ///
262 /// An implementation of `BitXor` trait for a wrapper around `Vec<bool>`.
263 ///
264 /// ```
265 /// use std::ops::BitXor;
266 ///
267 /// #[derive(Debug, PartialEq)]
268 /// struct BooleanVector(Vec<bool>);
269 ///
270 /// impl BitXor for BooleanVector {
271 ///     type Output = Self;
272 ///
273 ///     fn bitxor(self, BooleanVector(rhs): Self) -> Self {
274 ///         let BooleanVector(lhs) = self;
275 ///         assert_eq!(lhs.len(), rhs.len());
276 ///         BooleanVector(lhs.iter()
277 ///                          .zip(rhs.iter())
278 ///                          .map(|(x, y)| (*x || *y) && !(*x && *y))
279 ///                          .collect())
280 ///     }
281 /// }
282 ///
283 /// let bv1 = BooleanVector(vec![true, true, false, false]);
284 /// let bv2 = BooleanVector(vec![true, false, true, false]);
285 /// let expected = BooleanVector(vec![false, true, true, false]);
286 /// assert_eq!(bv1 ^ bv2, expected);
287 /// ```
288 #[lang = "bitxor"]
289 #[stable(feature = "rust1", since = "1.0.0")]
290 #[rustc_on_unimplemented(message="no implementation for `{Self} ^ {RHS}`",
291                          label="no implementation for `{Self} ^ {RHS}`")]
292 pub trait BitXor<RHS=Self> {
293     /// The resulting type after applying the `^` operator.
294     #[stable(feature = "rust1", since = "1.0.0")]
295     type Output;
296
297     /// Performs the `^` operation.
298     #[stable(feature = "rust1", since = "1.0.0")]
299     fn bitxor(self, rhs: RHS) -> Self::Output;
300 }
301
302 macro_rules! bitxor_impl {
303     ($($t:ty)*) => ($(
304         #[stable(feature = "rust1", since = "1.0.0")]
305         impl BitXor for $t {
306             type Output = $t;
307
308             #[inline]
309             fn bitxor(self, other: $t) -> $t { self ^ other }
310         }
311
312         forward_ref_binop! { impl BitXor, bitxor for $t, $t }
313     )*)
314 }
315
316 bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
317
318 /// The left shift operator `<<`.
319 ///
320 /// # Examples
321 ///
322 /// An implementation of `Shl` that lifts the `<<` operation on integers to a
323 /// wrapper around `usize`.
324 ///
325 /// ```
326 /// use std::ops::Shl;
327 ///
328 /// #[derive(PartialEq, Debug)]
329 /// struct Scalar(usize);
330 ///
331 /// impl Shl<Scalar> for Scalar {
332 ///     type Output = Self;
333 ///
334 ///     fn shl(self, Scalar(rhs): Self) -> Scalar {
335 ///         let Scalar(lhs) = self;
336 ///         Scalar(lhs << rhs)
337 ///     }
338 /// }
339 ///
340 /// assert_eq!(Scalar(4) << Scalar(2), Scalar(16));
341 /// ```
342 ///
343 /// An implementation of `Shl` that spins a vector leftward by a given amount.
344 ///
345 /// ```
346 /// use std::ops::Shl;
347 ///
348 /// #[derive(PartialEq, Debug)]
349 /// struct SpinVector<T: Clone> {
350 ///     vec: Vec<T>,
351 /// }
352 ///
353 /// impl<T: Clone> Shl<usize> for SpinVector<T> {
354 ///     type Output = Self;
355 ///
356 ///     fn shl(self, rhs: usize) -> SpinVector<T> {
357 ///         // Rotate the vector by `rhs` places.
358 ///         let (a, b) = self.vec.split_at(rhs);
359 ///         let mut spun_vector: Vec<T> = vec![];
360 ///         spun_vector.extend_from_slice(b);
361 ///         spun_vector.extend_from_slice(a);
362 ///         SpinVector { vec: spun_vector }
363 ///     }
364 /// }
365 ///
366 /// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2,
367 ///            SpinVector { vec: vec![2, 3, 4, 0, 1] });
368 /// ```
369 #[lang = "shl"]
370 #[stable(feature = "rust1", since = "1.0.0")]
371 #[rustc_on_unimplemented(message="no implementation for `{Self} << {RHS}`",
372                          label="no implementation for `{Self} << {RHS}`")]
373 pub trait Shl<RHS> {
374     /// The resulting type after applying the `<<` operator.
375     #[stable(feature = "rust1", since = "1.0.0")]
376     type Output;
377
378     /// Performs the `<<` operation.
379     #[stable(feature = "rust1", since = "1.0.0")]
380     fn shl(self, rhs: RHS) -> Self::Output;
381 }
382
383 macro_rules! shl_impl {
384     ($t:ty, $f:ty) => (
385         #[stable(feature = "rust1", since = "1.0.0")]
386         impl Shl<$f> for $t {
387             type Output = $t;
388
389             #[inline]
390             #[rustc_inherit_overflow_checks]
391             fn shl(self, other: $f) -> $t {
392                 self << other
393             }
394         }
395
396         forward_ref_binop! { impl Shl, shl for $t, $f }
397     )
398 }
399
400 macro_rules! shl_impl_all {
401     ($($t:ty)*) => ($(
402         shl_impl! { $t, u8 }
403         shl_impl! { $t, u16 }
404         shl_impl! { $t, u32 }
405         shl_impl! { $t, u64 }
406         shl_impl! { $t, u128 }
407         shl_impl! { $t, usize }
408
409         shl_impl! { $t, i8 }
410         shl_impl! { $t, i16 }
411         shl_impl! { $t, i32 }
412         shl_impl! { $t, i64 }
413         shl_impl! { $t, i128 }
414         shl_impl! { $t, isize }
415     )*)
416 }
417
418 shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
419
420 /// The right shift operator `>>`.
421 ///
422 /// # Examples
423 ///
424 /// An implementation of `Shr` that lifts the `>>` operation on integers to a
425 /// wrapper around `usize`.
426 ///
427 /// ```
428 /// use std::ops::Shr;
429 ///
430 /// #[derive(PartialEq, Debug)]
431 /// struct Scalar(usize);
432 ///
433 /// impl Shr<Scalar> for Scalar {
434 ///     type Output = Self;
435 ///
436 ///     fn shr(self, Scalar(rhs): Self) -> Scalar {
437 ///         let Scalar(lhs) = self;
438 ///         Scalar(lhs >> rhs)
439 ///     }
440 /// }
441 ///
442 /// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4));
443 /// ```
444 ///
445 /// An implementation of `Shr` that spins a vector rightward by a given amount.
446 ///
447 /// ```
448 /// use std::ops::Shr;
449 ///
450 /// #[derive(PartialEq, Debug)]
451 /// struct SpinVector<T: Clone> {
452 ///     vec: Vec<T>,
453 /// }
454 ///
455 /// impl<T: Clone> Shr<usize> for SpinVector<T> {
456 ///     type Output = Self;
457 ///
458 ///     fn shr(self, rhs: usize) -> SpinVector<T> {
459 ///         // Rotate the vector by `rhs` places.
460 ///         let (a, b) = self.vec.split_at(self.vec.len() - rhs);
461 ///         let mut spun_vector: Vec<T> = vec![];
462 ///         spun_vector.extend_from_slice(b);
463 ///         spun_vector.extend_from_slice(a);
464 ///         SpinVector { vec: spun_vector }
465 ///     }
466 /// }
467 ///
468 /// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2,
469 ///            SpinVector { vec: vec![3, 4, 0, 1, 2] });
470 /// ```
471 #[lang = "shr"]
472 #[stable(feature = "rust1", since = "1.0.0")]
473 #[rustc_on_unimplemented(message="no implementation for `{Self} >> {RHS}`",
474                          label="no implementation for `{Self} >> {RHS}`")]
475 pub trait Shr<RHS> {
476     /// The resulting type after applying the `>>` operator.
477     #[stable(feature = "rust1", since = "1.0.0")]
478     type Output;
479
480     /// Performs the `>>` operation.
481     #[stable(feature = "rust1", since = "1.0.0")]
482     fn shr(self, rhs: RHS) -> Self::Output;
483 }
484
485 macro_rules! shr_impl {
486     ($t:ty, $f:ty) => (
487         #[stable(feature = "rust1", since = "1.0.0")]
488         impl Shr<$f> for $t {
489             type Output = $t;
490
491             #[inline]
492             #[rustc_inherit_overflow_checks]
493             fn shr(self, other: $f) -> $t {
494                 self >> other
495             }
496         }
497
498         forward_ref_binop! { impl Shr, shr for $t, $f }
499     )
500 }
501
502 macro_rules! shr_impl_all {
503     ($($t:ty)*) => ($(
504         shr_impl! { $t, u8 }
505         shr_impl! { $t, u16 }
506         shr_impl! { $t, u32 }
507         shr_impl! { $t, u64 }
508         shr_impl! { $t, u128 }
509         shr_impl! { $t, usize }
510
511         shr_impl! { $t, i8 }
512         shr_impl! { $t, i16 }
513         shr_impl! { $t, i32 }
514         shr_impl! { $t, i64 }
515         shr_impl! { $t, i128 }
516         shr_impl! { $t, isize }
517     )*)
518 }
519
520 shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
521
522 /// The bitwise AND assignment operator `&=`.
523 ///
524 /// # Examples
525 ///
526 /// An implementation of `BitAndAssign` that lifts the `&=` operator to a
527 /// wrapper around `bool`.
528 ///
529 /// ```
530 /// use std::ops::BitAndAssign;
531 ///
532 /// #[derive(Debug, PartialEq)]
533 /// struct Scalar(bool);
534 ///
535 /// impl BitAndAssign for Scalar {
536 ///     // rhs is the "right-hand side" of the expression `a &= b`
537 ///     fn bitand_assign(&mut self, rhs: Self) {
538 ///         *self = Scalar(self.0 & rhs.0)
539 ///     }
540 /// }
541 ///
542 /// let mut scalar = Scalar(true);
543 /// scalar &= Scalar(true);
544 /// assert_eq!(scalar, Scalar(true));
545 ///
546 /// let mut scalar = Scalar(true);
547 /// scalar &= Scalar(false);
548 /// assert_eq!(scalar, Scalar(false));
549 ///
550 /// let mut scalar = Scalar(false);
551 /// scalar &= Scalar(true);
552 /// assert_eq!(scalar, Scalar(false));
553 ///
554 /// let mut scalar = Scalar(false);
555 /// scalar &= Scalar(false);
556 /// assert_eq!(scalar, Scalar(false));
557 /// ```
558 ///
559 /// Here, the `BitAndAssign` trait is implemented for a wrapper around
560 /// `Vec<bool>`.
561 ///
562 /// ```
563 /// use std::ops::BitAndAssign;
564 ///
565 /// #[derive(Debug, PartialEq)]
566 /// struct BooleanVector(Vec<bool>);
567 ///
568 /// impl BitAndAssign for BooleanVector {
569 ///     // `rhs` is the "right-hand side" of the expression `a &= b`.
570 ///     fn bitand_assign(&mut self, rhs: Self) {
571 ///         assert_eq!(self.0.len(), rhs.0.len());
572 ///         *self = BooleanVector(self.0
573 ///                                   .iter()
574 ///                                   .zip(rhs.0.iter())
575 ///                                   .map(|(x, y)| *x && *y)
576 ///                                   .collect());
577 ///     }
578 /// }
579 ///
580 /// let mut bv = BooleanVector(vec![true, true, false, false]);
581 /// bv &= BooleanVector(vec![true, false, true, false]);
582 /// let expected = BooleanVector(vec![true, false, false, false]);
583 /// assert_eq!(bv, expected);
584 /// ```
585 #[lang = "bitand_assign"]
586 #[stable(feature = "op_assign_traits", since = "1.8.0")]
587 #[rustc_on_unimplemented(message="no implementation for `{Self} &= {Rhs}`",
588                          label="no implementation for `{Self} &= {Rhs}`")]
589 pub trait BitAndAssign<Rhs=Self> {
590     /// Performs the `&=` operation.
591     #[stable(feature = "op_assign_traits", since = "1.8.0")]
592     fn bitand_assign(&mut self, rhs: Rhs);
593 }
594
595 macro_rules! bitand_assign_impl {
596     ($($t:ty)+) => ($(
597         #[stable(feature = "op_assign_traits", since = "1.8.0")]
598         impl BitAndAssign for $t {
599             #[inline]
600             fn bitand_assign(&mut self, other: $t) { *self &= other }
601         }
602
603         forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t }
604     )+)
605 }
606
607 bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
608
609 /// The bitwise OR assignment operator `|=`.
610 ///
611 /// # Examples
612 ///
613 /// ```
614 /// use std::ops::BitOrAssign;
615 ///
616 /// #[derive(Debug, PartialEq)]
617 /// struct PersonalPreferences {
618 ///     likes_cats: bool,
619 ///     likes_dogs: bool,
620 /// }
621 ///
622 /// impl BitOrAssign for PersonalPreferences {
623 ///     fn bitor_assign(&mut self, rhs: Self) {
624 ///         self.likes_cats |= rhs.likes_cats;
625 ///         self.likes_dogs |= rhs.likes_dogs;
626 ///     }
627 /// }
628 ///
629 /// let mut prefs = PersonalPreferences { likes_cats: true, likes_dogs: false };
630 /// prefs |= PersonalPreferences { likes_cats: false, likes_dogs: true };
631 /// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true });
632 /// ```
633 #[lang = "bitor_assign"]
634 #[stable(feature = "op_assign_traits", since = "1.8.0")]
635 #[rustc_on_unimplemented(message="no implementation for `{Self} |= {Rhs}`",
636                          label="no implementation for `{Self} |= {Rhs}`")]
637 pub trait BitOrAssign<Rhs=Self> {
638     /// Performs the `|=` operation.
639     #[stable(feature = "op_assign_traits", since = "1.8.0")]
640     fn bitor_assign(&mut self, rhs: Rhs);
641 }
642
643 macro_rules! bitor_assign_impl {
644     ($($t:ty)+) => ($(
645         #[stable(feature = "op_assign_traits", since = "1.8.0")]
646         impl BitOrAssign for $t {
647             #[inline]
648             fn bitor_assign(&mut self, other: $t) { *self |= other }
649         }
650
651         forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t }
652     )+)
653 }
654
655 bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
656
657 /// The bitwise XOR assignment operator `^=`.
658 ///
659 /// # Examples
660 ///
661 /// ```
662 /// use std::ops::BitXorAssign;
663 ///
664 /// #[derive(Debug, PartialEq)]
665 /// struct Personality {
666 ///     has_soul: bool,
667 ///     likes_knitting: bool,
668 /// }
669 ///
670 /// impl BitXorAssign for Personality {
671 ///     fn bitxor_assign(&mut self, rhs: Self) {
672 ///         self.has_soul ^= rhs.has_soul;
673 ///         self.likes_knitting ^= rhs.likes_knitting;
674 ///     }
675 /// }
676 ///
677 /// let mut personality = Personality { has_soul: false, likes_knitting: true };
678 /// personality ^= Personality { has_soul: true, likes_knitting: true };
679 /// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false});
680 /// ```
681 #[lang = "bitxor_assign"]
682 #[stable(feature = "op_assign_traits", since = "1.8.0")]
683 #[rustc_on_unimplemented(message="no implementation for `{Self} ^= {Rhs}`",
684                          label="no implementation for `{Self} ^= {Rhs}`")]
685 pub trait BitXorAssign<Rhs=Self> {
686     /// Performs the `^=` operation.
687     #[stable(feature = "op_assign_traits", since = "1.8.0")]
688     fn bitxor_assign(&mut self, rhs: Rhs);
689 }
690
691 macro_rules! bitxor_assign_impl {
692     ($($t:ty)+) => ($(
693         #[stable(feature = "op_assign_traits", since = "1.8.0")]
694         impl BitXorAssign for $t {
695             #[inline]
696             fn bitxor_assign(&mut self, other: $t) { *self ^= other }
697         }
698
699         forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t }
700     )+)
701 }
702
703 bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
704
705 /// The left shift assignment operator `<<=`.
706 ///
707 /// # Examples
708 ///
709 /// An implementation of `ShlAssign` for a wrapper around `usize`.
710 ///
711 /// ```
712 /// use std::ops::ShlAssign;
713 ///
714 /// #[derive(Debug, PartialEq)]
715 /// struct Scalar(usize);
716 ///
717 /// impl ShlAssign<usize> for Scalar {
718 ///     fn shl_assign(&mut self, rhs: usize) {
719 ///         self.0 <<= rhs;
720 ///     }
721 /// }
722 ///
723 /// let mut scalar = Scalar(4);
724 /// scalar <<= 2;
725 /// assert_eq!(scalar, Scalar(16));
726 /// ```
727 #[lang = "shl_assign"]
728 #[stable(feature = "op_assign_traits", since = "1.8.0")]
729 #[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`",
730                          label="no implementation for `{Self} <<= {Rhs}`")]
731 pub trait ShlAssign<Rhs> {
732     /// Performs the `<<=` operation.
733     #[stable(feature = "op_assign_traits", since = "1.8.0")]
734     fn shl_assign(&mut self, rhs: Rhs);
735 }
736
737 macro_rules! shl_assign_impl {
738     ($t:ty, $f:ty) => (
739         #[stable(feature = "op_assign_traits", since = "1.8.0")]
740         impl ShlAssign<$f> for $t {
741             #[inline]
742             #[rustc_inherit_overflow_checks]
743             fn shl_assign(&mut self, other: $f) {
744                 *self <<= other
745             }
746         }
747
748         forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f }
749     )
750 }
751
752 macro_rules! shl_assign_impl_all {
753     ($($t:ty)*) => ($(
754         shl_assign_impl! { $t, u8 }
755         shl_assign_impl! { $t, u16 }
756         shl_assign_impl! { $t, u32 }
757         shl_assign_impl! { $t, u64 }
758         shl_assign_impl! { $t, u128 }
759         shl_assign_impl! { $t, usize }
760
761         shl_assign_impl! { $t, i8 }
762         shl_assign_impl! { $t, i16 }
763         shl_assign_impl! { $t, i32 }
764         shl_assign_impl! { $t, i64 }
765         shl_assign_impl! { $t, i128 }
766         shl_assign_impl! { $t, isize }
767     )*)
768 }
769
770 shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
771
772 /// The right shift assignment operator `>>=`.
773 ///
774 /// # Examples
775 ///
776 /// An implementation of `ShrAssign` for a wrapper around `usize`.
777 ///
778 /// ```
779 /// use std::ops::ShrAssign;
780 ///
781 /// #[derive(Debug, PartialEq)]
782 /// struct Scalar(usize);
783 ///
784 /// impl ShrAssign<usize> for Scalar {
785 ///     fn shr_assign(&mut self, rhs: usize) {
786 ///         self.0 >>= rhs;
787 ///     }
788 /// }
789 ///
790 /// let mut scalar = Scalar(16);
791 /// scalar >>= 2;
792 /// assert_eq!(scalar, Scalar(4));
793 /// ```
794 #[lang = "shr_assign"]
795 #[stable(feature = "op_assign_traits", since = "1.8.0")]
796 #[rustc_on_unimplemented(message="no implementation for `{Self} >>= {Rhs}`",
797                          label="no implementation for `{Self} >>= {Rhs}`")]
798 pub trait ShrAssign<Rhs=Self> {
799     /// Performs the `>>=` operation.
800     #[stable(feature = "op_assign_traits", since = "1.8.0")]
801     fn shr_assign(&mut self, rhs: Rhs);
802 }
803
804 macro_rules! shr_assign_impl {
805     ($t:ty, $f:ty) => (
806         #[stable(feature = "op_assign_traits", since = "1.8.0")]
807         impl ShrAssign<$f> for $t {
808             #[inline]
809             #[rustc_inherit_overflow_checks]
810             fn shr_assign(&mut self, other: $f) {
811                 *self >>= other
812             }
813         }
814
815         forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f }
816     )
817 }
818
819 macro_rules! shr_assign_impl_all {
820     ($($t:ty)*) => ($(
821         shr_assign_impl! { $t, u8 }
822         shr_assign_impl! { $t, u16 }
823         shr_assign_impl! { $t, u32 }
824         shr_assign_impl! { $t, u64 }
825         shr_assign_impl! { $t, u128 }
826         shr_assign_impl! { $t, usize }
827
828         shr_assign_impl! { $t, i8 }
829         shr_assign_impl! { $t, i16 }
830         shr_assign_impl! { $t, i32 }
831         shr_assign_impl! { $t, i64 }
832         shr_assign_impl! { $t, i128 }
833         shr_assign_impl! { $t, isize }
834     )*)
835 }
836
837 shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }