Skip to content

Commit 8abcbab

Browse files
committed
Auto merge of #21227 - sellibitze:core-ops-for-references, r=aturon
As discussed with @aturon I added implementations of various op traits for references to built-in types which was already suggested by the ops reform RFC. The 2nd commit updates the module documentation of core::ops to fully reflect the recent change from pass-by-reference to pass-by-value and expands on the implications for generic code.
2 parents 51e28dd + 970fd74 commit 8abcbab

File tree

1 file changed

+92
-4
lines changed

1 file changed

+92
-4
lines changed

src/libcore/ops.rs

+92-4
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,20 @@
1313
//! Implementing these traits allows you to get an effect similar to
1414
//! overloading operators.
1515
//!
16-
//! The values for the right hand side of an operator are automatically
17-
//! borrowed, so `a + b` is sugar for `a.add(&b)`.
18-
//!
19-
//! All of these traits are imported by the prelude, so they are available in
16+
//! Some of these traits are imported by the prelude, so they are available in
2017
//! every Rust program.
2118
//!
19+
//! Many of the operators take their operands by value. In non-generic
20+
//! contexts involving built-in types, this is usually not a problem.
21+
//! However, using these operators in generic code, requires some
22+
//! attention if values have to be reused as opposed to letting the operators
23+
//! consume them. One option is to occasionally use `clone()`.
24+
//! Another option is to rely on the types involved providing additional
25+
//! operator implementations for references. For example, for a user-defined
26+
//! type `T` which is supposed to support addition, it is probably a good
27+
//! idea to have both `T` and `&T` implement the traits `Add<T>` and `Add<&T>`
28+
//! so that generic code can be written without unnecessary cloning.
29+
//!
2230
//! # Example
2331
//!
2432
//! This example creates a `Point` struct that implements `Add` and `Sub`, and then
@@ -96,6 +104,58 @@ pub trait Drop {
96104
fn drop(&mut self);
97105
}
98106

107+
// implements the unary operator "op &T"
108+
// based on "op T" where T is expected to be `Copy`able
109+
macro_rules! forward_ref_unop {
110+
(impl $imp:ident, $method:ident for $t:ty) => {
111+
#[unstable = "recently added, waiting for dust to settle"]
112+
impl<'a> $imp for &'a $t {
113+
type Output = <$t as $imp>::Output;
114+
115+
#[inline]
116+
fn $method(self) -> <$t as $imp>::Output {
117+
$imp::$method(*self)
118+
}
119+
}
120+
}
121+
}
122+
123+
// implements binary operators "&T op U", "T op &U", "&T op &U"
124+
// based on "T op U" where T and U are expected to be `Copy`able
125+
macro_rules! forward_ref_binop {
126+
(impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
127+
#[unstable = "recently added, waiting for dust to settle"]
128+
impl<'a> $imp<$u> for &'a $t {
129+
type Output = <$t as $imp<$u>>::Output;
130+
131+
#[inline]
132+
fn $method(self, other: $u) -> <$t as $imp<$u>>::Output {
133+
$imp::$method(*self, other)
134+
}
135+
}
136+
137+
#[unstable = "recently added, waiting for dust to settle"]
138+
impl<'a> $imp<&'a $u> for $t {
139+
type Output = <$t as $imp<$u>>::Output;
140+
141+
#[inline]
142+
fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
143+
$imp::$method(self, *other)
144+
}
145+
}
146+
147+
#[unstable = "recently added, waiting for dust to settle"]
148+
impl<'a, 'b> $imp<&'a $u> for &'b $t {
149+
type Output = <$t as $imp<$u>>::Output;
150+
151+
#[inline]
152+
fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
153+
$imp::$method(*self, *other)
154+
}
155+
}
156+
}
157+
}
158+
99159
/// The `Add` trait is used to specify the functionality of `+`.
100160
///
101161
/// # Example
@@ -144,6 +204,8 @@ macro_rules! add_impl {
144204
#[inline]
145205
fn add(self, other: $t) -> $t { self + other }
146206
}
207+
208+
forward_ref_binop! { impl Add, add for $t, $t }
147209
)*)
148210
}
149211

