about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorClar Charr <clar@charr.xyz>2017-06-07 22:08:14 -0400
committerClar Charr <clar@charr.xyz>2017-06-09 19:07:26 -0400
commitd460aca7204b8252f20b970937838bf70b466efe (patch)
treef906f523b87a633b2c230f1af96ee257bfb6003b /src/libcore
parent75677e0646a3e110c22b56145b5c586c1f87a741 (diff)
downloadrust-d460aca7204b8252f20b970937838bf70b466efe.tar.gz
rust-d460aca7204b8252f20b970937838bf70b466efe.zip
Move bit ops to module.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/ops/bit.rs839
-rw-r--r--src/libcore/ops/mod.rs837
2 files changed, 846 insertions, 830 deletions
diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs
new file mode 100644
index 00000000000..8743be3557c
--- /dev/null
+++ b/src/libcore/ops/bit.rs
@@ -0,0 +1,839 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// The unary logical negation operator `!`.
+///
+/// # Examples
+///
+/// An implementation of `Not` for `Answer`, which enables the use of `!` to
+/// invert its value.
+///
+/// ```
+/// use std::ops::Not;
+///
+/// #[derive(Debug, PartialEq)]
+/// enum Answer {
+///     Yes,
+///     No,
+/// }
+///
+/// impl Not for Answer {
+///     type Output = Answer;
+///
+///     fn not(self) -> Answer {
+///         match self {
+///             Answer::Yes => Answer::No,
+///             Answer::No => Answer::Yes
+///         }
+///     }
+/// }
+///
+/// assert_eq!(!Answer::Yes, Answer::No);
+/// assert_eq!(!Answer::No, Answer::Yes);
+/// ```
+#[lang = "not"]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait Not {
+    /// The resulting type after applying the `!` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    type Output;
+
+    /// The method for the unary `!` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn not(self) -> Self::Output;
+}
+
+macro_rules! not_impl {
+    ($($t:ty)*) => ($(
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl Not for $t {
+            type Output = $t;
+
+            #[inline]
+            fn not(self) -> $t { !self }
+        }
+
+        forward_ref_unop! { impl Not, not for $t }
+    )*)
+}
+
+not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+
+/// The bitwise AND operator `&`.
+///
+/// # Examples
+///
+/// In this example, the `&` operator is lifted to a trivial `Scalar` type.
+///
+/// ```
+/// use std::ops::BitAnd;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct Scalar(bool);
+///
+/// impl BitAnd for Scalar {
+///     type Output = Self;
+///
+///     // rhs is the "right-hand side" of the expression `a & b`
+///     fn bitand(self, rhs: Self) -> Self {
+///         Scalar(self.0 & rhs.0)
+///     }
+/// }
+///
+/// fn main() {
+///     assert_eq!(Scalar(true) & Scalar(true), Scalar(true));
+///     assert_eq!(Scalar(true) & Scalar(false), Scalar(false));
+///     assert_eq!(Scalar(false) & Scalar(true), Scalar(false));
+///     assert_eq!(Scalar(false) & Scalar(false), Scalar(false));
+/// }
+/// ```
+///
+/// In this example, the `BitAnd` trait is implemented for a `BooleanVector`
+/// struct.
+///
+/// ```
+/// use std::ops::BitAnd;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct BooleanVector(Vec<bool>);
+///
+/// impl BitAnd for BooleanVector {
+///     type Output = Self;
+///
+///     fn bitand(self, BooleanVector(rhs): Self) -> Self {
+///         let BooleanVector(lhs) = self;
+///         assert_eq!(lhs.len(), rhs.len());
+///         BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect())
+///     }
+/// }
+///
+/// fn main() {
+///     let bv1 = BooleanVector(vec![true, true, false, false]);
+///     let bv2 = BooleanVector(vec![true, false, true, false]);
+///     let expected = BooleanVector(vec![true, false, false, false]);
+///     assert_eq!(bv1 & bv2, expected);
+/// }
+/// ```
+#[lang = "bitand"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"]
+pub trait BitAnd<RHS=Self> {
+    /// The resulting type after applying the `&` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    type Output;
+
+    /// The method for the `&` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn bitand(self, rhs: RHS) -> Self::Output;
+}
+
+macro_rules! bitand_impl {
+    ($($t:ty)*) => ($(
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl BitAnd for $t {
+            type Output = $t;
+
+            #[inline]
+            fn bitand(self, rhs: $t) -> $t { self & rhs }
+        }
+
+        forward_ref_binop! { impl BitAnd, bitand for $t, $t }
+    )*)
+}
+
+bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+
+/// The bitwise OR operator `|`.
+///
+/// # Examples
+///
+/// In this example, the `|` operator is lifted to a trivial `Scalar` type.
+///
+/// ```
+/// use std::ops::BitOr;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct Scalar(bool);
+///
+/// impl BitOr for Scalar {
+///     type Output = Self;
+///
+///     // rhs is the "right-hand side" of the expression `a | b`
+///     fn bitor(self, rhs: Self) -> Self {
+///         Scalar(self.0 | rhs.0)
+///     }
+/// }
+///
+/// fn main() {
+///     assert_eq!(Scalar(true) | Scalar(true), Scalar(true));
+///     assert_eq!(Scalar(true) | Scalar(false), Scalar(true));
+///     assert_eq!(Scalar(false) | Scalar(true), Scalar(true));
+///     assert_eq!(Scalar(false) | Scalar(false), Scalar(false));
+/// }
+/// ```
+///
+/// In this example, the `BitOr` trait is implemented for a `BooleanVector`
+/// struct.
+///
+/// ```
+/// use std::ops::BitOr;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct BooleanVector(Vec<bool>);
+///
+/// impl BitOr for BooleanVector {
+///     type Output = Self;
+///
+///     fn bitor(self, BooleanVector(rhs): Self) -> Self {
+///         let BooleanVector(lhs) = self;
+///         assert_eq!(lhs.len(), rhs.len());
+///         BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect())
+///     }
+/// }
+///
+/// fn main() {
+///     let bv1 = BooleanVector(vec![true, true, false, false]);
+///     let bv2 = BooleanVector(vec![true, false, true, false]);
+///     let expected = BooleanVector(vec![true, true, true, false]);
+///     assert_eq!(bv1 | bv2, expected);
+/// }
+/// ```
+#[lang = "bitor"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"]
+pub trait BitOr<RHS=Self> {
+    /// The resulting type after applying the `|` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    type Output;
+
+    /// The method for the `|` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn bitor(self, rhs: RHS) -> Self::Output;
+}
+
+macro_rules! bitor_impl {
+    ($($t:ty)*) => ($(
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl BitOr for $t {
+            type Output = $t;
+
+            #[inline]
+            fn bitor(self, rhs: $t) -> $t { self | rhs }
+        }
+
+        forward_ref_binop! { impl BitOr, bitor for $t, $t }
+    )*)
+}
+
+bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+
+/// The bitwise XOR operator `^`.
+///
+/// # Examples
+///
+/// In this example, the `^` operator is lifted to a trivial `Scalar` type.
+///
+/// ```
+/// use std::ops::BitXor;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct Scalar(bool);
+///
+/// impl BitXor for Scalar {
+///     type Output = Self;
+///
+///     // rhs is the "right-hand side" of the expression `a ^ b`
+///     fn bitxor(self, rhs: Self) -> Self {
+///         Scalar(self.0 ^ rhs.0)
+///     }
+/// }
+///
+/// fn main() {
+///     assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false));
+///     assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true));
+///     assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true));
+///     assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false));
+/// }
+/// ```
+///
+/// In this example, the `BitXor` trait is implemented for a `BooleanVector`
+/// struct.
+///
+/// ```
+/// use std::ops::BitXor;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct BooleanVector(Vec<bool>);
+///
+/// impl BitXor for BooleanVector {
+///     type Output = Self;
+///
+///     fn bitxor(self, BooleanVector(rhs): Self) -> Self {
+///         let BooleanVector(lhs) = self;
+///         assert_eq!(lhs.len(), rhs.len());
+///         BooleanVector(lhs.iter()
+///                          .zip(rhs.iter())
+///                          .map(|(x, y)| (*x || *y) && !(*x && *y))
+///                          .collect())
+///     }
+/// }
+///
+/// fn main() {
+///     let bv1 = BooleanVector(vec![true, true, false, false]);
+///     let bv2 = BooleanVector(vec![true, false, true, false]);
+///     let expected = BooleanVector(vec![false, true, true, false]);
+///     assert_eq!(bv1 ^ bv2, expected);
+/// }
+/// ```
+#[lang = "bitxor"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"]
+pub trait BitXor<RHS=Self> {
+    /// The resulting type after applying the `^` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    type Output;
+
+    /// The method for the `^` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn bitxor(self, rhs: RHS) -> Self::Output;
+}
+
+macro_rules! bitxor_impl {
+    ($($t:ty)*) => ($(
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl BitXor for $t {
+            type Output = $t;
+
+            #[inline]
+            fn bitxor(self, other: $t) -> $t { self ^ other }
+        }
+
+        forward_ref_binop! { impl BitXor, bitxor for $t, $t }
+    )*)
+}
+
+bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+
+/// The left shift operator `<<`.
+///
+/// # Examples
+///
+/// An implementation of `Shl` that lifts the `<<` operation on integers to a
+/// `Scalar` struct.
+///
+/// ```
+/// use std::ops::Shl;
+///
+/// #[derive(PartialEq, Debug)]
+/// struct Scalar(usize);
+///
+/// impl Shl<Scalar> for Scalar {
+///     type Output = Self;
+///
+///     fn shl(self, Scalar(rhs): Self) -> Scalar {
+///         let Scalar(lhs) = self;
+///         Scalar(lhs << rhs)
+///     }
+/// }
+/// fn main() {
+///     assert_eq!(Scalar(4) << Scalar(2), Scalar(16));
+/// }
+/// ```
+///
+/// An implementation of `Shl` that spins a vector leftward by a given amount.
+///
+/// ```
+/// use std::ops::Shl;
+///
+/// #[derive(PartialEq, Debug)]
+/// struct SpinVector<T: Clone> {
+///     vec: Vec<T>,
+/// }
+///
+/// impl<T: Clone> Shl<usize> for SpinVector<T> {
+///     type Output = Self;
+///
+///     fn shl(self, rhs: usize) -> SpinVector<T> {
+///         // rotate the vector by `rhs` places
+///         let (a, b) = self.vec.split_at(rhs);
+///         let mut spun_vector: Vec<T> = vec![];
+///         spun_vector.extend_from_slice(b);
+///         spun_vector.extend_from_slice(a);
+///         SpinVector { vec: spun_vector }
+///     }
+/// }
+///
+/// fn main() {
+///     assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2,
+///                SpinVector { vec: vec![2, 3, 4, 0, 1] });
+/// }
+/// ```
+#[lang = "shl"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"]
+pub trait Shl<RHS> {
+    /// The resulting type after applying the `<<` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    type Output;
+
+    /// The method for the `<<` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn shl(self, rhs: RHS) -> Self::Output;
+}
+
+macro_rules! shl_impl {
+    ($t:ty, $f:ty) => (
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl Shl<$f> for $t {
+            type Output = $t;
+
+            #[inline]
+            #[rustc_inherit_overflow_checks]
+            fn shl(self, other: $f) -> $t {
+                self << other
+            }
+        }
+
+        forward_ref_binop! { impl Shl, shl for $t, $f }
+    )
+}
+
+macro_rules! shl_impl_all {
+    ($($t:ty)*) => ($(
+        shl_impl! { $t, u8 }
+        shl_impl! { $t, u16 }
+        shl_impl! { $t, u32 }
+        shl_impl! { $t, u64 }
+        shl_impl! { $t, u128 }
+        shl_impl! { $t, usize }
+
+        shl_impl! { $t, i8 }
+        shl_impl! { $t, i16 }
+        shl_impl! { $t, i32 }
+        shl_impl! { $t, i64 }
+        shl_impl! { $t, i128 }
+        shl_impl! { $t, isize }
+    )*)
+}
+
+shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
+
+/// The right shift operator `>>`.
+///
+/// # Examples
+///
+/// An implementation of `Shr` that lifts the `>>` operation on integers to a
+/// `Scalar` struct.
+///
+/// ```
+/// use std::ops::Shr;
+///
+/// #[derive(PartialEq, Debug)]
+/// struct Scalar(usize);
+///
+/// impl Shr<Scalar> for Scalar {
+///     type Output = Self;
+///
+///     fn shr(self, Scalar(rhs): Self) -> Scalar {
+///         let Scalar(lhs) = self;
+///         Scalar(lhs >> rhs)
+///     }
+/// }
+/// fn main() {
+///     assert_eq!(Scalar(16) >> Scalar(2), Scalar(4));
+/// }
+/// ```
+///
+/// An implementation of `Shr` that spins a vector rightward by a given amount.
+///
+/// ```
+/// use std::ops::Shr;
+///
+/// #[derive(PartialEq, Debug)]
+/// struct SpinVector<T: Clone> {
+///     vec: Vec<T>,
+/// }
+///
+/// impl<T: Clone> Shr<usize> for SpinVector<T> {
+///     type Output = Self;
+///
+///     fn shr(self, rhs: usize) -> SpinVector<T> {
+///         // rotate the vector by `rhs` places
+///         let (a, b) = self.vec.split_at(self.vec.len() - rhs);
+///         let mut spun_vector: Vec<T> = vec![];
+///         spun_vector.extend_from_slice(b);
+///         spun_vector.extend_from_slice(a);
+///         SpinVector { vec: spun_vector }
+///     }
+/// }
+///
+/// fn main() {
+///     assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2,
+///                SpinVector { vec: vec![3, 4, 0, 1, 2] });
+/// }
+/// ```
+#[lang = "shr"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"]
+pub trait Shr<RHS> {
+    /// The resulting type after applying the `>>` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    type Output;
+
+    /// The method for the `>>` operator
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn shr(self, rhs: RHS) -> Self::Output;
+}
+
+macro_rules! shr_impl {
+    ($t:ty, $f:ty) => (
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl Shr<$f> for $t {
+            type Output = $t;
+
+            #[inline]
+            #[rustc_inherit_overflow_checks]
+            fn shr(self, other: $f) -> $t {
+                self >> other
+            }
+        }
+
+        forward_ref_binop! { impl Shr, shr for $t, $f }
+    )
+}
+
+macro_rules! shr_impl_all {
+    ($($t:ty)*) => ($(
+        shr_impl! { $t, u8 }
+        shr_impl! { $t, u16 }
+        shr_impl! { $t, u32 }
+        shr_impl! { $t, u64 }
+        shr_impl! { $t, u128 }
+        shr_impl! { $t, usize }
+
+        shr_impl! { $t, i8 }
+        shr_impl! { $t, i16 }
+        shr_impl! { $t, i32 }
+        shr_impl! { $t, i64 }
+        shr_impl! { $t, i128 }
+        shr_impl! { $t, isize }
+    )*)
+}
+
+shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
+
+/// The bitwise AND assignment operator `&=`.
+///
+/// # Examples
+///
+/// In this example, the `&=` operator is lifted to a trivial `Scalar` type.
+///
+/// ```
+/// use std::ops::BitAndAssign;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct Scalar(bool);
+///
+/// impl BitAndAssign for Scalar {
+///     // rhs is the "right-hand side" of the expression `a &= b`
+///     fn bitand_assign(&mut self, rhs: Self) {
+///         *self = Scalar(self.0 & rhs.0)
+///     }
+/// }
+///
+/// fn main() {
+///     let mut scalar = Scalar(true);
+///     scalar &= Scalar(true);
+///     assert_eq!(scalar, Scalar(true));
+///
+///     let mut scalar = Scalar(true);
+///     scalar &= Scalar(false);
+///     assert_eq!(scalar, Scalar(false));
+///
+///     let mut scalar = Scalar(false);
+///     scalar &= Scalar(true);
+///     assert_eq!(scalar, Scalar(false));
+///
+///     let mut scalar = Scalar(false);
+///     scalar &= Scalar(false);
+///     assert_eq!(scalar, Scalar(false));
+/// }
+/// ```
+///
+/// In this example, the `BitAndAssign` trait is implemented for a
+/// `BooleanVector` struct.
+///
+/// ```
+/// use std::ops::BitAndAssign;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct BooleanVector(Vec<bool>);
+///
+/// impl BitAndAssign for BooleanVector {
+///     // rhs is the "right-hand side" of the expression `a &= b`
+///     fn bitand_assign(&mut self, rhs: Self) {
+///         assert_eq!(self.0.len(), rhs.0.len());
+///         *self = BooleanVector(self.0
+///                                   .iter()
+///                                   .zip(rhs.0.iter())
+///                                   .map(|(x, y)| *x && *y)
+///                                   .collect());
+///     }
+/// }
+///
+/// fn main() {
+///     let mut bv = BooleanVector(vec![true, true, false, false]);
+///     bv &= BooleanVector(vec![true, false, true, false]);
+///     let expected = BooleanVector(vec![true, false, false, false]);
+///     assert_eq!(bv, expected);
+/// }
+/// ```
+#[lang = "bitand_assign"]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"]
+pub trait BitAndAssign<Rhs=Self> {
+    /// The method for the `&=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
+    fn bitand_assign(&mut self, rhs: Rhs);
+}
+
+macro_rules! bitand_assign_impl {
+    ($($t:ty)+) => ($(
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
+        impl BitAndAssign for $t {
+            #[inline]
+            fn bitand_assign(&mut self, other: $t) { *self &= other }
+        }
+    )+)
+}
+
+bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+
+/// The bitwise OR assignment operator `|=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up
+/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`.
+///
+/// ```
+/// use std::ops::BitOrAssign;
+///
+/// struct Foo;
+///
+/// impl BitOrAssign for Foo {
+///     fn bitor_assign(&mut self, _rhs: Foo) {
+///         println!("Bitwise Or-ing!");
+///     }
+/// }
+///
+/// # #[allow(unused_assignments)]
+/// fn main() {
+///     let mut foo = Foo;
+///     foo |= Foo;
+/// }
+/// ```
+#[lang = "bitor_assign"]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"]
+pub trait BitOrAssign<Rhs=Self> {
+    /// The method for the `|=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
+    fn bitor_assign(&mut self, rhs: Rhs);
+}
+
+macro_rules! bitor_assign_impl {
+    ($($t:ty)+) => ($(
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
+        impl BitOrAssign for $t {
+            #[inline]
+            fn bitor_assign(&mut self, other: $t) { *self |= other }
+        }
+    )+)
+}
+
+bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+
+/// The bitwise XOR assignment operator `^=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up
+/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`.
+///
+/// ```
+/// use std::ops::BitXorAssign;
+///
+/// struct Foo;
+///
+/// impl BitXorAssign for Foo {
+///     fn bitxor_assign(&mut self, _rhs: Foo) {
+///         println!("Bitwise Xor-ing!");
+///     }
+/// }
+///
+/// # #[allow(unused_assignments)]
+/// fn main() {
+///     let mut foo = Foo;
+///     foo ^= Foo;
+/// }
+/// ```
+#[lang = "bitxor_assign"]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"]
+pub trait BitXorAssign<Rhs=Self> {
+    /// The method for the `^=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
+    fn bitxor_assign(&mut self, rhs: Rhs);
+}
+
+macro_rules! bitxor_assign_impl {
+    ($($t:ty)+) => ($(
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
+        impl BitXorAssign for $t {
+            #[inline]
+            fn bitxor_assign(&mut self, other: $t) { *self ^= other }
+        }
+    )+)
+}
+
+bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+
+/// The left shift assignment operator `<<=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up
+/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`.
+///
+/// ```
+/// use std::ops::ShlAssign;
+///
+/// struct Foo;
+///
+/// impl ShlAssign<Foo> for Foo {
+///     fn shl_assign(&mut self, _rhs: Foo) {
+///         println!("Shifting left!");
+///     }
+/// }
+///
+/// # #[allow(unused_assignments)]
+/// fn main() {
+///     let mut foo = Foo;
+///     foo <<= Foo;
+/// }
+/// ```
+#[lang = "shl_assign"]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"]
+pub trait ShlAssign<Rhs> {
+    /// The method for the `<<=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
+    fn shl_assign(&mut self, rhs: Rhs);
+}
+
+macro_rules! shl_assign_impl {
+    ($t:ty, $f:ty) => (
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
+        impl ShlAssign<$f> for $t {
+            #[inline]
+            #[rustc_inherit_overflow_checks]
+            fn shl_assign(&mut self, other: $f) {
+                *self <<= other
+            }
+        }
+    )
+}
+
+macro_rules! shl_assign_impl_all {
+    ($($t:ty)*) => ($(
+        shl_assign_impl! { $t, u8 }
+        shl_assign_impl! { $t, u16 }
+        shl_assign_impl! { $t, u32 }
+        shl_assign_impl! { $t, u64 }
+        shl_assign_impl! { $t, u128 }
+        shl_assign_impl! { $t, usize }
+
+        shl_assign_impl! { $t, i8 }
+        shl_assign_impl! { $t, i16 }
+        shl_assign_impl! { $t, i32 }
+        shl_assign_impl! { $t, i64 }
+        shl_assign_impl! { $t, i128 }
+        shl_assign_impl! { $t, isize }
+    )*)
+}
+
+shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
+
+/// The right shift assignment operator `>>=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up
+/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`.
+///
+/// ```
+/// use std::ops::ShrAssign;
+///
+/// struct Foo;
+///
+/// impl ShrAssign<Foo> for Foo {
+///     fn shr_assign(&mut self, _rhs: Foo) {
+///         println!("Shifting right!");
+///     }
+/// }
+///
+/// # #[allow(unused_assignments)]
+/// fn main() {
+///     let mut foo = Foo;
+///     foo >>= Foo;
+/// }
+/// ```
+#[lang = "shr_assign"]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
+#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"]
+pub trait ShrAssign<Rhs=Self> {
+    /// The method for the `>>=` operator
+    #[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")]
+        impl ShrAssign<$f> for $t {
+            #[inline]
+            #[rustc_inherit_overflow_checks]
+            fn shr_assign(&mut self, other: $f) {
+                *self >>= other
+            }
+        }
+    )
+}
+
+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 }
diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs
index 7d10c35d5e0..fdc1b5fc235 100644
--- a/src/libcore/ops/mod.rs
+++ b/src/libcore/ops/mod.rs
@@ -148,6 +148,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 mod arith;
+mod bit;
 mod function;
 mod range;
 
