diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index cd01c008fe1bc..d4c05e4b7d39c 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -409,6 +409,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>`. /// @@ -430,6 +432,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>`. /// @@ -451,6 +477,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>`. /// @@ -472,6 +522,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>`. /// @@ -492,6 +566,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, "{{")); diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index d8dc1f36e056d..4df1be1bb355c 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -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, diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index c4659f86680e4..f3a9e7b186758 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -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"); } diff --git a/src/libcollections/tree/set.rs b/src/libcollections/tree/set.rs index bd8bf5c6cb67f..1d3ec2eb7f2f6 100644 --- a/src/libcollections/tree/set.rs +++ b/src/libcollections/tree/set.rs @@ -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]); } diff --git a/src/libcollections/trie/set.rs b/src/libcollections/trie/set.rs index 5621726dc5682..7b7b4d8280b78 100644 --- a/src/libcollections/trie/set.rs +++ b/src/libcollections/trie/set.rs @@ -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]); } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 2ed8686394c01..275825da3b55f 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -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) { diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 8ee2a8874bb03..5405c7aa3b7dd 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -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) } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 3c9b68b350b6b..2416cf5bcc7ae 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -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. diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index ebe46af516957..7ff5026d0b9c8 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -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 diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs index e25f10bd0dad5..87e2fe752995c 100644 --- a/src/libcoretest/num/int_macros.rs +++ b/src/libcoretest/num/int_macros.rs @@ -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()); } diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 6ee3633d36c14..b7f8b81f996de 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -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)] diff --git a/src/libcoretest/num/uint_macros.rs b/src/libcoretest/num/uint_macros.rs index 01a88119b6470..5657a43de1922 100644 --- a/src/libcoretest/num/uint_macros.rs +++ b/src/libcoretest/num/uint_macros.rs @@ -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()); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 8e00c96535b1e..59344258833a6 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -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); } @@ -911,13 +924,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 diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8e99045cffb58..2f694b382cc67 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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) diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index b8b2395dde172..bde68981ff493 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -996,10 +996,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. @@ -1171,7 +1172,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, { @@ -1185,7 +1186,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 }) })); } } diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index e1769001942d5..55672004f1422 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -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) @@ -1092,25 +1094,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: @@ -1803,7 +1806,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, @@ -1815,7 +1819,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) } @@ -2122,7 +2126,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 => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 18a773fb949fc..5f8991278b08c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -77,7 +77,6 @@ type parameter). */ pub use self::LvaluePreference::*; -pub use self::DerefArgs::*; pub use self::Expectation::*; use self::IsBinopAssignment::*; use self::TupleArgumentsFlag::*; @@ -2117,7 +2116,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); @@ -2274,7 +2273,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| { @@ -2480,7 +2479,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_type, iterator_expr, &[], - DontDerefArgs, + AutorefArgs::No, DontTupleArguments); match method { @@ -2522,7 +2521,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) { @@ -2538,7 +2537,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()) @@ -2551,7 +2550,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 @@ -2571,7 +2570,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; @@ -2674,8 +2673,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 => (), @@ -2690,7 +2689,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } } - DontDerefArgs => {} + AutorefArgs::No => {} } check_expr_coercable_to_type(fcx, &***arg, formal_ty); @@ -2904,12 +2903,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. @@ -2997,7 +2997,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); @@ -3047,7 +3047,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); @@ -3130,7 +3130,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 { @@ -3183,7 +3184,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() @@ -3199,7 +3200,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() } @@ -3347,7 +3348,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>, @@ -3363,7 +3364,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 diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index cadcee43b4402..3e7992b3cba17 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -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); } diff --git a/src/librustdoc/stability_summary.rs b/src/librustdoc/stability_summary.rs index 881270afe140c..f92cdaf46b6b4 100644 --- a/src/librustdoc/stability_summary.rs +++ b/src/librustdoc/stability_summary.rs @@ -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, diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs index ffcd6505dadd1..38bb32ea775ab 100644 --- a/src/libstd/bitflags.rs +++ b/src/libstd/bitflags.rs @@ -209,6 +209,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] @@ -217,6 +219,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] @@ -225,6 +238,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] @@ -233,6 +257,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] @@ -241,6 +276,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] diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index a15e71b4a2a88..9aaaceb87e6d3 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -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), 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), 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); } #[cfg(test)] diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index 34a3d6aa27536..f98cebd967596 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -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, diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 7579972c6d843..71ce4847922d3 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -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() ", diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index d2fe667339c84..592fdd7207c7b 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -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 diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 99799fecb7882..e2439bad178fe 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -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) => { diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index e293c547944d5..4129086e9ec97 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -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 { diff --git a/src/test/auxiliary/trait_inheritance_overloading_xc.rs b/src/test/auxiliary/trait_inheritance_overloading_xc.rs index 95bdecd77605f..61854aba2790d 100644 --- a/src/test/auxiliary/trait_inheritance_overloading_xc.rs +++ b/src/test/auxiliary/trait_inheritance_overloading_xc.rs @@ -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 { diff --git a/src/test/compile-fail/binop-consume-args.rs b/src/test/compile-fail/binop-consume-args.rs new file mode 100644 index 0000000000000..2bdd148b99bd0 --- /dev/null +++ b/src/test/compile-fail/binop-consume-args.rs @@ -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() {} diff --git a/src/test/compile-fail/binop-move-semantics.rs b/src/test/compile-fail/binop-move-semantics.rs new file mode 100644 index 0000000000000..d9440e1837572 --- /dev/null +++ b/src/test/compile-fail/binop-move-semantics.rs @@ -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() {} diff --git a/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs index 4a6c20079c17e..692303fc1e481 100644 --- a/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs +++ b/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs @@ -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` } diff --git a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs index c5d7b6fa4518f..b83e1544c96d3 100644 --- a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs +++ b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs @@ -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` diff --git a/src/test/compile-fail/wrong-mul-method-signature.rs b/src/test/compile-fail/wrong-mul-method-signature.rs index aead739d3e01a..b5e4cac75550f 100644 --- a/src/test/compile-fail/wrong-mul-method-signature.rs +++ b/src/test/compile-fail/wrong-mul-method-signature.rs @@ -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 } } diff --git a/src/test/run-pass/bool.rs b/src/test/run-pass/bool.rs index 91075633ab8d8..238d0ecdca7f8 100644 --- a/src/test/run-pass/bool.rs +++ b/src/test/run-pass/bool.rs @@ -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); diff --git a/src/test/run-pass/deriving-zero.rs b/src/test/run-pass/deriving-zero.rs index 690d82a4ed25a..88f3e5775b78b 100644 --- a/src/test/run-pass/deriving-zero.rs +++ b/src/test/run-pass/deriving-zero.rs @@ -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, diff --git a/src/test/run-pass/issue-3743.rs b/src/test/run-pass/issue-3743.rs index ada3e37c092a7..80d3d29bc004d 100644 --- a/src/test/run-pass/issue-3743.rs +++ b/src/test/run-pass/issue-3743.rs @@ -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' diff --git a/src/test/run-pass/numeric-method-autoexport.rs b/src/test/run-pass/numeric-method-autoexport.rs index 585ade71fc603..f8184d248ff01 100644 --- a/src/test/run-pass/numeric-method-autoexport.rs +++ b/src/test/run-pass/numeric-method-autoexport.rs @@ -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 diff --git a/src/test/run-pass/operator-multidispatch.rs b/src/test/run-pass/operator-multidispatch.rs index fc79e4f0edb36..cb3397c00bc57 100644 --- a/src/test/run-pass/operator-multidispatch.rs +++ b/src/test/run-pass/operator-multidispatch.rs @@ -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} } diff --git a/src/test/run-pass/operator-overloading.rs b/src/test/run-pass/operator-overloading.rs index a896d2b06f7bd..0f3da6836cb34 100644 --- a/src/test/run-pass/operator-overloading.rs +++ b/src/test/run-pass/operator-overloading.rs @@ -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} } } diff --git a/src/test/run-pass/overloaded-calls-param-vtables.rs b/src/test/run-pass/overloaded-calls-param-vtables.rs index d0dbee39ae095..2e8ec3916bd89 100644 --- a/src/test/run-pass/overloaded-calls-param-vtables.rs +++ b/src/test/run-pass/overloaded-calls-param-vtables.rs @@ -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) } } diff --git a/src/test/run-pass/simd-generics.rs b/src/test/run-pass/simd-generics.rs index 31c29b615fc09..42f93a97142d2 100644 --- a/src/test/run-pass/simd-generics.rs +++ b/src/test/run-pass/simd-generics.rs @@ -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 } } diff --git a/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs b/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs index 7760395bf1c95..2a087e5e425ad 100644 --- a/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs +++ b/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs @@ -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 } } diff --git a/src/test/run-pass/trait-inheritance-overloading.rs b/src/test/run-pass/trait-inheritance-overloading.rs index b13ea7ae0baef..5f8e945cce860 100644 --- a/src/test/run-pass/trait-inheritance-overloading.rs +++ b/src/test/run-pass/trait-inheritance-overloading.rs @@ -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 } }