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