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 }