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 = "!")]
35
#[const_trait]
36
pub 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.
42
    ///
43
    /// # Examples
44
    ///
45
    /// ```
46
    /// assert_eq!(!true, false);
47
    /// assert_eq!(!false, true);
48
    /// assert_eq!(!1u8, 254);
49
    /// assert_eq!(!0u8, 255);
50
    /// ```
51
    #[must_use]
52
    #[stable(feature = "rust1", since = "1.0.0")]
53
    fn not(self) -> Self::Output;
54
}
55

            
56
macro_rules! not_impl {
57
    ($($t:ty)*) => ($(
58
        #[stable(feature = "rust1", since = "1.0.0")]
59
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
60
        impl const Not for $t {
61
            type Output = $t;
62

            
63
            #[inline]
64
2043
            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

            
73
not_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")]
77
#[cfg(not(feature = "ferrocene_certified"))]
78
impl const Not for ! {
79
    type Output = !;
80

            
81
    #[inline]
82
    fn not(self) -> ! {
83
        match self {}
84
    }
85
}
86

            
87
/// The bitwise AND operator `&`.
88
///
89
/// Note that `Rhs` is `Self` by default, but this is not mandatory.
90
///
91
/// # Examples
92
///
93
/// An implementation of `BitAnd` for a wrapper around `bool`.
94
///
95
/// ```
96
/// use std::ops::BitAnd;
97
///
98
/// #[derive(Debug, PartialEq)]
99
/// struct Scalar(bool);
100
///
101
/// impl BitAnd for Scalar {
102
///     type Output = Self;
103
///
104
///     // rhs is the "right-hand side" of the expression `a & b`
105
///     fn bitand(self, rhs: Self) -> Self::Output {
106
///         Self(self.0 & rhs.0)
107
///     }
108
/// }
109
///
110
/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true));
111
/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false));
112
/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false));
113
/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false));
114
/// ```
115
///
116
/// An implementation of `BitAnd` for a wrapper around `Vec<bool>`.
117
///
118
/// ```
119
/// use std::ops::BitAnd;
120
///
121
/// #[derive(Debug, PartialEq)]
122
/// struct BooleanVector(Vec<bool>);
123
///
124
/// impl BitAnd for BooleanVector {
125
///     type Output = Self;
126
///
127
///     fn bitand(self, Self(rhs): Self) -> Self::Output {
128
///         let Self(lhs) = self;
129
///         assert_eq!(lhs.len(), rhs.len());
130
///         Self(
131
///             lhs.iter()
132
///                 .zip(rhs.iter())
133
///                 .map(|(x, y)| *x & *y)
134
///                 .collect()
135
///         )
136
///     }
137
/// }
138
///
139
/// let bv1 = BooleanVector(vec![true, true, false, false]);
140
/// let bv2 = BooleanVector(vec![true, false, true, false]);
141
/// let expected = BooleanVector(vec![true, false, false, false]);
142
/// assert_eq!(bv1 & bv2, expected);
143
/// ```
144
#[lang = "bitand"]
145
#[doc(alias = "&")]
146
#[stable(feature = "rust1", since = "1.0.0")]
147
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
148
#[diagnostic::on_unimplemented(
149
    message = "no implementation for `{Self} & {Rhs}`",
150
    label = "no implementation for `{Self} & {Rhs}`"
