mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 22:41:50 +00:00
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:
commit
0669a432a2
@ -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, "{{"));
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 })
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -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 => {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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]
|
||||
|
@ -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)]
|
||||
|
@ -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,
|
||||
|
@ -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() ",
|
||||
|
@ -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
|
||||
|
@ -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) => {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
73
src/test/compile-fail/binop-consume-args.rs
Normal file
73
src/test/compile-fail/binop-consume-args.rs
Normal 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() {}
|
69
src/test/compile-fail/binop-move-semantics.rs
Normal file
69
src/test/compile-fail/binop-move-semantics.rs
Normal 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() {}
|
@ -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`
|
||||
}
|
||||
|
@ -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`
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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}
|
||||
}
|
||||
|
@ -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}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 } }
|
||||
|
@ -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 } }
|
||||
|
Loading…
Reference in New Issue
Block a user