auto merge of #19448 : japaric/rust/binops-by-value, r=nikomatsakis

- The following operator traits now take their arguments by value: `Add`, `Sub`, `Mul`, `Div`, `Rem`, `BitAnd`, `BitOr`, `BitXor`, `Shl`, `Shr`. This breaks all existing implementations of these traits.

- The binary operation `a OP b` now "desugars" to `OpTrait::op_method(a, b)` and consumes both arguments.

- `String` and `Vec` addition have been changed to reuse the LHS owned value, and to avoid internal cloning. Only the following asymmetric operations are available: `String + &str` and `Vec<T> + &[T]`, which are now a short-hand for the "append" operation.

[breaking-change]

---

This passes `make check` locally. I haven't touch the unary operators in this PR, but converting them to by value should be very similar to this PR. I can work on them after this gets the thumbs up.

@nikomatsakis r? the compiler changes
@aturon r? the library changes. I think the only controversial bit is the semantic change of the `Vec`/`String` `Add` implementation.
cc #19148
This commit is contained in:
bors 2014-12-15 22:11:44 +00:00
commit 0669a432a2
42 changed files with 1387 additions and 162 deletions

View File

@ -443,6 +443,8 @@ impl<T: Ord> Default for BTreeSet<T> {
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> Sub<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
/// Returns the difference of `self` and `rhs` as a new `BTreeSet<T>`.
///
@ -464,6 +466,30 @@ impl<T: Ord + Clone> Sub<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
/// Returns the difference of `self` and `rhs` as a new `BTreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<int> = vec![1, 2, 3].into_iter().collect();
/// let b: BTreeSet<int> = vec![3, 4, 5].into_iter().collect();
///
/// let result: BTreeSet<int> = &a - &b;
/// let result_vec: Vec<int> = result.into_iter().collect();
/// assert_eq!(result_vec, vec![1, 2]);
/// ```
fn sub(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
self.difference(rhs).cloned().collect()
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> BitXor<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
/// Returns the symmetric difference of `self` and `rhs` as a new `BTreeSet<T>`.
///
@ -485,6 +511,30 @@ impl<T: Ord + Clone> BitXor<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
/// Returns the symmetric difference of `self` and `rhs` as a new `BTreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<int> = vec![1, 2, 3].into_iter().collect();
/// let b: BTreeSet<int> = vec![2, 3, 4].into_iter().collect();
///
/// let result: BTreeSet<int> = &a ^ &b;
/// let result_vec: Vec<int> = result.into_iter().collect();
/// assert_eq!(result_vec, vec![1, 4]);
/// ```
fn bitxor(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
self.symmetric_difference(rhs).cloned().collect()
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> BitAnd<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
/// Returns the intersection of `self` and `rhs` as a new `BTreeSet<T>`.
///
@ -506,6 +556,30 @@ impl<T: Ord + Clone> BitAnd<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
/// Returns the intersection of `self` and `rhs` as a new `BTreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<int> = vec![1, 2, 3].into_iter().collect();
/// let b: BTreeSet<int> = vec![2, 3, 4].into_iter().collect();
///
/// let result: BTreeSet<int> = &a & &b;
/// let result_vec: Vec<int> = result.into_iter().collect();
/// assert_eq!(result_vec, vec![2, 3]);
/// ```
fn bitand(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
self.intersection(rhs).cloned().collect()
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> BitOr<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
/// Returns the union of `self` and `rhs` as a new `BTreeSet<T>`.
///
@ -526,6 +600,28 @@ impl<T: Ord + Clone> BitOr<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
/// Returns the union of `self` and `rhs` as a new `BTreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<int> = vec![1, 2, 3].into_iter().collect();
/// let b: BTreeSet<int> = vec![3, 4, 5].into_iter().collect();
///
/// let result: BTreeSet<int> = &a | &b;
/// let result_vec: Vec<int> = result.into_iter().collect();
/// assert_eq!(result_vec, vec![1, 2, 3, 4, 5]);
/// ```
fn bitor(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
self.union(rhs).cloned().collect()
}
}
impl<T: Show> Show for BTreeSet<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{{"));

View File

@ -183,30 +183,66 @@ impl<E:CLike> EnumSet<E> {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<E:CLike> Sub<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn sub(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits & !e.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<E:CLike> Sub<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn sub(self, e: EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits & !e.bits}
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
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}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
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}
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
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}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
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}
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<E:CLike> BitXor<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitxor(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits ^ e.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<E:CLike> BitXor<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitxor(self, e: EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits ^ e.bits}
}
}
/// An iterator over an EnumSet
pub struct Items<E> {
index: uint,

View File

@ -855,6 +855,8 @@ impl<'a, S: Str> Equiv<S> for String {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
#[experimental = "waiting on Add stabilization"]
impl<S: Str> Add<S, String> for String {
fn add(&self, other: &S) -> String {
@ -864,6 +866,22 @@ impl<S: Str> Add<S, String> for String {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a> Add<&'a str, String> for String {
fn add(mut self, other: &str) -> String {
self.push_str(other);
self
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a> Add<String, String> for &'a str {
fn add(self, mut other: String) -> String {
other.push_str(self);
other
}
}
impl ops::Slice<uint, str> for String {
#[inline]
fn as_slice_<'a>(&'a self) -> &'a str {
@ -1280,7 +1298,7 @@ mod tests {
fn test_str_add() {
let a = String::from_str("12345");
let b = a + "2";
let b = b + String::from_str("2");
let b = b + "2";
assert_eq!(b.len(), 7);
assert_eq!(b, "1234522");
}

View File

@ -668,6 +668,8 @@ impl<'a, T: Ord> Iterator<&'a T> for UnionItems<'a, T> {
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> BitOr<TreeSet<T>, TreeSet<T>> for TreeSet<T> {
/// Returns the union of `self` and `rhs` as a new `TreeSet<T>`.
///
@ -689,6 +691,30 @@ impl<T: Ord + Clone> BitOr<TreeSet<T>, TreeSet<T>> for TreeSet<T> {
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> BitOr<&'b TreeSet<T>, TreeSet<T>> for &'a TreeSet<T> {
/// Returns the union of `self` and `rhs` as a new `TreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::TreeSet;
///
/// let a: TreeSet<int> = vec![1, 2, 3].into_iter().collect();
/// let b: TreeSet<int> = vec![3, 4, 5].into_iter().collect();
///
/// let set: TreeSet<int> = &a | &b;
/// let v: Vec<int> = set.into_iter().collect();
/// assert_eq!(v, vec![1, 2, 3, 4, 5]);
/// ```
fn bitor(self, rhs: &TreeSet<T>) -> TreeSet<T> {
self.union(rhs).cloned().collect()
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> BitAnd<TreeSet<T>, TreeSet<T>> for TreeSet<T> {
/// Returns the intersection of `self` and `rhs` as a new `TreeSet<T>`.
///
@ -710,6 +736,30 @@ impl<T: Ord + Clone> BitAnd<TreeSet<T>, TreeSet<T>> for TreeSet<T> {
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> BitAnd<&'b TreeSet<T>, TreeSet<T>> for &'a TreeSet<T> {
/// Returns the intersection of `self` and `rhs` as a new `TreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::TreeSet;
///
/// let a: TreeSet<int> = vec![1, 2, 3].into_iter().collect();
/// let b: TreeSet<int> = vec![2, 3, 4].into_iter().collect();
///
/// let set: TreeSet<int> = &a & &b;
/// let v: Vec<int> = set.into_iter().collect();
/// assert_eq!(v, vec![2, 3]);
/// ```
fn bitand(self, rhs: &TreeSet<T>) -> TreeSet<T> {
self.intersection(rhs).cloned().collect()
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> BitXor<TreeSet<T>, TreeSet<T>> for TreeSet<T> {
/// Returns the symmetric difference of `self` and `rhs` as a new `TreeSet<T>`.
///
@ -731,6 +781,30 @@ impl<T: Ord + Clone> BitXor<TreeSet<T>, TreeSet<T>> for TreeSet<T> {
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> BitXor<&'b TreeSet<T>, TreeSet<T>> for &'a TreeSet<T> {
/// Returns the symmetric difference of `self` and `rhs` as a new `TreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::TreeSet;
///
/// let a: TreeSet<int> = vec![1, 2, 3].into_iter().collect();
/// let b: TreeSet<int> = vec![3, 4, 5].into_iter().collect();
///
/// let set: TreeSet<int> = &a ^ &b;
/// let v: Vec<int> = set.into_iter().collect();
/// assert_eq!(v, vec![1, 2, 4, 5]);
/// ```
fn bitxor(self, rhs: &TreeSet<T>) -> TreeSet<T> {
self.symmetric_difference(rhs).cloned().collect()
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> Sub<TreeSet<T>, TreeSet<T>> for TreeSet<T> {
/// Returns the difference of `self` and `rhs` as a new `TreeSet<T>`.
///
@ -751,6 +825,28 @@ impl<T: Ord + Clone> Sub<TreeSet<T>, TreeSet<T>> for TreeSet<T> {
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> Sub<&'b TreeSet<T>, TreeSet<T>> for &'a TreeSet<T> {
/// Returns the difference of `self` and `rhs` as a new `TreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::TreeSet;
///
/// let a: TreeSet<int> = vec![1, 2, 3].into_iter().collect();
/// let b: TreeSet<int> = vec![3, 4, 5].into_iter().collect();
///
/// let set: TreeSet<int> = &a - &b;
/// let v: Vec<int> = set.into_iter().collect();
/// assert_eq!(v, vec![1, 2]);
/// ```
fn sub(self, rhs: &TreeSet<T>) -> TreeSet<T> {
self.difference(rhs).cloned().collect()
}
}
impl<T: Ord> FromIterator<T> for TreeSet<T> {
fn from_iter<Iter: Iterator<T>>(iter: Iter) -> TreeSet<T> {
let mut set = TreeSet::new();
@ -1032,7 +1128,7 @@ mod test {
let a: TreeSet<int> = vec![1, 3, 5, 9, 11, 16, 19, 24].into_iter().collect();
let b: TreeSet<int> = vec![-2, 1, 5, 9, 13, 19].into_iter().collect();
let set: TreeSet<int> = a | b;
let set: TreeSet<int> = &a | &b;
let v: Vec<int> = set.into_iter().collect();
assert_eq!(v, vec![-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]);
}
@ -1042,7 +1138,7 @@ mod test {
let a: TreeSet<int> = vec![11, 1, 3, 77, 103, 5, -5].into_iter().collect();
let b: TreeSet<int> = vec![2, 11, 77, -9, -42, 5, 3].into_iter().collect();
let set: TreeSet<int> = a & b;
let set: TreeSet<int> = &a & &b;
let v: Vec<int> = set.into_iter().collect();
assert_eq!(v, vec![3, 5, 11, 77]);
}
@ -1052,7 +1148,7 @@ mod test {
let a: TreeSet<int> = vec![1, 3, 5, 9, 11].into_iter().collect();
let b: TreeSet<int> = vec![-2, 3, 9, 14, 22].into_iter().collect();
let set: TreeSet<int> = a ^ b;
let set: TreeSet<int> = &a ^ &b;
let v: Vec<int> = set.into_iter().collect();
assert_eq!(v, vec![-2, 1, 5, 11, 14, 22]);
}
@ -1062,7 +1158,7 @@ mod test {
let a: TreeSet<int> = vec![-5, 11, 22, 33, 40, 42].into_iter().collect();
let b: TreeSet<int> = vec![-12, -5, 14, 23, 34, 38, 39, 50].into_iter().collect();
let set: TreeSet<int> = a - b;
let set: TreeSet<int> = &a - &b;
let v: Vec<int> = set.into_iter().collect();
assert_eq!(v, vec![11, 22, 33, 40, 42]);
}

View File

@ -462,6 +462,8 @@ impl Extend<uint> for TrieSet {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
impl BitOr<TrieSet, TrieSet> for TrieSet {
/// Returns the union of `self` and `rhs` as a new `TrieSet`.
@ -483,6 +485,30 @@ impl BitOr<TrieSet, TrieSet> for TrieSet {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[unstable = "matches collection reform specification, waiting for dust to settle"]
impl<'a, 'b> BitOr<&'b TrieSet, TrieSet> for &'a TrieSet {
/// Returns the union of `self` and `rhs` as a new `TrieSet`.
///
/// # Example
///
/// ```
/// use std::collections::TrieSet;
///
/// let a: TrieSet = vec![1, 2, 3].into_iter().collect();
/// let b: TrieSet = vec![3, 4, 5].into_iter().collect();
///
/// let set: TrieSet = &a | &b;
/// let v: Vec<uint> = set.iter().collect();
/// assert_eq!(v, vec![1u, 2, 3, 4, 5]);
/// ```
fn bitor(self, rhs: &TrieSet) -> TrieSet {
self.union(rhs).collect()
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
impl BitAnd<TrieSet, TrieSet> for TrieSet {
/// Returns the intersection of `self` and `rhs` as a new `TrieSet`.
@ -504,6 +530,30 @@ impl BitAnd<TrieSet, TrieSet> for TrieSet {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[unstable = "matches collection reform specification, waiting for dust to settle"]
impl<'a, 'b> BitAnd<&'b TrieSet, TrieSet> for &'a TrieSet {
/// Returns the intersection of `self` and `rhs` as a new `TrieSet`.
///
/// # Example
///
/// ```
/// use std::collections::TrieSet;
///
/// let a: TrieSet = vec![1, 2, 3].into_iter().collect();
/// let b: TrieSet = vec![2, 3, 4].into_iter().collect();
///
/// let set: TrieSet = &a & &b;
/// let v: Vec<uint> = set.iter().collect();
/// assert_eq!(v, vec![2u, 3]);
/// ```
fn bitand(self, rhs: &TrieSet) -> TrieSet {
self.intersection(rhs).collect()
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
impl BitXor<TrieSet, TrieSet> for TrieSet {
/// Returns the symmetric difference of `self` and `rhs` as a new `TrieSet`.
@ -525,6 +575,30 @@ impl BitXor<TrieSet, TrieSet> for TrieSet {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[unstable = "matches collection reform specification, waiting for dust to settle"]
impl<'a, 'b> BitXor<&'b TrieSet, TrieSet> for &'a TrieSet {
/// Returns the symmetric difference of `self` and `rhs` as a new `TrieSet`.
///
/// # Example
///
/// ```
/// use std::collections::TrieSet;
///
/// let a: TrieSet = vec![1, 2, 3].into_iter().collect();
/// let b: TrieSet = vec![3, 4, 5].into_iter().collect();
///
/// let set: TrieSet = &a ^ &b;
/// let v: Vec<uint> = set.iter().collect();
/// assert_eq!(v, vec![1u, 2, 4, 5]);
/// ```
fn bitxor(self, rhs: &TrieSet) -> TrieSet {
self.symmetric_difference(rhs).collect()
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
impl Sub<TrieSet, TrieSet> for TrieSet {
/// Returns the difference of `self` and `rhs` as a new `TrieSet`.
@ -546,6 +620,28 @@ impl Sub<TrieSet, TrieSet> for TrieSet {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[unstable = "matches collection reform specification, waiting for dust to settle"]
impl<'a, 'b> Sub<&'b TrieSet, TrieSet> for &'a TrieSet {
/// Returns the difference of `self` and `rhs` as a new `TrieSet`.
///
/// # Example
///
/// ```
/// use std::collections::TrieSet;
///
/// let a: TrieSet = vec![1, 2, 3].into_iter().collect();
/// let b: TrieSet = vec![3, 4, 5].into_iter().collect();
///
/// let set: TrieSet = &a - &b;
/// let v: Vec<uint> = set.iter().collect();
/// assert_eq!(v, vec![1u, 2]);
/// ```
fn sub(self, rhs: &TrieSet) -> TrieSet {
self.difference(rhs).collect()
}
}
/// A forward iterator over a set.
pub struct SetItems<'a> {
iter: Entries<'a, ()>
@ -837,7 +933,7 @@ mod test {
let a: TrieSet = vec![1, 2, 3].into_iter().collect();
let b: TrieSet = vec![3, 4, 5].into_iter().collect();
let set: TrieSet = a | b;
let set: TrieSet = &a | &b;
let v: Vec<uint> = set.iter().collect();
assert_eq!(v, vec![1u, 2, 3, 4, 5]);
}
@ -847,7 +943,7 @@ mod test {
let a: TrieSet = vec![1, 2, 3].into_iter().collect();
let b: TrieSet = vec![2, 3, 4].into_iter().collect();
let set: TrieSet = a & b;
let set: TrieSet = &a & &b;
let v: Vec<uint> = set.iter().collect();
assert_eq!(v, vec![2u, 3]);
}
@ -857,7 +953,7 @@ mod test {
let a: TrieSet = vec![1, 2, 3].into_iter().collect();
let b: TrieSet = vec![3, 4, 5].into_iter().collect();
let set: TrieSet = a ^ b;
let set: TrieSet = &a ^ &b;
let v: Vec<uint> = set.iter().collect();
assert_eq!(v, vec![1u, 2, 4, 5]);
}
@ -867,7 +963,7 @@ mod test {
let a: TrieSet = vec![1, 2, 3].into_iter().collect();
let b: TrieSet = vec![3, 4, 5].into_iter().collect();
let set: TrieSet = a - b;
let set: TrieSet = &a - &b;
let v: Vec<uint> = set.iter().collect();
assert_eq!(v, vec![1u, 2]);
}

View File

@ -1273,6 +1273,8 @@ impl<T> AsSlice<T> for Vec<T> {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Clone, Sized? V: AsSlice<T>> Add<V, Vec<T>> for Vec<T> {
#[inline]
fn add(&self, rhs: &V) -> Vec<T> {
@ -1283,6 +1285,25 @@ impl<T: Clone, Sized? V: AsSlice<T>> Add<V, Vec<T>> for Vec<T> {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove impl after a snapshot
impl<'a, T: Clone> Add<&'a [T], Vec<T>> for Vec<T> {
#[inline]
fn add(mut self, rhs: &[T]) -> Vec<T> {
self.push_all(rhs);
self
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove impl after a snapshot
impl<'a, T: Clone> Add<Vec<T>, Vec<T>> for &'a [T] {
#[inline]
fn add(self, mut rhs: Vec<T>) -> Vec<T> {
rhs.push_all(self);
rhs
}
}
#[unsafe_destructor]
impl<T> Drop for Vec<T> {
fn drop(&mut self) {

View File

@ -2166,7 +2166,7 @@ impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> {
#[inline]
fn next(&mut self) -> Option<A> {
let result = self.state.clone();
self.state = self.state + self.step;
self.state = self.state.clone() + self.step.clone();
Some(result)
}

View File

@ -37,8 +37,8 @@ use str::{FromStr, from_str, StrPrelude};
/// Simultaneous division and remainder
#[inline]
#[deprecated = "use division and remainder directly"]
pub fn div_rem<T: Div<T, T> + Rem<T, T>>(x: T, y: T) -> (T, T) {
(x / y, x % y)
pub fn div_rem<T: Clone + Div<T, T> + Rem<T, T>>(x: T, y: T) -> (T, T) {
(x.clone() / y.clone(), x % y)
}
/// Raises a `base` to the power of `exp`, using exponentiation by squaring.

View File

@ -32,13 +32,13 @@
//! }
//!
//! impl Add<Point, Point> for Point {
//! fn add(&self, other: &Point) -> Point {
//! fn add(self, other: Point) -> Point {
//! Point {x: self.x + other.x, y: self.y + other.y}
//! }
//! }
//!
//! impl Sub<Point, Point> for Point {
//! fn sub(&self, other: &Point) -> Point {
//! fn sub(self, other: Point) -> Point {
//! Point {x: self.x - other.x, y: self.y - other.y}
//! }
//! }
@ -103,12 +103,16 @@ pub trait Drop {
/// Foo + Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="add"]
pub trait Add<Sized? RHS,Result> for Sized? {
/// The method for the `+` operator
fn add(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! add_impl(
($($t:ty)*) => ($(
impl Add<$t, $t> for $t {
@ -118,6 +122,44 @@ macro_rules! add_impl(
)*)
)
/// The `Add` trait is used to specify the functionality of `+`.
///
/// # Example
///
/// A trivial implementation of `Add`. When `Foo + Foo` happens, it ends up
/// calling `add`, and therefore, `main` prints `Adding!`.
///
/// ```rust
/// struct Foo;
///
/// impl Add<Foo, Foo> for Foo {
/// fn add(self, _rhs: Foo) -> Foo {
/// println!("Adding!");
/// self
/// }
/// }
///
/// fn main() {
/// Foo + Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="add"]
pub trait Add<RHS, Result> {
/// The method for the `+` operator
fn add(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! add_impl(
($($t:ty)*) => ($(
impl Add<$t, $t> for $t {
#[inline]
fn add(self, other: $t) -> $t { self + other }
}
)*)
)
add_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// The `Sub` trait is used to specify the functionality of `-`.
@ -143,12 +185,16 @@ add_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// Foo - Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="sub"]
pub trait Sub<Sized? RHS, Result> for Sized? {
/// The method for the `-` operator
fn sub(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! sub_impl(
($($t:ty)*) => ($(
impl Sub<$t, $t> for $t {
@ -158,6 +204,44 @@ macro_rules! sub_impl(
)*)
)
/// The `Sub` trait is used to specify the functionality of `-`.
///
/// # Example
///
/// A trivial implementation of `Sub`. When `Foo - Foo` happens, it ends up
/// calling `sub`, and therefore, `main` prints `Subtracting!`.
///
/// ```rust
/// struct Foo;
///
/// impl Sub<Foo, Foo> for Foo {
/// fn sub(self, _rhs: Foo) -> Foo {
/// println!("Subtracting!");
/// self
/// }
/// }
///
/// fn main() {
/// Foo - Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="sub"]
pub trait Sub<RHS, Result> {
/// The method for the `-` operator
fn sub(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! sub_impl(
($($t:ty)*) => ($(
impl Sub<$t, $t> for $t {
#[inline]
fn sub(self, other: $t) -> $t { self - other }
}
)*)
)
sub_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// The `Mul` trait is used to specify the functionality of `*`.
@ -183,12 +267,16 @@ sub_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// Foo * Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="mul"]
pub trait Mul<Sized? RHS, Result> for Sized? {
/// The method for the `*` operator
fn mul(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! mul_impl(
($($t:ty)*) => ($(
impl Mul<$t, $t> for $t {
@ -198,6 +286,44 @@ macro_rules! mul_impl(
)*)
)
/// The `Mul` trait is used to specify the functionality of `*`.
///
/// # Example
///
/// A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up
/// calling `mul`, and therefore, `main` prints `Multiplying!`.
///
/// ```rust
/// struct Foo;
///
/// impl Mul<Foo, Foo> for Foo {
/// fn mul(self, _rhs: Foo) -> Foo {
/// println!("Multiplying!");
/// self
/// }
/// }
///
/// fn main() {
/// Foo * Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="mul"]
pub trait Mul<RHS, Result> {
/// The method for the `*` operator
fn mul(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! mul_impl(
($($t:ty)*) => ($(
impl Mul<$t, $t> for $t {
#[inline]
fn mul(self, other: $t) -> $t { self * other }
}
)*)
)
mul_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// The `Div` trait is used to specify the functionality of `/`.
@ -223,12 +349,16 @@ mul_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// Foo / Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="div"]
pub trait Div<Sized? RHS, Result> for Sized? {
/// The method for the `/` operator
fn div(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! div_impl(
($($t:ty)*) => ($(
impl Div<$t, $t> for $t {
@ -238,6 +368,44 @@ macro_rules! div_impl(
)*)
)
/// The `Div` trait is used to specify the functionality of `/`.
///
/// # Example
///
/// A trivial implementation of `Div`. When `Foo / Foo` happens, it ends up
/// calling `div`, and therefore, `main` prints `Dividing!`.
///
/// ```
/// struct Foo;
///
/// impl Div<Foo, Foo> for Foo {
/// fn div(self, _rhs: Foo) -> Foo {
/// println!("Dividing!");
/// self
/// }
/// }
///
/// fn main() {
/// Foo / Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="div"]
pub trait Div<RHS, Result> {
/// The method for the `/` operator
fn div(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! div_impl(
($($t:ty)*) => ($(
impl Div<$t, $t> for $t {
#[inline]
fn div(self, other: $t) -> $t { self / other }
}
)*)
)
div_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// The `Rem` trait is used to specify the functionality of `%`.
@ -263,12 +431,16 @@ div_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// Foo % Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="rem"]
pub trait Rem<Sized? RHS, Result> for Sized? {
/// The method for the `%` operator
fn rem(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! rem_impl(
($($t:ty)*) => ($(
impl Rem<$t, $t> for $t {
@ -278,6 +450,8 @@ macro_rules! rem_impl(
)*)
)
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! rem_float_impl(
($t:ty, $fmod:ident) => {
impl Rem<$t, $t> for $t {
@ -290,6 +464,57 @@ macro_rules! rem_float_impl(
}
)
/// The `Rem` trait is used to specify the functionality of `%`.
///
/// # Example
///
/// A trivial implementation of `Rem`. When `Foo % Foo` happens, it ends up
/// calling `rem`, and therefore, `main` prints `Remainder-ing!`.
///
/// ```
/// struct Foo;
///
/// impl Rem<Foo, Foo> for Foo {
/// fn rem(self, _rhs: Foo) -> Foo {
/// println!("Remainder-ing!");
/// self
/// }
/// }
///
/// fn main() {
/// Foo % Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="rem"]
pub trait Rem<RHS, Result> {
/// The method for the `%` operator
fn rem(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! rem_impl(
($($t:ty)*) => ($(
impl Rem<$t, $t> for $t {
#[inline]
fn rem(self, other: $t) -> $t { self % other }
}
)*)
)
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! rem_float_impl(
($t:ty, $fmod:ident) => {
impl Rem<$t, $t> for $t {
#[inline]
fn rem(self, other: $t) -> $t {
extern { fn $fmod(a: $t, b: $t) -> $t; }
unsafe { $fmod(self, other) }
}
}
}
)
rem_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
rem_float_impl!(f32, fmodf)
rem_float_impl!(f64, fmod)
@ -414,12 +639,16 @@ not_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// Foo & Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="bitand"]
pub trait BitAnd<Sized? RHS, Result> for Sized? {
/// The method for the `&` operator
fn bitand(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! bitand_impl(
($($t:ty)*) => ($(
impl BitAnd<$t, $t> for $t {
@ -429,6 +658,44 @@ macro_rules! bitand_impl(
)*)
)
/// The `BitAnd` trait is used to specify the functionality of `&`.
///
/// # Example
///
/// A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up
/// calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`.
///
/// ```
/// struct Foo;
///
/// impl BitAnd<Foo, Foo> for Foo {
/// fn bitand(self, _rhs: Foo) -> Foo {
/// println!("Bitwise And-ing!");
/// self
/// }
/// }
///
/// fn main() {
/// Foo & Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="bitand"]
pub trait BitAnd<RHS, Result> {
/// The method for the `&` operator
fn bitand(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! bitand_impl(
($($t:ty)*) => ($(
impl BitAnd<$t, $t> for $t {
#[inline]
fn bitand(self, rhs: $t) -> $t { self & rhs }
}
)*)
)
bitand_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// The `BitOr` trait is used to specify the functionality of `|`.
@ -454,12 +721,16 @@ bitand_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// Foo | Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="bitor"]
pub trait BitOr<Sized? RHS, Result> for Sized? {
/// The method for the `|` operator
fn bitor(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! bitor_impl(
($($t:ty)*) => ($(
impl BitOr<$t,$t> for $t {
@ -469,6 +740,44 @@ macro_rules! bitor_impl(
)*)
)
/// The `BitOr` trait is used to specify the functionality of `|`.
///
/// # Example
///
/// A trivial implementation of `BitOr`. When `Foo | Foo` happens, it ends up
/// calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`.
///
/// ```
/// struct Foo;
///
/// impl BitOr<Foo, Foo> for Foo {
/// fn bitor(self, _rhs: Foo) -> Foo {
/// println!("Bitwise Or-ing!");
/// self
/// }
/// }
///
/// fn main() {
/// Foo | Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="bitor"]
pub trait BitOr<RHS, Result> {
/// The method for the `|` operator
fn bitor(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! bitor_impl(
($($t:ty)*) => ($(
impl BitOr<$t,$t> for $t {
#[inline]
fn bitor(self, rhs: $t) -> $t { self | rhs }
}
)*)
)
bitor_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// The `BitXor` trait is used to specify the functionality of `^`.
@ -494,12 +803,16 @@ bitor_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// Foo ^ Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="bitxor"]
pub trait BitXor<Sized? RHS, Result> for Sized? {
/// The method for the `^` operator
fn bitxor(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! bitxor_impl(
($($t:ty)*) => ($(
impl BitXor<$t, $t> for $t {
@ -509,6 +822,44 @@ macro_rules! bitxor_impl(
)*)
)
/// The `BitXor` trait is used to specify the functionality of `^`.
///
/// # Example
///
/// A trivial implementation of `BitXor`. When `Foo ^ Foo` happens, it ends up
/// calling `bitxor`, and therefore, `main` prints `Bitwise Xor-ing!`.
///
/// ```
/// struct Foo;
///
/// impl BitXor<Foo, Foo> for Foo {
/// fn bitxor(self, _rhs: Foo) -> Foo {
/// println!("Bitwise Xor-ing!");
/// self
/// }
/// }
///
/// fn main() {
/// Foo ^ Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="bitxor"]
pub trait BitXor<RHS, Result> {
/// The method for the `^` operator
fn bitxor(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! bitxor_impl(
($($t:ty)*) => ($(
impl BitXor<$t, $t> for $t {
#[inline]
fn bitxor(self, other: $t) -> $t { self ^ other }
}
)*)
)
bitxor_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// The `Shl` trait is used to specify the functionality of `<<`.
@ -534,12 +885,16 @@ bitxor_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// Foo << Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="shl"]
pub trait Shl<Sized? RHS, Result> for Sized? {
/// The method for the `<<` operator
fn shl(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! shl_impl(
($($t:ty)*) => ($(
impl Shl<uint, $t> for $t {
@ -551,6 +906,46 @@ macro_rules! shl_impl(
)*)
)
/// The `Shl` trait is used to specify the functionality of `<<`.
///
/// # Example
///
/// A trivial implementation of `Shl`. When `Foo << Foo` happens, it ends up
/// calling `shl`, and therefore, `main` prints `Shifting left!`.
///
/// ```
/// struct Foo;
///
/// impl Shl<Foo, Foo> for Foo {
/// fn shl(self, _rhs: Foo) -> Foo {
/// println!("Shifting left!");
/// self
/// }
/// }
///
/// fn main() {
/// Foo << Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="shl"]
pub trait Shl<RHS, Result> {
/// The method for the `<<` operator
fn shl(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! shl_impl(
($($t:ty)*) => ($(
impl Shl<uint, $t> for $t {
#[inline]
fn shl(self, other: uint) -> $t {
self << other
}
}
)*)
)
shl_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// The `Shr` trait is used to specify the functionality of `>>`.
@ -576,12 +971,16 @@ shl_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// Foo >> Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="shr"]
pub trait Shr<Sized? RHS, Result> for Sized? {
/// The method for the `>>` operator
fn shr(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! shr_impl(
($($t:ty)*) => ($(
impl Shr<uint, $t> for $t {
@ -591,6 +990,44 @@ macro_rules! shr_impl(
)*)
)
/// The `Shr` trait is used to specify the functionality of `>>`.
///
/// # Example
///
/// A trivial implementation of `Shr`. When `Foo >> Foo` happens, it ends up
/// calling `shr`, and therefore, `main` prints `Shifting right!`.
///
/// ```
/// struct Foo;
///
/// impl Shr<Foo, Foo> for Foo {
/// fn shr(self, _rhs: Foo) -> Foo {
/// println!("Shifting right!");
/// self
/// }
/// }
///
/// fn main() {
/// Foo >> Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="shr"]
pub trait Shr<RHS, Result> {
/// The method for the `>>` operator
fn shr(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! shr_impl(
($($t:ty)*) => ($(
impl Shr<uint, $t> for $t {
#[inline]
fn shr(self, other: uint) -> $t { self >> other }
}
)*)
)
shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
/// The `Index` trait is used to specify the functionality of indexing operations

View File

@ -64,11 +64,11 @@ mod tests {
#[test]
fn test_bitwise_operators() {
assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T)));
assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T)));
assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T)));
assert!(0b1110 as $T == (0b0111 as $T).shl(&1));
assert!(0b0111 as $T == (0b1110 as $T).shr(&1));
assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
assert!(0b1110 as $T == (0b0111 as $T).shl(1));
assert!(0b0111 as $T == (0b1110 as $T).shr(1));
assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not());
}

View File

@ -12,6 +12,7 @@ use core::cmp::PartialEq;
use core::fmt::Show;
use core::num::{NumCast, cast};
use core::ops::{Add, Sub, Mul, Div, Rem};
use core::kinds::Copy;
mod int_macros;
mod i8;
@ -32,18 +33,19 @@ pub fn test_num<T>(ten: T, two: T) where
+ Add<T, T> + Sub<T, T>
+ Mul<T, T> + Div<T, T>
+ Rem<T, T> + Show
+ Copy
{
assert_eq!(ten.add(&two), cast(12i).unwrap());
assert_eq!(ten.sub(&two), cast(8i).unwrap());
assert_eq!(ten.mul(&two), cast(20i).unwrap());
assert_eq!(ten.div(&two), cast(5i).unwrap());
assert_eq!(ten.rem(&two), cast(0i).unwrap());
assert_eq!(ten.add(two), cast(12i).unwrap());
assert_eq!(ten.sub(two), cast(8i).unwrap());
assert_eq!(ten.mul(two), cast(20i).unwrap());
assert_eq!(ten.div(two), cast(5i).unwrap());
assert_eq!(ten.rem(two), cast(0i).unwrap());
assert_eq!(ten.add(&two), ten + two);
assert_eq!(ten.sub(&two), ten - two);
assert_eq!(ten.mul(&two), ten * two);
assert_eq!(ten.div(&two), ten / two);
assert_eq!(ten.rem(&two), ten % two);
assert_eq!(ten.add(two), ten + two);
assert_eq!(ten.sub(two), ten - two);
assert_eq!(ten.mul(two), ten * two);
assert_eq!(ten.div(two), ten / two);
assert_eq!(ten.rem(two), ten % two);
}
#[cfg(test)]

View File

@ -31,11 +31,11 @@ mod tests {
#[test]
fn test_bitwise_operators() {
assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T)));
assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T)));
assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T)));
assert!(0b1110 as $T == (0b0111 as $T).shl(&1u));
assert!(0b0111 as $T == (0b1110 as $T).shr(&1u));
assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
assert!(0b1110 as $T == (0b0111 as $T).shl(1u));
assert!(0b0111 as $T == (0b1110 as $T).shr(1u));
assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not());
}

View File

@ -30,7 +30,7 @@ use middle::ty::{MethodStatic, MethodStaticUnboxedClosure};
use util::ppaux::Repr;
use std::kinds;
use syntax::ast;
use syntax::{ast, ast_util};
use syntax::ptr::P;
use syntax::codemap::Span;
@ -329,6 +329,12 @@ macro_rules! return_if_err(
)
)
/// Whether the elements of an overloaded operation are passed by value or by reference
enum PassArgs {
ByValue,
ByRef,
}
impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
pub fn new(delegate: &'d mut Delegate<'tcx>,
typer: &'t TYPER,
@ -438,7 +444,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
ast::ExprPath(..) => { }
ast::ExprUnary(ast::UnDeref, ref base) => { // *base
if !self.walk_overloaded_operator(expr, &**base, Vec::new()) {
if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
self.select_from_expr(&**base);
}
}
@ -452,7 +458,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
}
ast::ExprIndex(ref lhs, ref rhs) => { // lhs[rhs]
if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs]) {
if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs], PassArgs::ByRef) {
self.select_from_expr(&**lhs);
self.consume_expr(&**rhs);
}
@ -465,7 +471,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
(&None, &Some(ref e)) => vec![&**e],
(&None, &None) => Vec::new()
};
let overloaded = self.walk_overloaded_operator(expr, &**base, args);
let overloaded =
self.walk_overloaded_operator(expr, &**base, args, PassArgs::ByRef);
assert!(overloaded);
}
@ -570,13 +577,19 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
}
ast::ExprUnary(_, ref lhs) => {
if !self.walk_overloaded_operator(expr, &**lhs, Vec::new()) {
if !self.walk_overloaded_operator(expr, &**lhs, Vec::new(), PassArgs::ByRef) {
self.consume_expr(&**lhs);
}
}
ast::ExprBinary(_, ref lhs, ref rhs) => {
if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs]) {
ast::ExprBinary(op, ref lhs, ref rhs) => {
let pass_args = if ast_util::is_by_value_binop(op) {
PassArgs::ByValue
} else {
PassArgs::ByRef
};
if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs], pass_args) {
self.consume_expr(&**lhs);
self.consume_expr(&**rhs);
}
@ -910,13 +923,24 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
fn walk_overloaded_operator(&mut self,
expr: &ast::Expr,
receiver: &ast::Expr,
rhs: Vec<&ast::Expr>)
rhs: Vec<&ast::Expr>,
pass_args: PassArgs)
-> bool
{
if !self.typer.is_method_call(expr.id) {
return false;
}
match pass_args {
PassArgs::ByValue => {
self.consume_expr(receiver);
self.consume_expr(rhs[0]);
return true;
},
PassArgs::ByRef => {},
}
self.walk_expr(receiver);
// Arguments (but not receivers) to overloaded operator

View File

@ -2859,24 +2859,51 @@ impl TypeContents {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl ops::BitOr<TypeContents,TypeContents> for TypeContents {
fn bitor(&self, other: &TypeContents) -> TypeContents {
TypeContents {bits: self.bits | other.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl ops::BitOr<TypeContents,TypeContents> for TypeContents {
fn bitor(self, other: TypeContents) -> TypeContents {
TypeContents {bits: self.bits | other.bits}
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl ops::BitAnd<TypeContents,TypeContents> for TypeContents {
fn bitand(&self, other: &TypeContents) -> TypeContents {
TypeContents {bits: self.bits & other.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl ops::BitAnd<TypeContents, TypeContents> for TypeContents {
fn bitand(self, other: TypeContents) -> TypeContents {
TypeContents {bits: self.bits & other.bits}
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl ops::Sub<TypeContents,TypeContents> for TypeContents {
fn sub(&self, other: &TypeContents) -> TypeContents {
TypeContents {bits: self.bits & !other.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl ops::Sub<TypeContents, TypeContents> for TypeContents {
fn sub(self, other: TypeContents) -> TypeContents {
TypeContents {bits: self.bits & !other.bits}
}
}
impl fmt::Show for TypeContents {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "TypeContents({:b})", self.bits)

View File

@ -848,10 +848,11 @@ pub enum CallArgs<'a, 'tcx> {
// value.
ArgVals(&'a [ValueRef]),
// For overloaded operators: `(lhs, Vec(rhs, rhs_id))`. `lhs`
// For overloaded operators: `(lhs, Vec(rhs, rhs_id), autoref)`. `lhs`
// is the left-hand-side and `rhs/rhs_id` is the datum/expr-id of
// the right-hand-side arguments (if any).
ArgOverloadedOp(Datum<'tcx, Expr>, Vec<(Datum<'tcx, Expr>, ast::NodeId)>),
// the right-hand-side arguments (if any). `autoref` indicates whether the `rhs`
// arguments should be auto-referenced
ArgOverloadedOp(Datum<'tcx, Expr>, Vec<(Datum<'tcx, Expr>, ast::NodeId)>, bool),
// Supply value of arguments as a list of expressions that must be
// translated, for overloaded call operators.
@ -1023,7 +1024,7 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
arg_cleanup_scope,
ignore_self)
}
ArgOverloadedOp(lhs, rhs) => {
ArgOverloadedOp(lhs, rhs, autoref) => {
assert!(!variadic);
llargs.push(unpack_result!(bcx, {
@ -1037,7 +1038,7 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
llargs.push(unpack_result!(bcx, {
trans_arg_datum(bcx, arg_tys[1], rhs,
arg_cleanup_scope,
DoAutorefArg(rhs_id))
if autoref { DoAutorefArg(rhs_id) } else { DontAutorefArg })
}));
}
}

View File

@ -609,7 +609,8 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
method_call,
base_datum,
args,
Some(SaveIn(scratch.val))));
Some(SaveIn(scratch.val)),
true));
DatumBlock::new(bcx, scratch.to_expr_datum())
}
ast::ExprBox(_, ref contents) => {
@ -762,7 +763,8 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
method_call,
base_datum,
vec![(ix_datum, idx.id)],
Some(SaveIn(scratch.val))));
Some(SaveIn(scratch.val)),
true));
let datum = scratch.to_expr_datum();
if ty::type_is_sized(bcx.tcx(), elt_ty) {
Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr)
@ -1091,25 +1093,26 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
callee::ArgExprs(args.as_slice()),
dest)
}
ast::ExprBinary(_, ref lhs, ref rhs) => {
ast::ExprBinary(op, ref lhs, ref rhs) => {
// if not overloaded, would be RvalueDatumExpr
let lhs = unpack_datum!(bcx, trans(bcx, &**lhs));
let rhs_datum = unpack_datum!(bcx, trans(bcx, &**rhs));
trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), lhs,
vec![(rhs_datum, rhs.id)], Some(dest)).bcx
vec![(rhs_datum, rhs.id)], Some(dest),
!ast_util::is_by_value_binop(op)).bcx
}
ast::ExprUnary(_, ref subexpr) => {
// if not overloaded, would be RvalueDatumExpr
let arg = unpack_datum!(bcx, trans(bcx, &**subexpr));
trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id),
arg, Vec::new(), Some(dest)).bcx
arg, Vec::new(), Some(dest), true).bcx
}
ast::ExprIndex(ref base, ref idx) => {
// if not overloaded, would be RvalueDatumExpr
let base = unpack_datum!(bcx, trans(bcx, &**base));
let idx_datum = unpack_datum!(bcx, trans(bcx, &**idx));
trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), base,
vec![(idx_datum, idx.id)], Some(dest)).bcx
vec![(idx_datum, idx.id)], Some(dest), true).bcx
}
ast::ExprCast(ref val, _) => {
// DPS output mode means this is a trait cast:
@ -1802,7 +1805,8 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
method_call: MethodCall,
lhs: Datum<'tcx, Expr>,
rhs: Vec<(Datum<'tcx, Expr>, ast::NodeId)>,
dest: Option<Dest>)
dest: Option<Dest>,
autoref: bool)
-> Result<'blk, 'tcx> {
let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty;
callee::trans_call_inner(bcx,
@ -1814,7 +1818,7 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
None,
arg_cleanup_scope)
},
callee::ArgOverloadedOp(lhs, rhs),
callee::ArgOverloadedOp(lhs, rhs, autoref),
dest)
}
@ -2121,7 +2125,8 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let scratch = rvalue_scratch_datum(bcx, ref_ty, "overloaded_deref");
unpack_result!(bcx, trans_overloaded_op(bcx, expr, method_call,
datum, Vec::new(), Some(SaveIn(scratch.val))));
datum, Vec::new(), Some(SaveIn(scratch.val)),
false));
scratch.to_expr_datum()
}
None => {

View File

@ -77,7 +77,6 @@ type parameter).
*/
pub use self::LvaluePreference::*;
pub use self::DerefArgs::*;
pub use self::Expectation::*;
use self::IsBinopAssignment::*;
use self::TupleArgumentsFlag::*;
@ -2115,7 +2114,7 @@ fn try_overloaded_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
method_callee.ty,
call_expression,
args,
DontDerefArgs,
AutorefArgs::No,
TupleArguments);
fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
write_call(fcx, call_expression, output_type);
@ -2264,7 +2263,7 @@ fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
method_ty_or_err,
expr,
args.as_slice(),
DoDerefArgs,
AutorefArgs::Yes,
DontTupleArguments);
opt_method_ty.map(|method_ty| {
@ -2470,7 +2469,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
method_type,
iterator_expr,
&[],
DontDerefArgs,
AutorefArgs::No,
DontTupleArguments);
match method {
@ -2512,7 +2511,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
method_fn_ty: Ty<'tcx>,
callee_expr: &ast::Expr,
args_no_rcvr: &[&P<ast::Expr>],
deref_args: DerefArgs,
autoref_args: AutorefArgs,
tuple_arguments: TupleArgumentsFlag)
-> ty::FnOutput<'tcx> {
if ty::type_is_error(method_fn_ty) {
@ -2528,7 +2527,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
err_inputs.as_slice(),
callee_expr,
args_no_rcvr,
deref_args,
autoref_args,
false,
tuple_arguments);
ty::FnConverging(ty::mk_err())
@ -2541,7 +2540,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
fty.sig.inputs.slice_from(1),
callee_expr,
args_no_rcvr,
deref_args,
autoref_args,
fty.sig.variadic,
tuple_arguments);
fty.sig.output
@ -2561,7 +2560,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
fn_inputs: &[Ty<'tcx>],
_callee_expr: &ast::Expr,
args: &[&P<ast::Expr>],
deref_args: DerefArgs,
autoref_args: AutorefArgs,
variadic: bool,
tuple_arguments: TupleArgumentsFlag) {
let tcx = fcx.ccx.tcx;
@ -2664,8 +2663,8 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
debug!("checking the argument");
let mut formal_ty = formal_tys[i];
match deref_args {
DoDerefArgs => {
match autoref_args {
AutorefArgs::Yes => {
match formal_ty.sty {
ty::ty_rptr(_, mt) => formal_ty = mt.ty,
ty::ty_err => (),
@ -2680,7 +2679,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
}
}
DontDerefArgs => {}
AutorefArgs::No => {}
}
check_expr_coercable_to_type(fcx, &***arg, formal_ty);
@ -2894,12 +2893,13 @@ pub fn lookup_tup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
// Controls whether the arguments are automatically referenced. This is useful
// for overloaded binary and unary operators.
pub enum DerefArgs {
DontDerefArgs,
DoDerefArgs
#[deriving(PartialEq)]
pub enum AutorefArgs {
Yes,
No,
}
impl Copy for DerefArgs {}
impl Copy for AutorefArgs {}
/// Controls whether the arguments are tupled. This is used for the call
/// operator.
@ -2987,7 +2987,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
fn_sig.inputs.as_slice(),
f,
args,
DontDerefArgs,
AutorefArgs::No,
fn_sig.variadic,
DontTupleArguments);
@ -3037,7 +3037,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
fn_ty,
expr,
args.as_slice(),
DontDerefArgs,
AutorefArgs::No,
DontTupleArguments);
write_call(fcx, expr, ret_ty);
@ -3120,7 +3120,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
trait_did: Option<ast::DefId>,
lhs: &'a ast::Expr,
rhs: Option<&P<ast::Expr>>,
unbound_method: F) -> Ty<'tcx> where
unbound_method: F,
autoref_args: AutorefArgs) -> Ty<'tcx> where
F: FnOnce(),
{
let method = match trait_did {
@ -3173,7 +3174,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
method_ty,
op_ex,
args.as_slice(),
DoDerefArgs,
autoref_args,
DontTupleArguments) {
ty::FnConverging(result_type) => result_type,
ty::FnDiverging => ty::mk_err()
@ -3189,7 +3190,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
expected_ty,
op_ex,
args.as_slice(),
DoDerefArgs,
autoref_args,
DontTupleArguments);
ty::mk_err()
}
@ -3337,7 +3338,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
ast_util::binop_to_string(op),
actual)
}, lhs_resolved_t, None)
})
}, if ast_util::is_by_value_binop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
}
fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
@ -3353,7 +3354,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
format!("cannot apply unary operator `{}` to type `{}`",
op_str, actual)
}, rhs_t, None);
})
}, AutorefArgs::Yes)
}
// Check field access expressions

View File

@ -131,7 +131,7 @@ use middle::pat_util;
use util::nodemap::{DefIdMap, NodeMap, FnvHashMap};
use util::ppaux::{ty_to_string, Repr};
use syntax::ast;
use syntax::{ast, ast_util};
use syntax::codemap::Span;
use syntax::visit;
use syntax::visit::Visitor;
@ -637,14 +637,22 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
visit::walk_expr(rcx, expr);
}
ast::ExprIndex(ref lhs, ref rhs) |
ast::ExprBinary(_, ref lhs, ref rhs) if has_method_map => {
ast::ExprIndex(ref lhs, ref rhs) if has_method_map => {
constrain_call(rcx, expr, Some(&**lhs),
Some(&**rhs).into_iter(), true);
visit::walk_expr(rcx, expr);
},
ast::ExprBinary(op, ref lhs, ref rhs) if has_method_map => {
let implicitly_ref_args = !ast_util::is_by_value_binop(op);
// As `expr_method_call`, but the call is via an
// overloaded op. Note that we (sadly) currently use an
// implicit "by ref" sort of passing style here. This
// should be converted to an adjustment!
constrain_call(rcx, expr, Some(&**lhs),
Some(&**rhs).into_iter(), true);
Some(&**rhs).into_iter(), implicitly_ref_args);
visit::walk_expr(rcx, expr);
}

View File

@ -42,7 +42,7 @@ pub struct Counts {
impl Copy for Counts {}
impl Add<Counts, Counts> for Counts {
fn add(&self, other: &Counts) -> Counts {
fn add(self, other: Counts) -> Counts {
Counts {
deprecated: self.deprecated + other.deprecated,
experimental: self.experimental + other.experimental,

View File

@ -205,6 +205,8 @@ macro_rules! bitflags {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the union of the two sets of flags.
#[inline]
@ -213,6 +215,17 @@ macro_rules! bitflags {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the union of the two sets of flags.
#[inline]
fn bitor(self, other: $BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits | other.bits }
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl BitXor<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the left flags, but with all the right flags toggled.
#[inline]
@ -221,6 +234,17 @@ macro_rules! bitflags {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl BitXor<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the left flags, but with all the right flags toggled.
#[inline]
fn bitxor(self, other: $BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits ^ other.bits }
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the intersection between the two sets of flags.
#[inline]
@ -229,6 +253,17 @@ macro_rules! bitflags {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the intersection between the two sets of flags.
#[inline]
fn bitand(self, other: $BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits & other.bits }
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Sub<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the set difference of the two sets of flags.
#[inline]
@ -237,6 +272,15 @@ macro_rules! bitflags {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Sub<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the set difference of the two sets of flags.
#[inline]
fn sub(self, other: $BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits & !other.bits }
}
}
impl Not<$BitFlags> for $BitFlags {
/// Returns the complement of this set of flags.
#[inline]

View File

@ -19,6 +19,7 @@
#[cfg(test)] use cmp::PartialEq;
#[cfg(test)] use fmt::Show;
#[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem};
#[cfg(test)] use kinds::Copy;
pub use core::num::{Num, div_rem, Zero, zero, One, one};
pub use core::num::{Unsigned, pow, Bounded};
@ -130,18 +131,19 @@ pub fn test_num<T>(ten: T, two: T) where
+ Add<T, T> + Sub<T, T>
+ Mul<T, T> + Div<T, T>
+ Rem<T, T> + Show
+ Copy
{
assert_eq!(ten.add(&two), cast(12i).unwrap());
assert_eq!(ten.sub(&two), cast(8i).unwrap());
assert_eq!(ten.mul(&two), cast(20i).unwrap());
assert_eq!(ten.div(&two), cast(5i).unwrap());
assert_eq!(ten.rem(&two), cast(0i).unwrap());
assert_eq!(ten.add(two), cast(12i).unwrap());
assert_eq!(ten.sub(two), cast(8i).unwrap());
assert_eq!(ten.mul(two), cast(20i).unwrap());
assert_eq!(ten.div(two), cast(5i).unwrap());
assert_eq!(ten.rem(two), cast(0i).unwrap());
assert_eq!(ten.add(&two), ten + two);
assert_eq!(ten.sub(&two), ten - two);
assert_eq!(ten.mul(&two), ten * two);
assert_eq!(ten.div(&two), ten / two);
assert_eq!(ten.rem(&two), ten % two);
assert_eq!(ten.add(two), ten + two);
assert_eq!(ten.sub(two), ten - two);
assert_eq!(ten.mul(two), ten * two);
assert_eq!(ten.div(two), ten / two);
assert_eq!(ten.rem(two), ten % two);
}
#[cfg(test)]

View File

@ -276,6 +276,8 @@ impl Neg<Duration> for Duration {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Add<Duration,Duration> for Duration {
fn add(&self, rhs: &Duration) -> Duration {
let mut secs = self.secs + rhs.secs;
@ -288,6 +290,21 @@ impl Add<Duration,Duration> for Duration {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Add<Duration, Duration> for Duration {
fn add(self, rhs: Duration) -> Duration {
let mut secs = self.secs + rhs.secs;
let mut nanos = self.nanos + rhs.nanos;
if nanos >= NANOS_PER_SEC {
nanos -= NANOS_PER_SEC;
secs += 1;
}
Duration { secs: secs, nanos: nanos }
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Sub<Duration,Duration> for Duration {
fn sub(&self, rhs: &Duration) -> Duration {
let mut secs = self.secs - rhs.secs;
@ -300,6 +317,21 @@ impl Sub<Duration,Duration> for Duration {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Sub<Duration, Duration> for Duration {
fn sub(self, rhs: Duration) -> Duration {
let mut secs = self.secs - rhs.secs;
let mut nanos = self.nanos - rhs.nanos;
if nanos < 0 {
nanos += NANOS_PER_SEC;
secs -= 1;
}
Duration { secs: secs, nanos: nanos }
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Mul<i32,Duration> for Duration {
fn mul(&self, rhs: &i32) -> Duration {
// Multiply nanoseconds as i64, because it cannot overflow that way.
@ -310,6 +342,19 @@ impl Mul<i32,Duration> for Duration {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Mul<i32, Duration> for Duration {
fn mul(self, rhs: i32) -> Duration {
// Multiply nanoseconds as i64, because it cannot overflow that way.
let total_nanos = self.nanos as i64 * rhs as i64;
let (extra_secs, nanos) = div_mod_floor_64(total_nanos, NANOS_PER_SEC as i64);
let secs = self.secs * rhs as i64 + extra_secs;
Duration { secs: secs, nanos: nanos as i32 }
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Div<i32,Duration> for Duration {
fn div(&self, rhs: &i32) -> Duration {
let mut secs = self.secs / *rhs as i64;
@ -328,6 +373,25 @@ impl Div<i32,Duration> for Duration {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Div<i32, Duration> for Duration {
fn div(self, rhs: i32) -> Duration {
let mut secs = self.secs / rhs as i64;
let carry = self.secs - secs * rhs as i64;
let extra_nanos = carry * NANOS_PER_SEC as i64 / rhs as i64;
let mut nanos = self.nanos / rhs + extra_nanos as i32;
if nanos >= NANOS_PER_SEC {
nanos -= NANOS_PER_SEC;
secs += 1;
}
if nanos < 0 {
nanos += NANOS_PER_SEC;
secs -= 1;
}
Duration { secs: secs, nanos: nanos }
}
}
impl fmt::Show for Duration {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// technically speaking, negative duration is not valid ISO 8601,

View File

@ -85,6 +85,16 @@ pub fn is_shift_binop(b: BinOp) -> bool {
}
}
/// Returns `true` is the binary operator takes its arguments by value
pub fn is_by_value_binop(b: BinOp) -> bool {
match b {
BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => {
true
}
_ => false
}
}
pub fn unop_to_string(op: UnOp) -> &'static str {
match op {
UnUniq => "box() ",

View File

@ -52,35 +52,71 @@ impl Pos for BytePos {
fn to_uint(&self) -> uint { let BytePos(n) = *self; n as uint }
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Add<BytePos, BytePos> for BytePos {
fn add(&self, rhs: &BytePos) -> BytePos {
BytePos((self.to_uint() + rhs.to_uint()) as u32)
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Add<BytePos, BytePos> for BytePos {
fn add(self, rhs: BytePos) -> BytePos {
BytePos((self.to_uint() + rhs.to_uint()) as u32)
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Sub<BytePos, BytePos> for BytePos {
fn sub(&self, rhs: &BytePos) -> BytePos {
BytePos((self.to_uint() - rhs.to_uint()) as u32)
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Sub<BytePos, BytePos> for BytePos {
fn sub(self, rhs: BytePos) -> BytePos {
BytePos((self.to_uint() - rhs.to_uint()) as u32)
}
}
impl Pos for CharPos {
fn from_uint(n: uint) -> CharPos { CharPos(n) }
fn to_uint(&self) -> uint { let CharPos(n) = *self; n }
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Add<CharPos,CharPos> for CharPos {
fn add(&self, rhs: &CharPos) -> CharPos {
CharPos(self.to_uint() + rhs.to_uint())
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Add<CharPos, CharPos> for CharPos {
fn add(self, rhs: CharPos) -> CharPos {
CharPos(self.to_uint() + rhs.to_uint())
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Sub<CharPos,CharPos> for CharPos {
fn sub(&self, rhs: &CharPos) -> CharPos {
CharPos(self.to_uint() - rhs.to_uint())
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Sub<CharPos, CharPos> for CharPos {
fn sub(self, rhs: CharPos) -> CharPos {
CharPos(self.to_uint() - rhs.to_uint())
}
}
/// Spans represent a region of code, used for error reporting. Positions in spans
/// are *absolute* positions from the beginning of the codemap, not positions
/// relative to FileMaps. Methods on the CodeMap can be used to relate spans back

View File

@ -106,6 +106,8 @@ enum LockstepIterSize {
LisContradiction(String),
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Add<LockstepIterSize, LockstepIterSize> for LockstepIterSize {
fn add(&self, other: &LockstepIterSize) -> LockstepIterSize {
match *self {
@ -127,6 +129,28 @@ impl Add<LockstepIterSize, LockstepIterSize> for LockstepIterSize {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Add<LockstepIterSize, LockstepIterSize> for LockstepIterSize {
fn add(self, other: LockstepIterSize) -> LockstepIterSize {
match self {
LisUnconstrained => other,
LisContradiction(_) => self,
LisConstraint(l_len, ref l_id) => match other {
LisUnconstrained => self.clone(),
LisContradiction(_) => other,
LisConstraint(r_len, _) if l_len == r_len => self.clone(),
LisConstraint(r_len, r_id) => {
let l_n = token::get_ident(l_id.clone());
let r_n = token::get_ident(r_id);
LisContradiction(format!("inconsistent lockstep iteration: \
'{}' has {} items, but '{}' has {}",
l_n, l_len, r_n, r_len).to_string())
}
},
}
}
}
fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize {
match *t {
TtDelimited(_, ref delimed) => {

View File

@ -99,6 +99,8 @@ impl Timespec {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Add<Duration, Timespec> for Timespec {
fn add(&self, other: &Duration) -> Timespec {
let d_sec = other.num_seconds();
@ -119,6 +121,29 @@ impl Add<Duration, Timespec> for Timespec {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Add<Duration, Timespec> for Timespec {
fn add(self, other: Duration) -> Timespec {
let d_sec = other.num_seconds();
// It is safe to unwrap the nanoseconds, because there cannot be
// more than one second left, which fits in i64 and in i32.
let d_nsec = (other - Duration::seconds(d_sec))
.num_nanoseconds().unwrap() as i32;
let mut sec = self.sec + d_sec;
let mut nsec = self.nsec + d_nsec;
if nsec >= NSEC_PER_SEC {
nsec -= NSEC_PER_SEC;
sec += 1;
} else if nsec < 0 {
nsec += NSEC_PER_SEC;
sec -= 1;
}
Timespec::new(sec, nsec)
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Sub<Timespec, Duration> for Timespec {
fn sub(&self, other: &Timespec) -> Duration {
let sec = self.sec - other.sec;
@ -127,6 +152,15 @@ impl Sub<Timespec, Duration> for Timespec {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Sub<Timespec, Duration> for Timespec {
fn sub(self, other: Timespec) -> Duration {
let sec = self.sec - other.sec;
let nsec = self.nsec - other.nsec;
Duration::seconds(sec) + Duration::nanoseconds(nsec as i64)
}
}
/// Returns the current time as a `timespec` containing the seconds and
/// nanoseconds since 1970-01-01T00:00:00Z.
pub fn get_time() -> Timespec {

View File

@ -10,24 +10,24 @@
use std::cmp::PartialEq;
pub trait MyNum : Add<Self,Self> + Sub<Self,Self> + Mul<Self,Self> + PartialEq {
pub trait MyNum : Add<Self,Self> + Sub<Self,Self> + Mul<Self,Self> + PartialEq + Clone {
}
#[deriving(Show)]
#[deriving(Clone, Show)]
pub struct MyInt {
pub val: int
}
impl Add<MyInt, MyInt> for MyInt {
fn add(&self, other: &MyInt) -> MyInt { mi(self.val + other.val) }
fn add(self, other: MyInt) -> MyInt { mi(self.val + other.val) }
}
impl Sub<MyInt, MyInt> for MyInt {
fn sub(&self, other: &MyInt) -> MyInt { mi(self.val - other.val) }
fn sub(self, other: MyInt) -> MyInt { mi(self.val - other.val) }
}
impl Mul<MyInt, MyInt> for MyInt {
fn mul(&self, other: &MyInt) -> MyInt { mi(self.val * other.val) }
fn mul(self, other: MyInt) -> MyInt { mi(self.val * other.val) }
}
impl PartialEq for MyInt {

View File

@ -0,0 +1,73 @@
// Copyright 2014 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.
// Test that binary operators consume their arguments
fn add<A: Add<B, ()>, B>(lhs: A, rhs: B) {
lhs + rhs;
drop(lhs); //~ ERROR use of moved value: `lhs`
drop(rhs); //~ ERROR use of moved value: `rhs`
}
fn sub<A: Sub<B, ()>, B>(lhs: A, rhs: B) {
lhs - rhs;
drop(lhs); //~ ERROR use of moved value: `lhs`
drop(rhs); //~ ERROR use of moved value: `rhs`
}
fn mul<A: Mul<B, ()>, B>(lhs: A, rhs: B) {
lhs * rhs;
drop(lhs); //~ ERROR use of moved value: `lhs`
drop(rhs); //~ ERROR use of moved value: `rhs`
}
fn div<A: Div<B, ()>, B>(lhs: A, rhs: B) {
lhs / rhs;
drop(lhs); //~ ERROR use of moved value: `lhs`
drop(rhs); //~ ERROR use of moved value: `rhs`
}
fn rem<A: Rem<B, ()>, B>(lhs: A, rhs: B) {
lhs % rhs;
drop(lhs); //~ ERROR use of moved value: `lhs`
drop(rhs); //~ ERROR use of moved value: `rhs`
}
fn bitand<A: BitAnd<B, ()>, B>(lhs: A, rhs: B) {
lhs & rhs;
drop(lhs); //~ ERROR use of moved value: `lhs`
drop(rhs); //~ ERROR use of moved value: `rhs`
}
fn bitor<A: BitOr<B, ()>, B>(lhs: A, rhs: B) {
lhs | rhs;
drop(lhs); //~ ERROR use of moved value: `lhs`
drop(rhs); //~ ERROR use of moved value: `rhs`
}
fn bitxor<A: BitXor<B, ()>, B>(lhs: A, rhs: B) {
lhs ^ rhs;
drop(lhs); //~ ERROR use of moved value: `lhs`
drop(rhs); //~ ERROR use of moved value: `rhs`
}
fn shl<A: Shl<B, ()>, B>(lhs: A, rhs: B) {
lhs << rhs;
drop(lhs); //~ ERROR use of moved value: `lhs`
drop(rhs); //~ ERROR use of moved value: `rhs`
}
fn shr<A: Shr<B, ()>, B>(lhs: A, rhs: B) {
lhs >> rhs;
drop(lhs); //~ ERROR use of moved value: `lhs`
drop(rhs); //~ ERROR use of moved value: `rhs`
}
fn main() {}

View File

@ -0,0 +1,69 @@
// Copyright 2014 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.
// Test that move restrictions are enforced on overloaded binary operations
fn double_move<T: Add<T, ()>>(x: T) {
x
+
x; //~ ERROR: use of moved value
}
fn move_then_borrow<T: Add<T, ()> + Clone>(x: T) {
x
+
x.clone(); //~ ERROR: use of moved value
}
fn move_borrowed<T: Add<T, ()>>(x: T, mut y: T) {
let m = &x;
let n = &mut y;
x //~ ERROR: cannot move out of `x` because it is borrowed
+
y; //~ ERROR: cannot move out of `y` because it is borrowed
}
fn illegal_dereference<T: Add<T, ()>>(mut x: T, y: T) {
let m = &mut x;
let n = &y;
*m //~ ERROR: cannot move out of dereference of `&mut`-pointer
+
*n; //~ ERROR: cannot move out of dereference of `&`-pointer
}
struct Foo;
impl<'a, 'b> Add<&'b Foo, ()> for &'a mut Foo {
fn add(self, _: &Foo) {}
}
impl<'a, 'b> Add<&'b mut Foo, ()> for &'a Foo {
fn add(self, _: &mut Foo) {}
}
fn mut_plus_immut() {
let mut f = Foo;
&mut f
+
&f; //~ ERROR: cannot borrow `f` as immutable because it is also borrowed as mutable
}
fn immut_plus_mut() {
let mut f = Foo;
&f
+
&mut f; //~ ERROR: cannot borrow `f` as mutable because it is also borrowed as immutable
}
fn main() {}

View File

@ -9,18 +9,19 @@
// except according to those terms.
#[deriving(Clone)]
struct foo(Box<uint>);
impl Add<foo, foo> for foo {
fn add(&self, f: &foo) -> foo {
let foo(box i) = *self;
let foo(box j) = *f;
fn add(self, f: foo) -> foo {
let foo(box i) = self;
let foo(box j) = f;
foo(box() (i + j))
}
}
fn main() {
let x = foo(box 3);
let _y = x + {x}; // the `{x}` forces a move to occur
//~^ ERROR cannot move out of `x`
let _y = {x} + x.clone(); // the `{x}` forces a move to occur
//~^ ERROR use of moved value: `x`
}

View File

@ -8,15 +8,15 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deriving(Copy)]
struct Point {
x: int,
y: int,
}
impl Add<int,int> for Point {
fn add(&self, z: &int) -> int {
self.x + self.y + (*z)
impl Add<int, int> for Point {
fn add(self, z: int) -> int {
self.x + self.y + z
}
}
@ -41,7 +41,7 @@ fn b() {
let q = &mut p;
p + 3; //~ ERROR cannot borrow `p`
p + 3; //~ ERROR cannot use `p`
p.times(3); //~ ERROR cannot borrow `p`
*q + 3; // OK to use the new alias `q`

View File

@ -17,12 +17,12 @@ struct Vec1 {
x: f64
}
// Expecting ref in input signature
// Expecting value in input signature
impl Mul<f64, Vec1> for Vec1 {
fn mul(&self, s: f64) -> Vec1 {
//~^ ERROR: method `mul` has an incompatible type for trait: expected &-ptr, found f64
fn mul(self, s: &f64) -> Vec1 {
//~^ ERROR: method `mul` has an incompatible type for trait: expected f64, found &-ptr
Vec1 {
x: self.x * s
x: self.x * *s
}
}
}
@ -34,8 +34,8 @@ struct Vec2 {
// Wrong type parameter ordering
impl Mul<Vec2, f64> for Vec2 {
fn mul(&self, s: f64) -> Vec2 {
//~^ ERROR: method `mul` has an incompatible type for trait: expected &-ptr, found f64
fn mul(self, s: f64) -> Vec2 {
//~^ ERROR: method `mul` has an incompatible type for trait: expected struct Vec2, found f64
Vec2 {
x: self.x * s,
y: self.y * s
@ -51,9 +51,9 @@ struct Vec3 {
// Unexpected return type
impl Mul<f64, i32> for Vec3 {
fn mul(&self, s: &f64) -> f64 {
fn mul(self, s: f64) -> f64 {
//~^ ERROR: method `mul` has an incompatible type for trait: expected i32, found f64
*s
s
}
}

View File

@ -16,30 +16,30 @@ fn main() {
assert_eq!(false != true, true);
assert_eq!(false.ne(&false), false);
assert_eq!(false.bitand(&false), false);
assert_eq!(true.bitand(&false), false);
assert_eq!(false.bitand(&true), false);
assert_eq!(true.bitand(&true), true);
assert_eq!(false.bitand(false), false);
assert_eq!(true.bitand(false), false);
assert_eq!(false.bitand(true), false);
assert_eq!(true.bitand(true), true);
assert_eq!(false & false, false);
assert_eq!(true & false, false);
assert_eq!(false & true, false);
assert_eq!(true & true, true);
assert_eq!(false.bitor(&false), false);
assert_eq!(true.bitor(&false), true);
assert_eq!(false.bitor(&true), true);
assert_eq!(true.bitor(&true), true);
assert_eq!(false.bitor(false), false);
assert_eq!(true.bitor(false), true);
assert_eq!(false.bitor(true), true);
assert_eq!(true.bitor(true), true);
assert_eq!(false | false, false);
assert_eq!(true | false, true);
assert_eq!(false | true, true);
assert_eq!(true | true, true);
assert_eq!(false.bitxor(&false), false);
assert_eq!(true.bitxor(&false), true);
assert_eq!(false.bitxor(&true), true);
assert_eq!(true.bitxor(&true), false);
assert_eq!(false.bitxor(false), false);
assert_eq!(true.bitxor(false), true);
assert_eq!(false.bitxor(true), true);
assert_eq!(true.bitxor(true), false);
assert_eq!(false ^ false, false);
assert_eq!(true ^ false, true);

View File

@ -15,10 +15,10 @@ use std::num::Zero;
struct Vector2<T>(T, T);
impl<T: Add<T, T>> Add<Vector2<T>, Vector2<T>> for Vector2<T> {
fn add(&self, other: &Vector2<T>) -> Vector2<T> {
fn add(self, other: Vector2<T>) -> Vector2<T> {
match (self, other) {
(&Vector2(ref x0, ref y0), &Vector2(ref x1, ref y1)) => {
Vector2(*x0 + *x1, *y0 + *y1)
(Vector2(x0, y0), Vector2(x1, y1)) => {
Vector2(x0 + x1, y0 + y1)
}
}
}
@ -30,7 +30,7 @@ struct Vector3<T> {
}
impl<T: Add<T, T>> Add<Vector3<T>, Vector3<T>> for Vector3<T> {
fn add(&self, other: &Vector3<T>) -> Vector3<T> {
fn add(self, other: Vector3<T>) -> Vector3<T> {
Vector3 {
x: self.x + other.x,
y: self.y + other.y,
@ -47,7 +47,7 @@ struct Matrix3x2<T> {
}
impl<T: Add<T, T>> Add<Matrix3x2<T>, Matrix3x2<T>> for Matrix3x2<T> {
fn add(&self, other: &Matrix3x2<T>) -> Matrix3x2<T> {
fn add(self, other: Matrix3x2<T>) -> Matrix3x2<T> {
Matrix3x2 {
x: self.x + other.x,
y: self.y + other.y,

View File

@ -28,7 +28,7 @@ trait RhsOfVec2Mul<Result> { fn mul_vec2_by(&self, lhs: &Vec2) -> Result; }
// Vec2's implementation of Mul "from the other side" using the above trait
impl<Res, Rhs: RhsOfVec2Mul<Res>> Mul<Rhs,Res> for Vec2 {
fn mul(&self, rhs: &Rhs) -> Res { rhs.mul_vec2_by(self) }
fn mul(self, rhs: Rhs) -> Res { rhs.mul_vec2_by(&self) }
}
// Implementation of 'f64 as right-hand-side of Vec2::Mul'

View File

@ -18,19 +18,19 @@
pub fn main() {
// ints
// num
assert_eq!(15i.add(&6), 21);
assert_eq!(15i8.add(&6i8), 21i8);
assert_eq!(15i16.add(&6i16), 21i16);
assert_eq!(15i32.add(&6i32), 21i32);
assert_eq!(15i64.add(&6i64), 21i64);
assert_eq!(15i.add(6), 21);
assert_eq!(15i8.add(6i8), 21i8);
assert_eq!(15i16.add(6i16), 21i16);
assert_eq!(15i32.add(6i32), 21i32);
assert_eq!(15i64.add(6i64), 21i64);
// uints
// num
assert_eq!(15u.add(&6u), 21u);
assert_eq!(15u8.add(&6u8), 21u8);
assert_eq!(15u16.add(&6u16), 21u16);
assert_eq!(15u32.add(&6u32), 21u32);
assert_eq!(15u64.add(&6u64), 21u64);
assert_eq!(15u.add(6u), 21u);
assert_eq!(15u8.add(6u8), 21u8);
assert_eq!(15u16.add(6u16), 21u16);
assert_eq!(15u32.add(6u32), 21u32);
assert_eq!(15u64.add(6u64), 21u64);
// floats
// num

View File

@ -20,13 +20,13 @@ struct Point {
}
impl ops::Add<Point,Point> for Point {
fn add(&self, other: &Point) -> Point {
Point {x: self.x + (*other).x, y: self.y + (*other).y}
fn add(self, other: Point) -> Point {
Point {x: self.x + other.x, y: self.y + other.y}
}
}
impl ops::Add<int,Point> for Point {
fn add(&self, &other: &int) -> Point {
fn add(self, other: int) -> Point {
Point {x: self.x + other,
y: self.y + other}
}

View File

@ -12,21 +12,21 @@
use std::cmp;
use std::ops;
#[deriving(Show)]
#[deriving(Copy, Show)]
struct Point {
x: int,
y: int
}
impl ops::Add<Point,Point> for Point {
fn add(&self, other: &Point) -> Point {
Point {x: self.x + (*other).x, y: self.y + (*other).y}
fn add(self, other: Point) -> Point {
Point {x: self.x + other.x, y: self.y + other.y}
}
}
impl ops::Sub<Point,Point> for Point {
fn sub(&self, other: &Point) -> Point {
Point {x: self.x - (*other).x, y: self.y - (*other).y}
fn sub(self, other: Point) -> Point {
Point {x: self.x - other.x, y: self.y - other.y}
}
}

View File

@ -18,7 +18,7 @@ struct G;
impl<'a, A: Add<int, int>> Fn<(A,), int> for G {
extern "rust-call" fn call(&self, (arg,): (A,)) -> int {
arg.add(&1)
arg.add(1)
}
}

View File

@ -22,8 +22,8 @@ fn add<T: ops::Add<T, T>>(lhs: T, rhs: T) -> T {
}
impl ops::Add<f32x4, f32x4> for f32x4 {
fn add(&self, rhs: &f32x4) -> f32x4 {
*self + *rhs
fn add(self, rhs: f32x4) -> f32x4 {
self + rhs
}
}

View File

@ -14,7 +14,7 @@ extern crate trait_inheritance_overloading_xc;
use trait_inheritance_overloading_xc::{MyNum, MyInt};
fn f<T:MyNum>(x: T, y: T) -> (T, T, T) {
return (x + y, x - y, x * y);
return (x.clone() + y.clone(), x.clone() - y.clone(), x * y);
}
fn mi(v: int) -> MyInt { MyInt { val: v } }

View File

@ -10,21 +10,21 @@
use std::cmp::PartialEq;
trait MyNum : Add<Self,Self> + Sub<Self,Self> + Mul<Self,Self> + PartialEq { }
trait MyNum : Add<Self,Self> + Sub<Self,Self> + Mul<Self,Self> + PartialEq + Clone { }
#[deriving(Show)]
#[deriving(Clone, Show)]
struct MyInt { val: int }
impl Add<MyInt, MyInt> for MyInt {
fn add(&self, other: &MyInt) -> MyInt { mi(self.val + other.val) }
fn add(self, other: MyInt) -> MyInt { mi(self.val + other.val) }
}
impl Sub<MyInt, MyInt> for MyInt {
fn sub(&self, other: &MyInt) -> MyInt { mi(self.val - other.val) }
fn sub(self, other: MyInt) -> MyInt { mi(self.val - other.val) }
}
impl Mul<MyInt, MyInt> for MyInt {
fn mul(&self, other: &MyInt) -> MyInt { mi(self.val * other.val) }
fn mul(self, other: MyInt) -> MyInt { mi(self.val * other.val) }
}
impl PartialEq for MyInt {
@ -35,7 +35,7 @@ impl PartialEq for MyInt {
impl MyNum for MyInt {}
fn f<T:MyNum>(x: T, y: T) -> (T, T, T) {
return (x + y, x - y, x * y);
return (x.clone() + y.clone(), x.clone() - y.clone(), x * y);
}
fn mi(v: int) -> MyInt { MyInt { val: v } }