151
)]
152
#[const_trait]
153
pub trait BitAnd<Rhs = Self> {
154
    /// The resulting type after applying the `&` operator.
155
    #[stable(feature = "rust1", since = "1.0.0")]
156
    type Output;
157

            
158
    /// Performs the `&` operation.
159
    ///
160
    /// # Examples
161
    ///
162
    /// ```
163
    /// assert_eq!(true & false, false);
164
    /// assert_eq!(true & true, true);
165
    /// assert_eq!(5u8 & 1u8, 1);
166
    /// assert_eq!(5u8 & 2u8, 0);
167
    /// ```
168
    #[must_use]
169
    #[stable(feature = "rust1", since = "1.0.0")]
170
    fn bitand(self, rhs: Rhs) -> Self::Output;
171
}
172

            
173
macro_rules! bitand_impl {
174
    ($($t:ty)*) => ($(
175
        #[stable(feature = "rust1", since = "1.0.0")]
176
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
177
        impl const BitAnd for $t {
178
            type Output = $t;
179

            
180
            #[inline]
181
336221
            fn bitand(self, rhs: $t) -> $t { self & rhs }
182
        }
183

            
184
        forward_ref_binop! { impl BitAnd, bitand for $t, $t,
185
        #[stable(feature = "rust1", since = "1.0.0")]
186
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
187
    )*)
188
}
189

            
190
bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
191

            
192
/// The bitwise OR operator `|`.
193
///
194
/// Note that `Rhs` is `Self` by default, but this is not mandatory.
195
///
196
/// # Examples
197
///
198
/// An implementation of `BitOr` for a wrapper around `bool`.
199
///
200
/// ```
201
/// use std::ops::BitOr;
202
///
203
/// #[derive(Debug, PartialEq)]
204
/// struct Scalar(bool);
205
///
206
/// impl BitOr for Scalar {
207
///     type Output = Self;
208
///
209
///     // rhs is the "right-hand side" of the expression `a | b`
210
///     fn bitor(self, rhs: Self) -> Self::Output {
211
///         Self(self.0 | rhs.0)
212
///     }
213
/// }
214
///
215
/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true));
216
/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true));
217
/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true));
218
/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false));
219
/// ```
220
///
221
/// An implementation of `BitOr` for a wrapper around `Vec<bool>`.
222
///
223
/// ```
224
/// use std::ops::BitOr;
225
///
226
/// #[derive(Debug, PartialEq)]
227
/// struct BooleanVector(Vec<bool>);
228
///
229
/// impl BitOr for BooleanVector {
230
///     type Output = Self;
231
///
232
///     fn bitor(self, Self(rhs): Self) -> Self::Output {
233
///         let Self(lhs) = self;
234
///         assert_eq!(lhs.len(), rhs.len());
235
///         Self(
236
///             lhs.iter()
237
///                 .zip(rhs.iter())
238
///                 .map(|(x, y)| *x | *y)
239
///                 .collect()
240
///         )
241
///     }
242
/// }
243
///
244
/// let bv1 = BooleanVector(vec![true, true, false, false]);
245
/// let bv2 = BooleanVector(vec![true, false, true, false]);
246
/// let expected = BooleanVector(vec![true, true, true, false]);
247
/// assert_eq!(bv1 | bv2, expected);
248
/// ```
249
#[lang = "bitor"]
250
#[doc(alias = "|")]
251
#[stable(feature = "rust1", since = "1.0.0")]
252
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
253
#[diagnostic::on_unimplemented(
254
    message = "no implementation for `{Self} | {Rhs}`",
255
    label = "no implementation for `{Self} | {Rhs}`"
