Skip to content

Commit 52caecd

Browse files
committed
Merge remote-tracking branch 'japaric/op-assign'
2 parents cafe0d8 + 7bca6c5 commit 52caecd

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

text/0000-op-assign.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
- Feature Name: op_assign
2+
- Start Date: 2015-03-08
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
5+
6+
# Summary
7+
8+
Add the family of `[Op]Assign` traits to allow overloading assignment
9+
operations like `a += b`.
10+
11+
# Motivation
12+
13+
We already let users overload the binary operations, letting them overload the
14+
assignment version is the next logical step. Plus, this sugar is important to
15+
make mathematical libraries more palatable.
16+
17+
# Detailed design
18+
19+
Add the following **unstable** traits to libcore and reexported them in libstd:
20+
21+
```
22+
// `+=`
23+
#[lang = "add_assign"]
24+
trait AddAssign<Rhs=Self> {
25+
fn add_assign(&mut self, Rhs);
26+
}
27+
28+
// the remaining traits have the same signature
29+
// (lang items have been omitted for brevity)
30+
trait BitAndAssign { .. } // `&=`
31+
trait BitOrAssign { .. } // `|=`
32+
trait BitXorAssign { .. } // `^=`
33+
trait DivAssign { .. } // `/=`
34+
trait MulAssign { .. } // `*=`
35+
trait RemAssign { .. } // `%=`
36+
trait ShlAssign { .. } // `<<=`
37+
trait ShrAssign { .. } // `>>=`
38+
trait SubAssign { .. } // `-=`
39+
```
40+
41+
Implement these traits for the primitive numeric types *without* overloading,
42+
i.e. only `impl AddAssign<i32> for i32 { .. }`.
43+
44+
Add an `op_assign` feature gate. When the feature gate is enabled, the compiler
45+
will consider these traits when typecheking `a += b`. Without the feature gate
46+
the compiler will enforce that `a` and `b` must be primitives of the same
47+
type/category as it does today.
48+
49+
Once we feel comfortable with the implementation we'll remove the feature gate
50+
and mark the traits as stable. This can be done after 1.0 as this change is
51+
backwards compatible.
52+
53+
## RHS: By value vs by ref
54+
55+
Taking the RHS by value is more flexible. The implementations allowed with
56+
a by value RHS are a superset of the implementations allowed with a by ref RHS.
57+
An example where taking the RHS by value is necessary would be operator sugar
58+
for extending a collection with an iterator [1]: `vec ++= iter` where
59+
`vec: Vec<T>` and `iter impls Iterator<T>`. This can't be implemented with the
60+
by ref version as the iterator couldn't be advanced in that case.
61+
62+
[1] Where `++` is the "combine" operator that has been proposed [elsewhere].
63+
Note that this RFC doesn't propose adding that particular operator or adding
64+
similar overloaded operations (`vec += iter`) to stdlib's collections, but it
65+
leaves the door open to the possibility of adding them in the future (if
66+
desired).
67+
68+
[elsewhere]: https://github.com/rust-lang/rfcs/pull/203
69+
70+
# Drawbacks
71+
72+
None that I can think of.
73+
74+
# Alternatives
75+
76+
Take the RHS by ref. This is less flexible than taking the RHS by value but, in
77+
some instances, it can save writing `&rhs` when the RHS is owned and the
78+
implementation demands a reference. However, this last point will be moot if we
79+
implement auto-referencing for binary operators, as `lhs += rhs` would actually
80+
call `add_assign(&mut lhs, &rhs)` if `Lhs impls AddAssign<&Rhs>`.
81+
82+
# Unresolved questions
83+
84+
Should we overload `ShlAssign` and `ShrAssign`, e.g.
85+
`impl ShlAssign<u8> for i32`, since we have already overloaded the `Shl` and
86+
`Shr` traits?
87+
88+
Should we overload all the traits for references, e.g.
89+
`impl<'a> AddAssign<&'a i32> for i32` to allow `x += &0;`?

0 commit comments

Comments
 (0)