@@ -158,6 +159,12 @@ pub use self::arith::{Add, Sub, Mul, Div, Rem, Neg};
 pub use self::arith::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
 
 #[stable(feature = "rust1", since = "1.0.0")]
+pub use self::bit::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
+
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
+pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
+
+#[stable(feature = "rust1", since = "1.0.0")]
 pub use self::function::{Fn, FnMut, FnOnce};
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -258,836 +265,6 @@ pub trait Drop {
     fn drop(&mut self);
 }
 
-/// The unary logical negation operator `!`.
-///
-/// # Examples
-///
-/// An implementation of `Not` for `Answer`, which enables the use of `!` to
-/// invert its value.
-///
-/// ```
-/// use std::ops::Not;
-///
-/// #[derive(Debug, PartialEq)]
-/// enum Answer {
-///     Yes,
-///     No,
-/// }
-///
-/// impl Not for Answer {
-///     type Output = Answer;
-///
-///     fn not(self) -> Answer {
-///         match self {
-///             Answer::Yes => Answer::No,
-///             Answer::No => Answer::Yes
-///         }
-///     }
-/// }
-///
-/// assert_eq!(!Answer::Yes, Answer::No);
-/// assert_eq!(!Answer::No, Answer::Yes);
-/// ```
-#[lang = "not"]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait Not {
-    /// The resulting type after applying the `!` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    type Output;
-
-    /// The method for the unary `!` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn not(self) -> Self::Output;
-}
-
-macro_rules! not_impl {
-    ($($t:ty)*) => ($(
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl Not for $t {
-            type Output = $t;
-
-            #[inline]
-            fn not(self) -> $t { !self }
-        }
-
-        forward_ref_unop! { impl Not, not for $t }
-    )*)
-}
-
-not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-
-/// The bitwise AND operator `&`.
-///
-/// # Examples
-///
-/// In this example, the `&` operator is lifted to a trivial `Scalar` type.
-///
-/// ```
-/// use std::ops::BitAnd;
-///
-/// #[derive(Debug, PartialEq)]
-/// struct Scalar(bool);
-///
-/// impl BitAnd for Scalar {
-///     type Output = Self;
-///
-///     // rhs is the "right-hand side" of the expression `a & b`
-///     fn bitand(self, rhs: Self) -> Self {
-///         Scalar(self.0 & rhs.0)
-///     }
-/// }
-///
-/// fn main() {
-///     assert_eq!(Scalar(true) & Scalar(true), Scalar(true));
-///     assert_eq!(Scalar(true) & Scalar(false), Scalar(false));
-///     assert_eq!(Scalar(false) & Scalar(true), Scalar(false));
-///     assert_eq!(Scalar(false) & Scalar(false), Scalar(false));
-/// }
-/// ```
-///
-/// In this example, the `BitAnd` trait is implemented for a `BooleanVector`
-/// struct.
-///
-/// ```
-/// use std::ops::BitAnd;
-///
-/// #[derive(Debug, PartialEq)]
-/// struct BooleanVector(Vec<bool>);
-///
-/// impl BitAnd for BooleanVector {
-///     type Output = Self;
-///
-///     fn bitand(self, BooleanVector(rhs): Self) -> Self {
-///         let BooleanVector(lhs) = self;
-///         assert_eq!(lhs.len(), rhs.len());
-///         BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect())
-///     }
-/// }
-///
-/// fn main() {
-///     let bv1 = BooleanVector(vec![true, true, false, false]);
-///     let bv2 = BooleanVector(vec![true, false, true, false]);
-///     let expected = BooleanVector(vec![true, false, false, false]);
-///     assert_eq!(bv1 & bv2, expected);
-/// }
-/// ```
-#[lang = "bitand"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"]
-pub trait BitAnd<RHS=Self> {
-    /// The resulting type after applying the `&` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    type Output;
-
-    /// The method for the `&` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn bitand(self, rhs: RHS) -> Self::Output;
-}
-
-macro_rules! bitand_impl {
-    ($($t:ty)*) => ($(
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl BitAnd for $t {
-            type Output = $t;
-
-            #[inline]
-            fn bitand(self, rhs: $t) -> $t { self & rhs }
-        }
-
-        forward_ref_binop! { impl BitAnd, bitand for $t, $t }
-    )*)
-}
-
-bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-
-/// The bitwise OR operator `|`.
-///
-/// # Examples
-///
-/// In this example, the `|` operator is lifted to a trivial `Scalar` type.
-///
-/// ```
-/// use std::ops::BitOr;
-///
-/// #[derive(Debug, PartialEq)]
-/// struct Scalar(bool);
-///
-/// impl BitOr for Scalar {
-///     type Output = Self;
-///
-///     // rhs is the "right-hand side" of the expression `a | b`
-///     fn bitor(self, rhs: Self) -> Self {
-///         Scalar(self.0 | rhs.0)
-///     }
-/// }
-///
-/// fn main() {
-///     assert_eq!(Scalar(true) | Scalar(true), Scalar(true));
-///     assert_eq!(Scalar(true) | Scalar(false), Scalar(true));
-///     assert_eq!(Scalar(false) | Scalar(true), Scalar(true));
-///     assert_eq!(Scalar(false) | Scalar(false), Scalar(false));
-/// }
-/// ```
-///
-/// In this example, the `BitOr` trait is implemented for a `BooleanVector`
-/// struct.
-///
-/// ```
-/// use std::ops::BitOr;
-///
-/// #[derive(Debug, PartialEq)]
-/// struct BooleanVector(Vec<bool>);
-///
-/// impl BitOr for BooleanVector {
-///     type Output = Self;
-///
-///     fn bitor(self, BooleanVector(rhs): Self) -> Self {
-///         let BooleanVector(lhs) = self;
-///         assert_eq!(lhs.len(), rhs.len());
-///         BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect())
-///     }
-/// }
-///
-/// fn main() {
-///     let bv1 = BooleanVector(vec![true, true, false, false]);
-///     let bv2 = BooleanVector(vec![true, false, true, false]);
-///     let expected = BooleanVector(vec![true, true, true, false]);
-///     assert_eq!(bv1 | bv2, expected);
-/// }
-/// ```
-#[lang = "bitor"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"]
-pub trait BitOr<RHS=Self> {
-    /// The resulting type after applying the `|` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    type Output;
-
-    /// The method for the `|` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn bitor(self, rhs: RHS) -> Self::Output;
-}
-
-macro_rules! bitor_impl {
-    ($($t:ty)*) => ($(
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl BitOr for $t {
-            type Output = $t;
-
-            #[inline]
-            fn bitor(self, rhs: $t) -> $t { self | rhs }
-        }
-
-        forward_ref_binop! { impl BitOr, bitor for $t, $t }
-    )*)
-}
-
-bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-
-/// The bitwise XOR operator `^`.
-///
-/// # Examples
-///
-/// In this example, the `^` operator is lifted to a trivial `Scalar` type.
-///
-/// ```
-/// use std::ops::BitXor;
-///
-/// #[derive(Debug, PartialEq)]
-/// struct Scalar(bool);
-///
-/// impl BitXor for Scalar {
-///     type Output = Self;
-///
-///     // rhs is the "right-hand side" of the expression `a ^ b`
-///     fn bitxor(self, rhs: Self) -> Self {
-///         Scalar(self.0 ^ rhs.0)
-///     }
-/// }
-///
-/// fn main() {
-///     assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false));
-///     assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true));
-///     assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true));
-///     assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false));
-/// }
-/// ```
-///
-/// In this example, the `BitXor` trait is implemented for a `BooleanVector`
-/// struct.
-///
-/// ```
-/// use std::ops::BitXor;
-///
-/// #[derive(Debug, PartialEq)]
-/// struct BooleanVector(Vec<bool>);
-///
-/// impl BitXor for BooleanVector {
-///     type Output = Self;
-///
-///     fn bitxor(self, BooleanVector(rhs): Self) -> Self {
-///         let BooleanVector(lhs) = self;
-///         assert_eq!(lhs.len(), rhs.len());
-///         BooleanVector(lhs.iter()
-///                          .zip(rhs.iter())
-///                          .map(|(x, y)| (*x || *y) && !(*x && *y))
-///                          .collect())
-///     }
-/// }
-///
-/// fn main() {
-///     let bv1 = BooleanVector(vec![true, true, false, false]);
-///     let bv2 = BooleanVector(vec![true, false, true, false]);
-///     let expected = BooleanVector(vec![false, true, true, false]);
-///     assert_eq!(bv1 ^ bv2, expected);
-/// }
-/// ```
-#[lang = "bitxor"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"]
-pub trait BitXor<RHS=Self> {
-    /// The resulting type after applying the `^` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    type Output;
-
-    /// The method for the `^` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn bitxor(self, rhs: RHS) -> Self::Output;
-}
-
-macro_rules! bitxor_impl {
-    ($($t:ty)*) => ($(
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl BitXor for $t {
-            type Output = $t;
-
-            #[inline]
-            fn bitxor(self, other: $t) -> $t { self ^ other }
-        }
-
-        forward_ref_binop! { impl BitXor, bitxor for $t, $t }
-    )*)
-}
-
-bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-
-/// The left shift operator `<<`.
-///
-/// # Examples
-///
-/// An implementation of `Shl` that lifts the `<<` operation on integers to a
-/// `Scalar` struct.
-///
-/// ```
-/// use std::ops::Shl;
-///
-/// #[derive(PartialEq, Debug)]
-/// struct Scalar(usize);
-///
-/// impl Shl<Scalar> for Scalar {
-///     type Output = Self;
-///
-///     fn shl(self, Scalar(rhs): Self) -> Scalar {
-///         let Scalar(lhs) = self;
-///         Scalar(lhs << rhs)
-///     }
-/// }
-/// fn main() {
-///     assert_eq!(Scalar(4) << Scalar(2), Scalar(16));
-/// }
-/// ```
-///
-/// An implementation of `Shl` that spins a vector leftward by a given amount.
-///
-/// ```
-/// use std::ops::Shl;
-///
-/// #[derive(PartialEq, Debug)]
-/// struct SpinVector<T: Clone> {
-///     vec: Vec<T>,
-/// }
-///
-/// impl<T: Clone> Shl<usize> for SpinVector<T> {
-///     type Output = Self;
-///
-///     fn shl(self, rhs: usize) -> SpinVector<T> {
-///         // rotate the vector by `rhs` places
-///         let (a, b) = self.vec.split_at(rhs);
-///         let mut spun_vector: Vec<T> = vec![];
-///         spun_vector.extend_from_slice(b);
-///         spun_vector.extend_from_slice(a);
-///         SpinVector { vec: spun_vector }
-///     }
-/// }
-///
-/// fn main() {
-///     assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2,
-///                SpinVector { vec: vec![2, 3, 4, 0, 1] });
-/// }
-/// ```
-#[lang = "shl"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"]
-pub trait Shl<RHS> {
-    /// The resulting type after applying the `<<` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    type Output;
-
-    /// The method for the `<<` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn shl(self, rhs: RHS) -> Self::Output;
-}
-
-macro_rules! shl_impl {
-    ($t:ty, $f:ty) => (
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl Shl<$f> for $t {
-            type Output = $t;
-
-            #[inline]
-            #[rustc_inherit_overflow_checks]
-            fn shl(self, other: $f) -> $t {
-                self << other
-            }
-        }
-
-        forward_ref_binop! { impl Shl, shl for $t, $f }
-    )
-}
-
-macro_rules! shl_impl_all {
-    ($($t:ty)*) => ($(
-        shl_impl! { $t, u8 }
-        shl_impl! { $t, u16 }
-        shl_impl! { $t, u32 }
-        shl_impl! { $t, u64 }
-        shl_impl! { $t, u128 }
-        shl_impl! { $t, usize }
-
-        shl_impl! { $t, i8 }
-        shl_impl! { $t, i16 }
-        shl_impl! { $t, i32 }
-        shl_impl! { $t, i64 }
-        shl_impl! { $t, i128 }
-        shl_impl! { $t, isize }
-    )*)
-}
-
-shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
-
-/// The right shift operator `>>`.
-///
-/// # Examples
-///
-/// An implementation of `Shr` that lifts the `>>` operation on integers to a
-/// `Scalar` struct.
-///
-/// ```
-/// use std::ops::Shr;
-///
-/// #[derive(PartialEq, Debug)]
-/// struct Scalar(usize);
-///
-/// impl Shr<Scalar> for Scalar {
-///     type Output = Self;
-///
-///     fn shr(self, Scalar(rhs): Self) -> Scalar {
-///         let Scalar(lhs) = self;
-///         Scalar(lhs >> rhs)
-///     }
-/// }
-/// fn main() {
-///     assert_eq!(Scalar(16) >> Scalar(2), Scalar(4));
-/// }
-/// ```
-///
-/// An implementation of `Shr` that spins a vector rightward by a given amount.
-///
-/// ```
-/// use std::ops::Shr;
-///
-/// #[derive(PartialEq, Debug)]
-/// struct SpinVector<T: Clone> {
-///     vec: Vec<T>,
-/// }
-///
-/// impl<T: Clone> Shr<usize> for SpinVector<T> {
-///     type Output = Self;
-///
-///     fn shr(self, rhs: usize) -> SpinVector<T> {
-///         // rotate the vector by `rhs` places
-///         let (a, b) = self.vec.split_at(self.vec.len() - rhs);
-///         let mut spun_vector: Vec<T> = vec![];
-///         spun_vector.extend_from_slice(b);
-///         spun_vector.extend_from_slice(a);
-///         SpinVector { vec: spun_vector }
-///     }
-/// }
-///
-/// fn main() {
-///     assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2,
-///                SpinVector { vec: vec![3, 4, 0, 1, 2] });
-/// }
-/// ```
-#[lang = "shr"]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"]
-pub trait Shr<RHS> {
-    /// The resulting type after applying the `>>` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    type Output;
-
-    /// The method for the `>>` operator
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn shr(self, rhs: RHS) -> Self::Output;
-}
-
-macro_rules! shr_impl {
-    ($t:ty, $f:ty) => (
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl Shr<$f> for $t {
-            type Output = $t;
-
-            #[inline]
-            #[rustc_inherit_overflow_checks]
-            fn shr(self, other: $f) -> $t {
-                self >> other
-            }
-        }
-
-        forward_ref_binop! { impl Shr, shr for $t, $f }
-    )
-}
-
-macro_rules! shr_impl_all {
-    ($($t:ty)*) => ($(
-        shr_impl! { $t, u8 }
-        shr_impl! { $t, u16 }
-        shr_impl! { $t, u32 }
-        shr_impl! { $t, u64 }
-        shr_impl! { $t, u128 }
-        shr_impl! { $t, usize }
-
-        shr_impl! { $t, i8 }
-        shr_impl! { $t, i16 }
-        shr_impl! { $t, i32 }
-        shr_impl! { $t, i64 }
-        shr_impl! { $t, i128 }
-        shr_impl! { $t, isize }
-    )*)
-}
-
-shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
-
-/// The bitwise AND assignment operator `&=`.
-///
-/// # Examples
-///
-/// In this example, the `&=` operator is lifted to a trivial `Scalar` type.
-///
-/// ```
-/// use std::ops::BitAndAssign;
-///
-/// #[derive(Debug, PartialEq)]
-/// struct Scalar(bool);
-///
-/// impl BitAndAssign for Scalar {
-///     // rhs is the "right-hand side" of the expression `a &= b`
-///     fn bitand_assign(&mut self, rhs: Self) {
-///         *self = Scalar(self.0 & rhs.0)
-///     }
-/// }
-///
-/// fn main() {
-///     let mut scalar = Scalar(true);
-///     scalar &= Scalar(true);
-///     assert_eq!(scalar, Scalar(true));
-///
-///     let mut scalar = Scalar(true);
-///     scalar &= Scalar(false);
-///     assert_eq!(scalar, Scalar(false));
-///
-///     let mut scalar = Scalar(false);
-///     scalar &= Scalar(true);
-///     assert_eq!(scalar, Scalar(false));
-///
-///     let mut scalar = Scalar(false);
-///     scalar &= Scalar(false);
-///     assert_eq!(scalar, Scalar(false));
-/// }
-/// ```
-///
-/// In this example, the `BitAndAssign` trait is implemented for a
-/// `BooleanVector` struct.
-///
-/// ```
-/// use std::ops::BitAndAssign;
-///
-/// #[derive(Debug, PartialEq)]
-/// struct BooleanVector(Vec<bool>);
-///
-/// impl BitAndAssign for BooleanVector {
-///     // rhs is the "right-hand side" of the expression `a &= b`
-///     fn bitand_assign(&mut self, rhs: Self) {
-///         assert_eq!(self.0.len(), rhs.0.len());
-///         *self = BooleanVector(self.0
-///                                   .iter()
-///                                   .zip(rhs.0.iter())
-///                                   .map(|(x, y)| *x && *y)
-///                                   .collect());
-///     }
-/// }
-///
-/// fn main() {
-///     let mut bv = BooleanVector(vec![true, true, false, false]);
-///     bv &= BooleanVector(vec![true, false, true, false]);
-///     let expected = BooleanVector(vec![true, false, false, false]);
-///     assert_eq!(bv, expected);
-/// }
-/// ```
-#[lang = "bitand_assign"]
-#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"]
-pub trait BitAndAssign<Rhs=Self> {
-    /// The method for the `&=` operator
-    #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn bitand_assign(&mut self, rhs: Rhs);
-}
-
-macro_rules! bitand_assign_impl {
-    ($($t:ty)+) => ($(
-        #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl BitAndAssign for $t {
-            #[inline]
-            fn bitand_assign(&mut self, other: $t) { *self &= other }
-        }
-    )+)
-}
-
-bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-
-/// The bitwise OR assignment operator `|=`.
-///
-/// # Examples
-///
-/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up
-/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`.
-///
-/// ```
-/// use std::ops::BitOrAssign;
-///
-/// struct Foo;
-///
-/// impl BitOrAssign for Foo {
-///     fn bitor_assign(&mut self, _rhs: Foo) {
-///         println!("Bitwise Or-ing!");
-///     }
-/// }
-///
-/// # #[allow(unused_assignments)]
-/// fn main() {
-///     let mut foo = Foo;
-///     foo |= Foo;
-/// }
-/// ```
-#[lang = "bitor_assign"]
-#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"]
-pub trait BitOrAssign<Rhs=Self> {
-    /// The method for the `|=` operator
-    #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn bitor_assign(&mut self, rhs: Rhs);
-}
-
-macro_rules! bitor_assign_impl {
-    ($($t:ty)+) => ($(
-        #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl BitOrAssign for $t {
-            #[inline]
-            fn bitor_assign(&mut self, other: $t) { *self |= other }
-        }
-    )+)
-}
-
-bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-
-/// The bitwise XOR assignment operator `^=`.
-///
-/// # Examples
-///
-/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up
-/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`.
-///
-/// ```
-/// use std::ops::BitXorAssign;
-///
-/// struct Foo;
-///
-/// impl BitXorAssign for Foo {
-///     fn bitxor_assign(&mut self, _rhs: Foo) {
-///         println!("Bitwise Xor-ing!");
-///     }
-/// }
-///
-/// # #[allow(unused_assignments)]
-/// fn main() {
-///     let mut foo = Foo;
-///     foo ^= Foo;
-/// }
-/// ```
-#[lang = "bitxor_assign"]
-#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"]
-pub trait BitXorAssign<Rhs=Self> {
-    /// The method for the `^=` operator
-    #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn bitxor_assign(&mut self, rhs: Rhs);
-}
-
-macro_rules! bitxor_assign_impl {
-    ($($t:ty)+) => ($(
-        #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl BitXorAssign for $t {
-            #[inline]
-            fn bitxor_assign(&mut self, other: $t) { *self ^= other }
-        }
-    )+)
-}
-
-bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-
-/// The left shift assignment operator `<<=`.
-///
-/// # Examples
-///
-/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up
-/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`.
-///
-/// ```
-/// use std::ops::ShlAssign;
-///
-/// struct Foo;
-///
-/// impl ShlAssign<Foo> for Foo {
-///     fn shl_assign(&mut self, _rhs: Foo) {
-///         println!("Shifting left!");
-///     }
-/// }
-///
-/// # #[allow(unused_assignments)]
-/// fn main() {
-///     let mut foo = Foo;
-///     foo <<= Foo;
-/// }
-/// ```
-#[lang = "shl_assign"]
-#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"]
-pub trait ShlAssign<Rhs> {
-    /// The method for the `<<=` operator
-    #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn shl_assign(&mut self, rhs: Rhs);
-}
-
-macro_rules! shl_assign_impl {
-    ($t:ty, $f:ty) => (
-        #[stable(feature = "op_assign_traits", since = "1.8.0")]
-        impl ShlAssign<$f> for $t {
-            #[inline]
-            #[rustc_inherit_overflow_checks]
-            fn shl_assign(&mut self, other: $f) {
-                *self <<= other
-            }
-        }
-    )
-}
-
-macro_rules! shl_assign_impl_all {
-    ($($t:ty)*) => ($(
-        shl_assign_impl! { $t, u8 }
-        shl_assign_impl! { $t, u16 }
-        shl_assign_impl! { $t, u32 }
-        shl_assign_impl! { $t, u64 }
-        shl_assign_impl! { $t, u128 }
-        shl_assign_impl! { $t, usize }
-
-        shl_assign_impl! { $t, i8 }
-        shl_assign_impl! { $t, i16 }
-        shl_assign_impl! { $t, i32 }
-        shl_assign_impl! { $t, i64 }
-        shl_assign_impl! { $t, i128 }
-        shl_assign_impl! { $t, isize }
-    )*)
-}
-
-shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
-
-/// The right shift assignment operator `>>=`.
-///
-/// # Examples
-///
-/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up
-/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`.
-///
-/// ```
-/// use std::ops::ShrAssign;
-///
-/// struct Foo;
-///
-/// impl ShrAssign<Foo> for Foo {
-///     fn shr_assign(&mut self, _rhs: Foo) {
-///         println!("Shifting right!");
-///     }
-/// }
-///
-/// # #[allow(unused_assignments)]
-/// fn main() {
-///     let mut foo = Foo;
-///     foo >>= Foo;
-/// }
-/// ```
-#[lang = "shr_assign"]
-#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"]
-pub trait ShrAssign<Rhs=Self> {
-    /// The method for the `>>=` operator
-    #[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")]
-        impl ShrAssign<$f> for $t {
-            #[inline]
-            #[rustc_inherit_overflow_checks]
-            fn shr_assign(&mut self, other: $f) {
-                *self >>= other
-            }
-        }
-    )
-}
-
-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 }
-
 /// The `Index` trait is used to specify the functionality of indexing operations
 /// like `container[index]` when used in an immutable context.
 ///