256
)]
257
#[const_trait]
258
pub trait BitOr<Rhs = Self> {
259
    /// The resulting type after applying the `|` operator.
260
    #[stable(feature = "rust1", since = "1.0.0")]
261
    type Output;
262

            
263
    /// Performs the `|` operation.
264
    ///
265
    /// # Examples
266
    ///
267
    /// ```
268
    /// assert_eq!(true | false, true);
269
    /// assert_eq!(false | false, false);
270
    /// assert_eq!(5u8 | 1u8, 5);
271
    /// assert_eq!(5u8 | 2u8, 7);
272
    /// ```
273
    #[must_use]
274
    #[stable(feature = "rust1", since = "1.0.0")]
275
    fn bitor(self, rhs: Rhs) -> Self::Output;
276
}
277

            
278
macro_rules! bitor_impl {
279
    ($($t:ty)*) => ($(
280
        #[stable(feature = "rust1", since = "1.0.0")]
281
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
282
        impl const BitOr for $t {
283
            type Output = $t;
284

            
285
            #[inline]
286
156236
            fn bitor(self, rhs: $t) -> $t { self | rhs }
287
        }
288

            
289
        forward_ref_binop! { impl BitOr, bitor for $t, $t,
290
        #[stable(feature = "rust1", since = "1.0.0")]
291
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
292
    )*)
293
}
294

            
295
bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
296

            
297
/// The bitwise XOR operator `^`.
298
///
299
/// Note that `Rhs` is `Self` by default, but this is not mandatory.
300
///
301
/// # Examples
302
///
303
/// An implementation of `BitXor` that lifts `^` to a wrapper around `bool`.
304
///
305
/// ```
306
/// use std::ops::BitXor;
307
///
308
/// #[derive(Debug, PartialEq)]
309
/// struct Scalar(bool);
310
///
311
/// impl BitXor for Scalar {
312
///     type Output = Self;
313
///
314
///     // rhs is the "right-hand side" of the expression `a ^ b`
315
///     fn bitxor(self, rhs: Self) -> Self::Output {
316
///         Self(self.0 ^ rhs.0)
317
///     }
318
/// }
319
///
320
/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false));
321
/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true));
322
/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true));
323
/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false));
324
/// ```
325
///
326
/// An implementation of `BitXor` trait for a wrapper around `Vec<bool>`.
327
///
328
/// ```
329
/// use std::ops::BitXor;
330
///
331
/// #[derive(Debug, PartialEq)]
332
/// struct BooleanVector(Vec<bool>);
333
///
334
/// impl BitXor for BooleanVector {
335
///     type Output = Self;
336
///
337
///     fn bitxor(self, Self(rhs): Self) -> Self::Output {
338
///         let Self(lhs) = self;
339
///         assert_eq!(lhs.len(), rhs.len());
340
///         Self(
341
///             lhs.iter()
342
///                 .zip(rhs.iter())
343
///                 .map(|(x, y)| *x ^ *y)
344
///                 .collect()
345
///         )
346
///     }
347
/// }
348
///
349
/// let bv1 = BooleanVector(vec![true, true, false, false]);
350
/// let bv2 = BooleanVector(vec![true, false, true, false]);
351
/// let expected = BooleanVector(vec![false, true, true, false]);
352
/// assert_eq!(bv1 ^ bv2, expected);
353
/// ```
354
#[lang = "bitxor"]
355
#[doc(alias = "^")]
356
#[stable(feature = "rust1", since = "1.0.0")]
357
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
358
#[diagnostic::on_unimplemented(
359
    message = "no implementation for `{Self} ^ {Rhs}`",
360
    label = "no implementation for `{Self} ^ {Rhs}`"