@@ -197,6 +259,8 @@ macro_rules! sub_impl {
197259
#[inline]
198260
fn sub(self, other: $t) -> $t { self - other }
199261
}
262+
263+
forward_ref_binop! { impl Sub, sub for $t, $t }
200264
)*)
201265
}
202266

@@ -250,6 +314,8 @@ macro_rules! mul_impl {
250314
#[inline]
251315
fn mul(self, other: $t) -> $t { self * other }
252316
}
317+
318+
forward_ref_binop! { impl Mul, mul for $t, $t }
253319
)*)
254320
}
255321

@@ -303,6 +369,8 @@ macro_rules! div_impl {
303369
#[inline]
304370
fn div(self, other: $t) -> $t { self / other }
305371
}
372+
373+
forward_ref_binop! { impl Div, div for $t, $t }
306374
)*)
307375
}
308376

@@ -356,6 +424,8 @@ macro_rules! rem_impl {
356424
#[inline]
357425
fn rem(self, other: $t) -> $t { self % other }
358426
}
427+
428+
forward_ref_binop! { impl Rem, rem for $t, $t }
359429
)*)
360430
}
361431

@@ -371,6 +441,8 @@ macro_rules! rem_float_impl {
371441
unsafe { $fmod(self, other) }
372442
}
373443
}
444+
445+
forward_ref_binop! { impl Rem, rem for $t, $t }
374446
}
375447
}
376448

@@ -429,6 +501,8 @@ macro_rules! neg_impl {
429501
#[stable]
430502
fn neg(self) -> $t { -self }
431503
}
504+
505+
forward_ref_unop! { impl Neg, neg for $t }
432506
)*)
433507
}
434508

@@ -441,6 +515,8 @@ macro_rules! neg_uint_impl {
441515
#[inline]
442516
fn neg(self) -> $t { -(self as $t_signed) as $t }
443517
}
518+
519+
forward_ref_unop! { impl Neg, neg for $t }
444520
}
445521
}
446522

@@ -502,6 +578,8 @@ macro_rules! not_impl {
502578
#[inline]
503579
fn not(self) -> $t { !self }
504580
}
581+
582+
forward_ref_unop! { impl Not, not for $t }
505583
)*)
506584
}
507585

@@ -555,6 +633,8 @@ macro_rules! bitand_impl {
555633
#[inline]
556634
fn bitand(self, rhs: $t) -> $t { self & rhs }
557635
}
636+
637+
forward_ref_binop! { impl BitAnd, bitand for $t, $t }
558638
)*)
559639
}
560640

@@ -608,6 +688,8 @@ macro_rules! bitor_impl {
608688
#[inline]
609689
fn bitor(self, rhs: $t) -> $t { self | rhs }
610690
}
691+
692+
forward_ref_binop! { impl BitOr, bitor for $t, $t }
611693
)*)
612694
}
613695

@@ -661,6 +743,8 @@ macro_rules! bitxor_impl {
661743
#[inline]
662744
fn bitxor(self, other: $t) -> $t { self ^ other }
663745
}
746+
747+
forward_ref_binop! { impl BitXor, bitxor for $t, $t }
664748
)*)
665749
}
666750

@@ -716,6 +800,8 @@ macro_rules! shl_impl {
716800
self << other
717801
}
718802
}
803+
804+
forward_ref_binop! { impl Shl, shl for $t, $f }
719805
)
720806
}
721807

@@ -786,6 +872,8 @@ macro_rules! shr_impl {
786872
self >> other
787873
}
788874
}
875+
876+
forward_ref_binop! { impl Shr, shr for $t, $f }
789877
)
790878
}
791879

0 commit comments

Comments
 (0)