about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-12-15 22:11:44 +0000
committerbors <bors@rust-lang.org>2014-12-15 22:11:44 +0000
commit0669a432a2e09ad08886cb2138dbe9f5d681fb7f (patch)
tree5183544df317d80a6bce406242596dd997e61b64 /src/libsyntax
parent92e9e70d15bcf8d29890bf93793be402ad629229 (diff)
parent89d2061c8f1cc2bcd5e9bb8a97e214f482d5ff2c (diff)
downloadrust-0669a432a2e09ad08886cb2138dbe9f5d681fb7f.tar.gz
rust-0669a432a2e09ad08886cb2138dbe9f5d681fb7f.zip
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 
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast_util.rs10
-rw-r--r--src/libsyntax/codemap.rs36
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs24
3 files changed, 70 insertions, 0 deletions
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 63c95a976d4..2e097d45515 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -85,6 +85,16 @@ pub fn is_shift_binop(b: BinOp) -> bool {
     }
 }
 
+/// Returns `true` is the binary operator takes its arguments by value
+pub fn is_by_value_binop(b: BinOp) -> bool {
+    match b {
+        BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => {
+            true
+        }
+        _ => false
+    }
+}
+
 pub fn unop_to_string(op: UnOp) -> &'static str {
     match op {
       UnUniq => "box() ",
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index d2fe667339c..592fdd7207c 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -52,35 +52,71 @@ impl Pos for BytePos {
     fn to_uint(&self) -> uint { let BytePos(n) = *self; n as uint }
 }
 
+// NOTE(stage0): Remove impl after a snapshot
+#[cfg(stage0)]
 impl Add<BytePos, BytePos> for BytePos {
     fn add(&self, rhs: &BytePos) -> BytePos {
         BytePos((self.to_uint() + rhs.to_uint()) as u32)
     }
 }
 
+#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
+impl Add<BytePos, BytePos> for BytePos {
+    fn add(self, rhs: BytePos) -> BytePos {
+        BytePos((self.to_uint() + rhs.to_uint()) as u32)
+    }
+}
+
+// NOTE(stage0): Remove impl after a snapshot
+#[cfg(stage0)]
 impl Sub<BytePos, BytePos> for BytePos {
     fn sub(&self, rhs: &BytePos) -> BytePos {
         BytePos((self.to_uint() - rhs.to_uint()) as u32)
     }
 }
 
+#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
+impl Sub<BytePos, BytePos> for BytePos {
+    fn sub(self, rhs: BytePos) -> BytePos {
+        BytePos((self.to_uint() - rhs.to_uint()) as u32)
+    }
+}
+
 impl Pos for CharPos {
     fn from_uint(n: uint) -> CharPos { CharPos(n) }
     fn to_uint(&self) -> uint { let CharPos(n) = *self; n }
 }
 
+// NOTE(stage0): Remove impl after a snapshot
+#[cfg(stage0)]
 impl Add<CharPos,CharPos> for CharPos {
     fn add(&self, rhs: &CharPos) -> CharPos {
         CharPos(self.to_uint() + rhs.to_uint())
     }
 }
 
+#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
+impl Add<CharPos, CharPos> for CharPos {
+    fn add(self, rhs: CharPos) -> CharPos {
+        CharPos(self.to_uint() + rhs.to_uint())
+    }
+}
+
+// NOTE(stage0): Remove impl after a snapshot
+#[cfg(stage0)]
 impl Sub<CharPos,CharPos> for CharPos {
     fn sub(&self, rhs: &CharPos) -> CharPos {
         CharPos(self.to_uint() - rhs.to_uint())
     }
 }
 
+#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
+impl Sub<CharPos, CharPos> for CharPos {
+    fn sub(self, rhs: CharPos) -> CharPos {
+        CharPos(self.to_uint() - rhs.to_uint())
+    }
+}
+
 /// Spans represent a region of code, used for error reporting. Positions in spans
 /// are *absolute* positions from the beginning of the codemap, not positions
 /// relative to FileMaps. Methods on the CodeMap can be used to relate spans back
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 99799fecb78..e2439bad178 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -106,6 +106,8 @@ enum LockstepIterSize {
     LisContradiction(String),
 }
 
+// NOTE(stage0): Remove impl after a snapshot
+#[cfg(stage0)]
 impl Add<LockstepIterSize, LockstepIterSize> for LockstepIterSize {
     fn add(&self, other: &LockstepIterSize) -> LockstepIterSize {
         match *self {
@@ -127,6 +129,28 @@ impl Add<LockstepIterSize, LockstepIterSize> for LockstepIterSize {
     }
 }
 
+#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
+impl Add<LockstepIterSize, LockstepIterSize> for LockstepIterSize {
+    fn add(self, other: LockstepIterSize) -> LockstepIterSize {
+        match self {
+            LisUnconstrained => other,
+            LisContradiction(_) => self,
+            LisConstraint(l_len, ref l_id) => match other {
+                LisUnconstrained => self.clone(),
+                LisContradiction(_) => other,
+                LisConstraint(r_len, _) if l_len == r_len => self.clone(),
+                LisConstraint(r_len, r_id) => {
+                    let l_n = token::get_ident(l_id.clone());
+                    let r_n = token::get_ident(r_id);
+                    LisContradiction(format!("inconsistent lockstep iteration: \
+                                              '{}' has {} items, but '{}' has {}",
+                                              l_n, l_len, r_n, r_len).to_string())
+                }
+            },
+        }
+    }
+}
+
 fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize {
     match *t {
         TtDelimited(_, ref delimed) => {