361
)]
362
#[const_trait]
363
pub trait BitXor<Rhs = Self> {
364
    /// The resulting type after applying the `^` operator.
365
    #[stable(feature = "rust1", since = "1.0.0")]
366
    type Output;
367

            
368
    /// Performs the `^` operation.
369
    ///
370
    /// # Examples
371
    ///
372
    /// ```
373
    /// assert_eq!(true ^ false, true);
374
    /// assert_eq!(true ^ true, false);
375
    /// assert_eq!(5u8 ^ 1u8, 4);
376
    /// assert_eq!(5u8 ^ 2u8, 7);
377
    /// ```
378
    #[must_use]
379
    #[stable(feature = "rust1", since = "1.0.0")]
380
    fn bitxor(self, rhs: Rhs) -> Self::Output;
381
}
382

            
383
macro_rules! bitxor_impl {
384
    ($($t:ty)*) => ($(
385
        #[stable(feature = "rust1", since = "1.0.0")]
386
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
387
        impl const BitXor for $t {
388
            type Output = $t;
389

            
390
            #[inline]
391
1356
            fn bitxor(self, other: $t) -> $t { self ^ other }
392
        }
393

            
394
        forward_ref_binop! { impl BitXor, bitxor for $t, $t,
395
        #[stable(feature = "rust1", since = "1.0.0")]
396
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
397
    )*)
398
}
399

            
400
bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
401

            
402
/// The left shift operator `<<`. Note that because this trait is implemented
403
/// for all integer types with multiple right-hand-side types, Rust's type
404
/// checker has special handling for `_ << _`, setting the result type for
405
/// integer operations to the type of the left-hand-side operand. This means
406
/// that though `a << b` and `a.shl(b)` are one and the same from an evaluation
407
/// standpoint, they are different when it comes to type inference.
408
///
409
/// # Examples
410
///
411
/// An implementation of `Shl` that lifts the `<<` operation on integers to a
412
/// wrapper around `usize`.
413
///
414
/// ```
415
/// use std::ops::Shl;
416
///
417
/// #[derive(PartialEq, Debug)]
418
/// struct Scalar(usize);
419
///
420
/// impl Shl<Scalar> for Scalar {
421
///     type Output = Self;
422
///
423
///     fn shl(self, Self(rhs): Self) -> Self::Output {
424
///         let Self(lhs) = self;
425
///         Self(lhs << rhs)
426
///     }
427
/// }
428
///
429
/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16));
430
/// ```
431
///
432
/// An implementation of `Shl` that spins a vector leftward by a given amount.
433
///
434
/// ```
435
/// use std::ops::Shl;
436
///
437
/// #[derive(PartialEq, Debug)]
438
/// struct SpinVector<T: Clone> {
439
///     vec: Vec<T>,
440
/// }
441
///
442
/// impl<T: Clone> Shl<usize> for SpinVector<T> {
443
///     type Output = Self;
444
///
445
///     fn shl(self, rhs: usize) -> Self::Output {
446
///         // Rotate the vector by `rhs` places.
447
///         let (a, b) = self.vec.split_at(rhs);
448
///         let mut spun_vector = vec![];
449
///         spun_vector.extend_from_slice(b);
450
///         spun_vector.extend_from_slice(a);
451
///         Self { vec: spun_vector }
452
///     }
453
/// }
454
///
455
/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2,
456
///            SpinVector { vec: vec![2, 3, 4, 0, 1] });
457
/// ```
458
#[lang = "shl"]
459
#[doc(alias = "<<")]
460
#[stable(feature = "rust1", since = "1.0.0")]
461
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
462
#[diagnostic::on_unimplemented(
463
    message = "no implementation for `{Self} << {Rhs}`",
464
    label = "no implementation for `{Self} << {Rhs}`"
