about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-04-25 21:44:50 +0000
committerbors <bors@rust-lang.org>2015-04-25 21:44:50 +0000
commit00c48d3779fb4c372d2dfe7a8654c6cd1e065511 (patch)
treeb0e0c2156d8874ecaad57c16c20d9336e8a7f69c /src/libsyntax/parse
parent0d8309ec0b13ebad02bbc76f93eff39edf4af2d0 (diff)
parent0ad48e41c1b1eb6386449254258603eab7d91620 (diff)
downloadrust-00c48d3779fb4c372d2dfe7a8654c6cd1e065511.tar.gz
rust-00c48d3779fb4c372d2dfe7a8654c6cd1e065511.zip
Auto merge of #24547 - bombless:comma, r=pnkfelix
Closes #20616 
It breaks code such as <https://github.com/rust-lang/rust/blob/c64feb63418fd05bd6e5adc6f9ad763aa6a594b1/src/librustc_typeck/check/method/suggest.rs#L367>, so this is a [breaking-change], you have to add missing comma after the last lifetime arguement now.
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs33
-rw-r--r--src/libsyntax/parse/token.rs8
2 files changed, 40 insertions, 1 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 68006a8979a..47ea8d556fa 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -902,7 +902,9 @@ impl<'a> Parser<'a> {
     pub fn bump(&mut self) -> PResult<()> {
         self.last_span = self.span;
         // Stash token for error recovery (sometimes; clone is not necessarily cheap).
-        self.last_token = if self.token.is_ident() || self.token.is_path() {
+        self.last_token = if self.token.is_ident() ||
+                          self.token.is_path() ||
+                          self.token == token::Comma {
             Some(Box::new(self.token.clone()))
         } else {
             None
@@ -3807,8 +3809,37 @@ impl<'a> Parser<'a> {
     fn parse_generic_values_after_lt(&mut self) -> PResult<(Vec<ast::Lifetime>,
                                                             Vec<P<Ty>>,
                                                             Vec<P<TypeBinding>>)> {
+        let span_lo = self.span.lo;
         let lifetimes = try!(self.parse_lifetimes(token::Comma));
 
+        let missing_comma = !lifetimes.is_empty() &&
+                            !self.token.is_like_gt() &&
+                            self.last_token
+                                .as_ref().map_or(true,
+                                                 |x| &**x != &token::Comma);
+
+        if missing_comma {
+
+            let msg = format!("expected `,` or `>` after lifetime \
+                              name, found `{}`",
+                              self.this_token_to_string());
+            self.span_err(self.span, &msg);
+
+            let span_hi = self.span.hi;
+            let span_hi = if self.parse_ty_nopanic().is_ok() {
+                self.span.hi
+            } else {
+                span_hi
+            };
+
+            let msg = format!("did you mean a single argument type &'a Type, \
+                              or did you mean the comma-separated arguments \
+                              'a, Type?");
+            self.span_note(mk_sp(span_lo, span_hi), &msg);
+
+            self.abort_if_errors()
+        }
+
         // First parse types.
         let (types, returned) = try!(self.parse_seq_to_gt_or_return(
             Some(token::Comma),
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 538aa384327..e33b1391a10 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -173,6 +173,14 @@ pub enum Token {
 }
 
 impl Token {
+    /// Returns `true` if the token starts with '>'.
+    pub fn is_like_gt(&self) -> bool {
+        match *self {
+            BinOp(Shr) | BinOpEq(Shr) | Gt | Ge => true,
+            _ => false,
+        }
+    }
+
     /// Returns `true` if the token can appear at the start of an expression.
     pub fn can_begin_expr(&self) -> bool {
         match *self {