Skip to content

Commit

Permalink
Add augmented assignment (rust-lang#5992), sans wiring.
Browse files Browse the repository at this point in the history
This is the first part of rust-lang#5992, covering the traits and their
implementations and documentation of it all, but not including the
wiring to make the actual operators (such as `+=`) desugar to the
appropriate method call.

This comes from my old augmented-assignment branch which had the wiring
also but wasn't quite right. Things have changed enough that that wiring
is utterly defunct and unworthy of any attempt at resurrection. The
traits, however, were not, so I have restored that part of the work.

All places in the present code base where any of the arithmetic traits
(`Add`, `Sub`, `Mul`, `Div`, `Rem`, `BitAnd`, `BitOr`, `BitXor`, `Shl`
and `Shr`) were implemented has an `*Assign` trait implementation added,
with the exception (as before and as noted in the code) of `&str` and
`&[T]` where the assignment operators cannot be implemented.

Note that there is necessarily no default implementation of the
`*Assign` traits, as that would preclude more efficient implementations
of the augmented assignment operators and render the whole thing utterly
pointless (c.f. rust-lang#7059 on function specialisation).
  • Loading branch information
chris-morgan authored and flaper87 committed Feb 11, 2014
1 parent be3cbcb commit 9a4ed61
Show file tree
Hide file tree
Showing 21 changed files with 424 additions and 12 deletions.
20 changes: 20 additions & 0 deletions src/doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -1852,28 +1852,48 @@ A complete list of the built-in language items follows:
: Have finalizers.
`add`
: Elements can be added (for example, integers and floats).
`add_assign`
: Elements can be added with augmented assignment.
`sub`
: Elements can be subtracted.
`sub_assign`
: Elements can be subtracted with augmented assignment.
`mul`
: Elements can be multiplied.
`mul_assign`
: Elements can be multiplied with augmented assignment.
`div`
: Elements have a division operation.
`div_assign`
: Elements have a division operation with augmented assignment.
`rem`
: Elements have a remainder operation.
`rem_assign`
: Elements have a remainder operation with augmented assignment.
`neg`
: Elements can be negated arithmetically.
`not`
: Elements can be negated logically.
`bitxor`
: Elements have an exclusive-or operation.
`bitxor_assign`
: Elements have an exclusive-or operation with augmented assignment.
`bitand`
: Elements have a bitwise `and` operation.
`bitand_assign`
: Elements have a bitwise `and` operation with augmented assignment.
`bitor`
: Elements have a bitwise `or` operation.
`bitor_assign`
: Elements have a bitwise `or` operation with augmented assignment.
`shl`
: Elements have a left shift operation.
`shl_assign`
: Elements have a left shift operation with augmented assignment.
`shr`
: Elements have a right shift operation.
`shr_assign`
: Elements have a right shift operation with augmented assignment.
`index`
: Elements can be indexed.
`eq`
Expand Down
12 changes: 11 additions & 1 deletion src/etc/kate/rust.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,26 @@
<item> Ptr </item>
<item> Drop </item>
<item> Add </item>
<item> AddAssign </item>
<item> Sub </item>
<item> SubAssign </item>
<item> Mul </item>
<item> Quot </item>
<item> MulAssign </item>
<item> Div </item>
<item> DivAssign </item>
<item> Rem </item>
<item> RemAssign </item>
<item> Neg </item>
<item> BitAnd </item>
<item> BitAndAssign </item>
<item> BitOr </item>
<item> BitOrAssign </item>
<item> BitXor </item>
<item> BitXorAssign </item>
<item> Shl </item>
<item> ShlAssign </item>
<item> Shr </item>
<item> ShrAssign </item>
<item> Index </item>
<item> Not </item>
</list>
Expand Down
3 changes: 3 additions & 0 deletions src/etc/vim/syntax/rust.vim
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,12 @@ syn keyword rustType f64 i8 i16 i32 i64 str Self
syn keyword rustTrait Sized
syn keyword rustTrait Freeze Send
syn keyword rustTrait Add Sub Mul Div Rem Neg Not
syn keyword rustTrait AddAssign SubAssign MulAssign DivAssign RemAssign
syn keyword rustTrait BitAnd BitOr BitXor
syn keyword rustTrait BitAndAssign BitOrAssign BitXorAssign
syn keyword rustTrait Drop
syn keyword rustTrait Shl Shr Index
syn keyword rustTrait ShlAssign ShrAssign
syn keyword rustEnum Option
syn keyword rustEnumVariant Some None
syn keyword rustEnum Result
Expand Down
18 changes: 18 additions & 0 deletions src/libextra/enum_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,36 @@ impl<E:CLike> Sub<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
}
}

impl<E:CLike> SubAssign<EnumSet<E>> for EnumSet<E> {
fn sub_assign(&mut self, e: &EnumSet<E>) {
self.bits &= !e.bits;
}
}

impl<E:CLike> BitOr<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitor(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits | e.bits}
}
}

impl<E:CLike> BitOrAssign<EnumSet<E>> for EnumSet<E> {
fn bitor_assign(&mut self, e: &EnumSet<E>) {
self.bits |= e.bits;
}
}