465
)]
466
#[const_trait]
467
pub trait Shl<Rhs = Self> {
468
    /// The resulting type after applying the `<<` operator.
469
    #[stable(feature = "rust1", since = "1.0.0")]
470
    type Output;
471

            
472
    /// Performs the `<<` operation.
473
    ///
474
    /// # Examples
475
    ///
476
    /// ```
477
    /// assert_eq!(5u8 << 1, 10);
478
    /// assert_eq!(1u8 << 1, 2);
479
    /// ```
480
    #[must_use]
481
    #[stable(feature = "rust1", since = "1.0.0")]
482
    fn shl(self, rhs: Rhs) -> Self::Output;
483
}
484

            
485
macro_rules! shl_impl {
486
    ($t:ty, $f:ty) => {
487
        #[stable(feature = "rust1", since = "1.0.0")]
488
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
489
        impl const Shl<$f> for $t {
490
            type Output = $t;
491

            
492
            #[inline]
493
            #[rustc_inherit_overflow_checks]
494
251782
            fn shl(self, other: $f) -> $t {
495
251782
                self << other
496
251782
            }
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

            
505
macro_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

            
523
shl_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
)]
589
#[const_trait]
590
pub trait Shr<Rhs = Self> {
591
    /// The resulting type after applying the `>>` operator.
592
    #[stable(feature = "rust1", since = "1.0.0")]
593
    type Output;
594

            
595
    /// Performs the `>>` operation.
596
    ///
597
    /// # Examples
598
    ///
599
    /// ```
600
    /// assert_eq!(5u8 >> 1, 2);
601
    /// assert_eq!(2u8 >> 1, 1);
602
    /// ```
603
    #[must_use]
604
    #[stable(feature = "rust1", since = "1.0.0")]
605
    fn shr(self, rhs: Rhs) -> Self::Output;
606
}
607

            
608
macro_rules! shr_impl {
609
    ($t:ty, $f:ty) => {
610
        #[stable(feature = "rust1", since = "1.0.0")]
611
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
612
        impl const Shr<$f> for $t {
613
            type Output = $t;
614

            
615
            #[inline]
616
            #[rustc_inherit_overflow_checks]
617
232825
            fn shr(self, other: $f) -> $t {
618
232825
                self >> other
619
232825
            }
620
        }
621

            
622
        forward_ref_binop! { impl Shr, shr for $t, $f,
623
        #[stable(feature = "rust1", since = "1.0.0")]
624
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
625
    };
626
}
627

            
628
macro_rules! shr_impl_all {
629
    ($($t:ty)*) => ($(
630
        shr_impl! { $t, u8 }
631
        shr_impl! { $t, u16 }
632
        shr_impl! { $t, u32 }
633
        shr_impl! { $t, u64 }
634
        shr_impl! { $t, u128 }
635
        shr_impl! { $t, usize }
636

            
637
        shr_impl! { $t, i8 }
638
        shr_impl! { $t, i16 }
639
        shr_impl! { $t, i32 }
640
        shr_impl! { $t, i64 }
641
        shr_impl! { $t, i128 }
642
        shr_impl! { $t, isize }
643
    )*)
644
}
645

            
646
shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
647

            
648
/// The bitwise AND assignment operator `&=`.
649
///
650
/// # Examples
651
///
652
/// An implementation of `BitAndAssign` that lifts the `&=` operator to a
653
/// wrapper around `bool`.
654
///
655
/// ```
656
/// use std::ops::BitAndAssign;
657
///
658
/// #[derive(Debug, PartialEq)]
659
/// struct Scalar(bool);
660
///
661
/// impl BitAndAssign for Scalar {
662
///     // rhs is the "right-hand side" of the expression `a &= b`
663
///     fn bitand_assign(&mut self, rhs: Self) {
664
///         *self = Self(self.0 & rhs.0)
665
///     }
666
/// }
667
///
668
/// let mut scalar = Scalar(true);
669
/// scalar &= Scalar(true);
670
/// assert_eq!(scalar, Scalar(true));
671
///
672
/// let mut scalar = Scalar(true);
673
/// scalar &= Scalar(false);
674
/// assert_eq!(scalar, Scalar(false));
675
///
676
/// let mut scalar = Scalar(false);
677
/// scalar &= Scalar(true);
678
/// assert_eq!(scalar, Scalar(false));
679
///
680
/// let mut scalar = Scalar(false);
681
/// scalar &= Scalar(false);
682
/// assert_eq!(scalar, Scalar(false));
683
/// ```
684
///
685
/// Here, the `BitAndAssign` trait is implemented for a wrapper around
686
/// `Vec<bool>`.
687
///
688
/// ```
689
/// use std::ops::BitAndAssign;
690
///
691
/// #[derive(Debug, PartialEq)]
692
/// struct BooleanVector(Vec<bool>);
693
///
694
/// impl BitAndAssign for BooleanVector {
695
///     // `rhs` is the "right-hand side" of the expression `a &= b`.
696
///     fn bitand_assign(&mut self, rhs: Self) {
697
///         assert_eq!(self.0.len(), rhs.0.len());
698
///         *self = Self(
699
///             self.0
700
///                 .iter()
701
///                 .zip(rhs.0.iter())
702
///                 .map(|(x, y)| *x & *y)
703
///                 .collect()
704
///         );
705
///     }
706
/// }
707
///
708
/// let mut bv = BooleanVector(vec![true, true, false, false]);
709
/// bv &= BooleanVector(vec![true, false, true, false]);
710
/// let expected = BooleanVector(vec![true, false, false, false]);
711
/// assert_eq!(bv, expected);
712
/// ```
713
#[lang = "bitand_assign"]
714
#[doc(alias = "&=")]
715
#[stable(feature = "op_assign_traits", since = "1.8.0")]
716
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
717
#[diagnostic::on_unimplemented(
718
    message = "no implementation for `{Self} &= {Rhs}`",
719
    label = "no implementation for `{Self} &= {Rhs}`"
720
)]
721
#[const_trait]
722
pub 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

            
748
macro_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
2047
            fn bitand_assign(&mut self, other: $t) { *self &= other }
