about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-01-07 17:38:03 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-01-07 17:38:03 -0800
commitd11bfba71bb71e05ab93e1576a07a48269b13021 (patch)
treec066874abec04d60a316410fbd147990de45b7dc /src
parent662132560133a17cb598083f44de2fbf3d74f157 (diff)
parent68a783a89f4c7e74d4c7e09bfac67283e054d4fc (diff)
downloadrust-d11bfba71bb71e05ab93e1576a07a48269b13021.tar.gz
rust-d11bfba71bb71e05ab93e1576a07a48269b13021.zip
rollup merge of #20720: nick29581/assoc-ice-missing
Diffstat (limited to 'src')
-rw-r--r--src/libcore/ops.rs37
-rw-r--r--src/libsyntax/parse/parser.rs38
-rw-r--r--src/test/run-pass/ranges-precedence.rs52
3 files changed, 105 insertions, 22 deletions
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 4debab91739..ab956587d82 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -65,6 +65,7 @@ use clone::Clone;
 use iter::{Step, Iterator,DoubleEndedIterator,ExactSizeIterator};
 use marker::Sized;
 use option::Option::{self, Some, None};
+use fmt;
 
 /// The `Drop` trait is used to run some code when a value goes out of scope. This
 /// is sometimes called a 'destructor'.
@@ -847,13 +848,20 @@ pub trait IndexMut<Index: ?Sized> {
 }
 
 /// An unbounded range.
-#[derive(Copy)]
+#[derive(Copy, PartialEq, Eq)]
 #[lang="full_range"]
 #[unstable = "API still in development"]
 pub struct FullRange;
 
+#[unstable = "API still in development"]
+impl fmt::Show for FullRange {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Show::fmt("..", fmt)
+    }
+}
+
 /// A (half-open) range which is bounded at both ends.
-#[derive(Copy)]
+#[derive(Copy, PartialEq, Eq)]
 #[lang="range"]
 #[unstable = "API still in development"]
 pub struct Range<Idx> {
@@ -904,8 +912,15 @@ impl<Idx: Clone + Step> DoubleEndedIterator for Range<Idx> {
 #[unstable = "API still in development"]
 impl<Idx: Clone + Step> ExactSizeIterator for Range<Idx> {}
 
+#[unstable = "API still in development"]
+impl<Idx: fmt::Show> fmt::Show for Range<Idx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmt, "{:?}..{:?}", self.start, self.end)
+    }
+}
+
 /// A range which is only bounded below.
-#[derive(Copy)]
+#[derive(Copy, PartialEq, Eq)]
 #[lang="range_from"]
 #[unstable = "API still in development"]
 pub struct RangeFrom<Idx> {
@@ -926,8 +941,15 @@ impl<Idx: Clone + Step> Iterator for RangeFrom<Idx> {
     }
 }
 
+#[unstable = "API still in development"]
+impl<Idx: fmt::Show> fmt::Show for RangeFrom<Idx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmt, "{:?}..", self.start)
+    }
+}
+
 /// A range which is only bounded above.
-#[derive(Copy)]
+#[derive(Copy, PartialEq, Eq)]
 #[lang="range_to"]
 #[unstable = "API still in development"]
 pub struct RangeTo<Idx> {
@@ -935,6 +957,13 @@ pub struct RangeTo<Idx> {
     pub end: Idx,
 }
 
+#[unstable = "API still in development"]
+impl<Idx: fmt::Show> fmt::Show for RangeTo<Idx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmt, "..{:?}", self.end)
+    }
+}
+
 
 /// The `Deref` trait is used to specify the functionality of dereferencing
 /// operations like `*v`.
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 3497bebd0bb..531e611594a 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2535,7 +2535,7 @@ impl<'a> Parser<'a> {
               }
 
               // expr[...]
-              // An index expression.
+              // Could be either an index expression or a slicing expression.
               token::OpenDelim(token::Bracket) => {
                 let bracket_pos = self.span.lo;
                 self.bump();
@@ -2575,22 +2575,6 @@ impl<'a> Parser<'a> {
                                    "use `&expr[]` to construct a slice of the whole of expr");
                 }
               }
-
-              // A range expression, either `expr..expr` or `expr..`.
-              token::DotDot if !self.restrictions.contains(RESTRICTION_NO_DOTS) => {
-                self.bump();
-
-                let opt_end = if self.token.can_begin_expr() {
-                    let end = self.parse_expr_res(RESTRICTION_NO_DOTS);
-                    Some(end)
-                } else {
-                    None
-                };
-
-                let hi = self.span.hi;
-                let range = self.mk_range(Some(e), opt_end);
-                return self.mk_expr(lo, hi, range);
-              }
               _ => return e
             }
         }
@@ -2833,7 +2817,7 @@ impl<'a> Parser<'a> {
           token::DotDot if !self.restrictions.contains(RESTRICTION_NO_DOTS) => {
             // A range, closed above: `..expr`.
             self.bump();
-            let e = self.parse_prefix_expr();
+            let e = self.parse_expr();
             hi = e.span.hi;
             ex = self.mk_range(None, Some(e));
           }
@@ -2900,6 +2884,7 @@ impl<'a> Parser<'a> {
             self.restrictions.contains(RESTRICTION_NO_BAR_OP) {
             return lhs;
         }
+
         self.expected_tokens.push(TokenType::Operator);
 
         let cur_opt = self.token.to_binop();
@@ -2991,6 +2976,23 @@ impl<'a> Parser<'a> {
               let assign_op = self.mk_assign_op(aop, lhs, rhs);
               self.mk_expr(span.lo, rhs_span.hi, assign_op)
           }
+          // A range expression, either `expr..expr` or `expr..`.
+          token::DotDot if !self.restrictions.contains(RESTRICTION_NO_DOTS) => {
+            self.bump();
+
+            let opt_end = if self.token.can_begin_expr() {
+                let end = self.parse_expr_res(RESTRICTION_NO_DOTS);
+                Some(end)
+            } else {
+                None
+            };
+
+            let lo = lhs.span.lo;
+            let hi = self.span.hi;
+            let range = self.mk_range(Some(lhs), opt_end);
+            return self.mk_expr(lo, hi, range);
+          }
+
           _ => {
               lhs
           }
diff --git a/src/test/run-pass/ranges-precedence.rs b/src/test/run-pass/ranges-precedence.rs
new file mode 100644
index 00000000000..f678eed8775
--- /dev/null
+++ b/src/test/run-pass/ranges-precedence.rs
@@ -0,0 +1,52 @@
+// Copyright 2015 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 the precedence of ranges is correct
+
+#![feature(slicing_syntax)]
+
+struct Foo {
+    foo: uint,
+}
+
+impl Foo {
+    fn bar(&self) -> uint { 5 }
+}
+
+fn main() {
+    let x = 1+3..4+5;
+    assert!(x == (4..9));
+
+    let x = 1..4+5;
+    assert!(x == (1..9));
+
+    let x = 1+3..4;
+    assert!(x == (4..4));
+
+    let a = Foo { foo: 3 };
+    let x = a.foo..a.bar();
+    assert!(x == (3..5));
+
+    let x = 1+3..;
+    assert!(x == (4..));
+    let x = ..1+3;
+    assert!(x == (..4));
+
+    let a = &[0i32, 1, 2, 3, 4, 5, 6];
+    let x = &a[1+1..2+2];
+    assert!(x == &a[2..4]);
+    let x = &a[..1+2];
+    assert!(x == &a[..3]);
+    let x = &a[1+2..];
+    assert!(x == &a[3..]);
+
+    for _i in 2+4..10-3 {}
+}
+