impl<E:CLike> BitAnd<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitand(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits & e.bits}
}
}

impl<E:CLike> BitAndAssign<EnumSet<E>> for EnumSet<E> {
fn bitand_assign(&mut self, e: &EnumSet<E>) {
self.bits &= e.bits;
}
}

/// An iterator over an EnumSet
pub struct Items<E> {
priv index: uint,
Expand Down
34 changes: 34 additions & 0 deletions src/libnum/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ impl BitAnd<BigUint, BigUint> for BigUint {
}
}

impl BitAndAssign<BigUint> for BigUint {}

impl BitOr<BigUint, BigUint> for BigUint {
fn bitor(&self, other: &BigUint) -> BigUint {
let new_len = num::max(self.data.len(), other.data.len());
Expand All @@ -176,6 +178,8 @@ impl BitOr<BigUint, BigUint> for BigUint {
}
}

impl BitOrAssign<BigUint> for BigUint {}

impl BitXor<BigUint, BigUint> for BigUint {
fn bitxor(&self, other: &BigUint) -> BigUint {
let new_len = num::max(self.data.len(), other.data.len());
Expand All @@ -188,6 +192,8 @@ impl BitXor<BigUint, BigUint> for BigUint {
}
}

impl BitXorAssign<BigUint> for BigUint {}

impl Shl<uint, BigUint> for BigUint {
#[inline]
fn shl(&self, rhs: &uint) -> BigUint {
Expand All @@ -197,6 +203,8 @@ impl Shl<uint, BigUint> for BigUint {
}
}

impl ShlAssign<uint> for BigUint {}

impl Shr<uint, BigUint> for BigUint {
#[inline]
fn shr(&self, rhs: &uint) -> BigUint {
Expand All @@ -206,6 +214,8 @@ impl Shr<uint, BigUint> for BigUint {
}
}

impl ShrAssign<uint> for BigUint {}

impl Zero for BigUint {
#[inline]
fn zero() -> BigUint { BigUint::new(~[]) }
Expand Down Expand Up @@ -240,6 +250,8 @@ impl Add<BigUint, BigUint> for BigUint {
}
}

impl AddAssign<BigUint> for BigUint {}

impl Sub<BigUint, BigUint> for BigUint {
fn sub(&self, other: &BigUint) -> BigUint {
let new_len = num::max(self.data.len(), other.data.len());
Expand All @@ -265,6 +277,8 @@ impl Sub<BigUint, BigUint> for BigUint {
}
}

impl SubAssign<BigUint> for BigUint {}

impl Mul<BigUint, BigUint> for BigUint {
fn mul(&self, other: &BigUint) -> BigUint {
if self.is_zero() || other.is_zero() { return Zero::zero(); }
Expand Down Expand Up @@ -331,6 +345,8 @@ impl Mul<BigUint, BigUint> for BigUint {
}
}

impl MulAssign<BigUint> for BigUint {}

impl Div<BigUint, BigUint> for BigUint {
#[inline]
fn div(&self, other: &BigUint) -> BigUint {
Expand All @@ -339,6 +355,8 @@ impl Div<BigUint, BigUint> for BigUint {
}
}

impl DivAssign<BigUint> for BigUint {}

impl Rem<BigUint, BigUint> for BigUint {
#[inline]
fn rem(&self, other: &BigUint) -> BigUint {
Expand All @@ -347,6 +365,8 @@ impl Rem<BigUint, BigUint> for BigUint {
}
}

impl RemAssign<BigUint> for BigUint {}

impl Neg<BigUint> for BigUint {
#[inline]
fn neg(&self) -> BigUint { fail!() }
Expand Down Expand Up @@ -965,13 +985,17 @@ impl Shl<uint, BigInt> for BigInt {
}
}

impl ShlAssign<uint> for BigInt {}

impl Shr<uint, BigInt> for BigInt {
#[inline]
fn shr(&self, rhs: &uint) -> BigInt {
BigInt::from_biguint(self.sign, self.data >> *rhs)
}
}

impl ShrAssign<uint> for BigInt {}

impl Zero for BigInt {
#[inline]
fn zero() -> BigInt {
Expand Down Expand Up @@ -1034,6 +1058,8 @@ impl Add<BigInt, BigInt> for BigInt {
}
}

impl AddAssign<BigInt> for BigInt {}

impl Sub<BigInt, BigInt> for BigInt {
#[inline]
fn sub(&self, other: &BigInt) -> BigInt {
Expand All @@ -1052,6 +1078,8 @@ impl Sub<BigInt, BigInt> for BigInt {
}
}

impl SubAssign<BigInt> for BigInt {}

impl Mul<BigInt, BigInt> for BigInt {
#[inline]
fn mul(&self, other: &BigInt) -> BigInt {
Expand All @@ -1067,6 +1095,8 @@ impl Mul<BigInt, BigInt> for BigInt {
}
}

impl MulAssign<BigInt> for BigInt {}

impl Div<BigInt, BigInt> for BigInt {
#[inline]
fn div(&self, other: &BigInt) -> BigInt {
Expand All @@ -1075,6 +1105,8 @@ impl Div<BigInt, BigInt> for BigInt {
}
}

impl DivAssign<BigInt> for BigInt {}

impl Rem<BigInt, BigInt> for BigInt {
#[inline]
fn rem(&self, other: &BigInt) -> BigInt {
Expand All @@ -1083,6 +1115,8 @@ impl Rem<BigInt, BigInt> for BigInt {
}
}

impl RemAssign<BigInt> for BigInt {}

impl Neg<BigInt> for BigInt {
#[inline]
fn neg(&self) -> BigInt {
Expand Down
6 changes: 6 additions & 0 deletions src/libnum/complex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,17 @@ impl<T: Clone + Num> Add<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
Cmplx::new(self.re + other.re, self.im + other.im)
}
}
impl<T: Clone + Num> AddAssign<Cmplx<T>> for Cmplx<T> {}

// (a + i b) - (c + i d) == (a - c) + i (b - d)
impl<T: Clone + Num> Sub<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
#[inline]
fn sub(&self, other: &Cmplx<T>) -> Cmplx<T> {
Cmplx::new(self.re - other.re, self.im - other.im)
}
}
impl<T: Clone + Num> SubAssign<Cmplx<T>> for Cmplx<T> {}

// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c)
impl<T: Clone + Num> Mul<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
#[inline]
Expand All @@ -127,6 +131,7 @@ impl<T: Clone + Num> Mul<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
self.re*other.im + self.im*other.re)
}
}
impl<T: Clone + Num> MulAssign<Cmplx<T>> for Cmplx<T> {}

// (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d)
// == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)]
Expand All @@ -138,6 +143,7 @@ impl<T: Clone + Num> Div<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
(self.im*other.re - self.re*other.im) / norm_sqr)
}
}
impl<T: Clone + Num> DivAssign<Cmplx<T>> for Cmplx<T> {}

impl<T: Clone + Num> Neg<Cmplx<T>> for Cmplx<T> {
#[inline]
Expand Down
14 changes: 10 additions & 4 deletions src/libnum/rational.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ impl<T: Clone + Integer + Ord>
}
}

impl<T: Clone + Integer + Ord> MulAssign<Ratio<T>> for Ratio<T> {}

// (a/b) / (c/d) = (a*d)/(b*c)
impl<T: Clone + Integer + Ord>
Div<Ratio<T>,Ratio<T>> for Ratio<T> {
Expand All @@ -198,9 +200,11 @@ impl<T: Clone + Integer + Ord>
}
}

impl<T: Clone + Integer + Ord> DivAssign<Ratio<T>> for Ratio<T> {}

// Abstracts the a/b `op` c/d = (a*d `op` b*d) / (b*d) pattern
macro_rules! arith_impl {
(impl $imp:ident, $method:ident) => {
(impl $imp:ident/$imp_assign:ident, $method:ident) => {
impl<T: Clone + Integer + Ord>
$imp<Ratio<T>,Ratio<T>> for Ratio<T> {
#[inline]
Expand All @@ -209,17 +213,19 @@ macro_rules! arith_impl {
self.denom * rhs.denom)
}
}
impl<T: Clone + Integer + Ord>
$imp_assign<Ratio<T>> for Ratio<T> {}
}
}

// a/b + c/d = (a*d + b*c)/(b*d
arith_impl!(impl Add, add)
arith_impl!(impl Add/AddAssign, add)

// a/b - c/d = (a*d - b*c)/(b*d)
arith_impl!(impl Sub, sub)
arith_impl!(impl Sub/SubAssign, sub)

// a/b % c/d = (a*d % b*c)/(b*d)
arith_impl!(impl Rem, rem)
arith_impl!(impl Rem/RemAssign, rem)

impl<T: Clone + Integer + Ord>
Neg<Ratio<T>> for Ratio<T> {
Expand Down
14 changes: 13 additions & 1 deletion src/librustc/middle/borrowck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use util::ppaux::{note_and_explain_region, Repr, UserString};

use std::cell::{Cell, RefCell};
use std::hashmap::HashMap;
use std::ops::{BitOr, BitAnd};
use std::ops::{BitOr, BitOrAssign, BitAnd, BitAndAssign};
use std::result::{Result};
use syntax::ast;
use syntax::ast_map;
Expand Down Expand Up @@ -352,12 +352,24 @@ impl BitOr<RestrictionSet,RestrictionSet> for RestrictionSet {
}
}

impl BitOrAssign<RestrictionSet> for RestrictionSet {
fn bitor_assign(&mut self, rhs: &RestrictionSet) {
self.bits |= rhs.bits;
}
}

impl BitAnd<RestrictionSet,RestrictionSet> for RestrictionSet {
fn bitand(&self, rhs: &RestrictionSet) -> RestrictionSet {
RestrictionSet {bits: self.bits & rhs.bits}
}
}

impl BitAndAssign<RestrictionSet> for RestrictionSet {
fn bitand_assign(&mut self, rhs: &RestrictionSet) {
self.bits &= rhs.bits;
}
}

///////////////////////////////////////////////////////////////////////////
// Rooting of managed boxes
//
Expand Down
Loading

0 comments on commit 9a4ed61

Please sign in to comment.