755
        }
756

            
757
        forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t,
758
        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
759
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
760
    )+)
761
}
762

            
763
bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
764

            
765
/// The bitwise OR assignment operator `|=`.
766
///
767
/// # Examples
768
///
769
/// ```
770
/// use std::ops::BitOrAssign;
771
///
772
/// #[derive(Debug, PartialEq)]
773
/// struct PersonalPreferences {
774
///     likes_cats: bool,
775
///     likes_dogs: bool,
776
/// }
777
///
778
/// impl BitOrAssign for PersonalPreferences {
779
///     fn bitor_assign(&mut self, rhs: Self) {
780
///         self.likes_cats |= rhs.likes_cats;
781
///         self.likes_dogs |= rhs.likes_dogs;
782
///     }
783
/// }
784
///
785
/// let mut prefs = PersonalPreferences { likes_cats: true, likes_dogs: false };
786
/// prefs |= PersonalPreferences { likes_cats: false, likes_dogs: true };
787
/// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true });
788
/// ```
789
#[lang = "bitor_assign"]
790
#[doc(alias = "|=")]
791
#[stable(feature = "op_assign_traits", since = "1.8.0")]
792
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
793
#[diagnostic::on_unimplemented(
794
    message = "no implementation for `{Self} |= {Rhs}`",
795
    label = "no implementation for `{Self} |= {Rhs}`"
796
)]
797
#[const_trait]
798
pub 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

            
824
macro_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
146
            fn bitor_assign(&mut self, other: $t) { *self |= other }
831
        }
832

            
833
        forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t,
834
        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
835
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
836
    )+)
837
}
838

            
839
bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
840

            
841
/// The bitwise XOR assignment operator `^=`.
842
///
843
/// # Examples
844
///
845
/// ```
846
/// use std::ops::BitXorAssign;
847
///
848
/// #[derive(Debug, PartialEq)]
849
/// struct Personality {
850
///     has_soul: bool,
851
///     likes_knitting: bool,
852
/// }
853
///
854
/// impl BitXorAssign for Personality {
855
///     fn bitxor_assign(&mut self, rhs: Self) {
856
///         self.has_soul ^= rhs.has_soul;
857
///         self.likes_knitting ^= rhs.likes_knitting;
858
///     }
859
/// }
860
///
861
/// let mut personality = Personality { has_soul: false, likes_knitting: true };
862
/// personality ^= Personality { has_soul: true, likes_knitting: true };
863
/// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false});
864
/// ```
865
#[lang = "bitxor_assign"]
866
#[doc(alias = "^=")]
867
#[stable(feature = "op_assign_traits", since = "1.8.0")]
868
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
869
#[diagnostic::on_unimplemented(
870
    message = "no implementation for `{Self} ^= {Rhs}`",
871
    label = "no implementation for `{Self} ^= {Rhs}`"
872
)]
873
#[const_trait]
874
pub 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

            
900
macro_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
            fn bitxor_assign(&mut self, other: $t) { *self ^= other }
907
        }
908

            
909
        forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t,
910
        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
911
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
912
    )+)
913
}
914

            
915
bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
916

            
917
/// The left shift assignment operator `<<=`.
918
///
919
/// # Examples
920
///
921
/// An implementation of `ShlAssign` for a wrapper around `usize`.
922
///
923
/// ```
924
/// use std::ops::ShlAssign;
925
///
926
/// #[derive(Debug, PartialEq)]
927
/// struct Scalar(usize);
928
///
929
/// impl ShlAssign<usize> for Scalar {
930
///     fn shl_assign(&mut self, rhs: usize) {
931
///         self.0 <<= rhs;
932
///     }
933
/// }
934
///
935
/// let mut scalar = Scalar(4);
936
/// scalar <<= 2;
937
/// assert_eq!(scalar, Scalar(16));
938
/// ```
939
#[lang = "shl_assign"]
940
#[doc(alias = "<<=")]
941
#[stable(feature = "op_assign_traits", since = "1.8.0")]
942
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
943
#[diagnostic::on_unimplemented(
944
    message = "no implementation for `{Self} <<= {Rhs}`",
945
    label = "no implementation for `{Self} <<= {Rhs}`"
946
)]
947
#[const_trait]
948
pub 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

            
966
macro_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
            #[rustc_inherit_overflow_checks]
973
8
            fn shl_assign(&mut self, other: $f) {
974
8
                *self <<= other
975
8
            }
976
        }
977

            
978
        forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f,
979
        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
980
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
981
    };
982
}
983

            
984
macro_rules! shl_assign_impl_all {
985
    ($($t:ty)*) => ($(
986
        shl_assign_impl! { $t, u8 }
987
        shl_assign_impl! { $t, u16 }
988
        shl_assign_impl! { $t, u32 }
989
        shl_assign_impl! { $t, u64 }
990
        shl_assign_impl! { $t, u128 }
991
        shl_assign_impl! { $t, usize }
992

            
993
        shl_assign_impl! { $t, i8 }
994
        shl_assign_impl! { $t, i16 }
995
        shl_assign_impl! { $t, i32 }
996
        shl_assign_impl! { $t, i64 }
997
        shl_assign_impl! { $t, i128 }
998
        shl_assign_impl! { $t, isize }
999
    )*)
}
shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
/// The right shift assignment operator `>>=`.
///
/// # Examples
///
/// An implementation of `ShrAssign` for a wrapper around `usize`.
///
/// ```
/// use std::ops::ShrAssign;
///
/// #[derive(Debug, PartialEq)]
/// struct Scalar(usize);
///
/// impl ShrAssign<usize> for Scalar {
///     fn shr_assign(&mut self, rhs: usize) {
///         self.0 >>= rhs;
///     }
/// }
///
/// let mut scalar = Scalar(16);
/// scalar >>= 2;
/// assert_eq!(scalar, Scalar(4));
/// ```
#[lang = "shr_assign"]
#[doc(alias = ">>=")]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
#[diagnostic::on_unimplemented(
    message = "no implementation for `{Self} >>= {Rhs}`",
    label = "no implementation for `{Self} >>= {Rhs}`"
)]
#[const_trait]
pub trait ShrAssign<Rhs = Self> {
    /// Performs the `>>=` operation.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut x: u8 = 5;
    /// x >>= 1;
    /// assert_eq!(x, 2);
    ///
    /// let mut x: u8 = 2;
    /// x >>= 1;
    /// assert_eq!(x, 1);
    /// ```
    #[stable(feature = "op_assign_traits", since = "1.8.0")]
    fn shr_assign(&mut self, rhs: Rhs);
}
macro_rules! shr_assign_impl {
    ($t:ty, $f:ty) => {
        #[stable(feature = "op_assign_traits", since = "1.8.0")]
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")]
        impl const ShrAssign<$f> for $t {
            #[inline]
            #[rustc_inherit_overflow_checks]
8
            fn shr_assign(&mut self, other: $f) {
8
                *self >>= other
8
            }
        }
        forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f,
        #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]
        #[rustc_const_unstable(feature = "const_ops", issue = "143802")] }
    };
}
macro_rules! shr_assign_impl_all {
    ($($t:ty)*) => ($(
        shr_assign_impl! { $t, u8 }
        shr_assign_impl! { $t, u16 }
        shr_assign_impl! { $t, u32 }
        shr_assign_impl! { $t, u64 }
        shr_assign_impl! { $t, u128 }
        shr_assign_impl! { $t, usize }
        shr_assign_impl! { $t, i8 }
        shr_assign_impl! { $t, i16 }
        shr_assign_impl! { $t, i32 }
        shr_assign_impl! { $t, i64 }
        shr_assign_impl! { $t, i128 }
        shr_assign_impl! { $t, isize }
    )*)
}
shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }