about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-12-18 23:59:31 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-12-20 22:55:57 +0300
commitd333752f5c6553e005fa7694837723b08ec8f13e (patch)
tree27f5049e9475aa54e2c2135432727f93d4240352
parenteef85cf0ff898aefe813ab1cc7e73e90a904d7b2 (diff)
downloadrust-d333752f5c6553e005fa7694837723b08ec8f13e.tar.gz
rust-d333752f5c6553e005fa7694837723b08ec8f13e.zip
Fix parsing of paths with fn-like generic arguments
-rw-r--r--src/libsyntax/parse/parser.rs20
-rw-r--r--src/test/ui/did_you_mean/bad-assoc-ty.rs4
-rw-r--r--src/test/ui/did_you_mean/bad-assoc-ty.stderr18
3 files changed, 18 insertions, 24 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 010ab3c2781..2dfcd1a2b2b 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1467,7 +1467,7 @@ impl<'a> Parser<'a> {
 
     // Parse a type
     pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
-        self.parse_ty_common(true)
+        self.parse_ty_common(true, true)
     }
 
     /// Parse a type in restricted contexts where `+` is not permitted.
@@ -1476,10 +1476,11 @@ impl<'a> Parser<'a> {
     /// Example 2: `value1 as TYPE + value2`
     ///     `+` is prohibited to avoid interactions with expression grammar.
     fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
-        self.parse_ty_common(false)
+        self.parse_ty_common(false, true)
     }
 
-    fn parse_ty_common(&mut self, allow_plus: bool) -> PResult<'a, P<Ty>> {
+    fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool)
+                       -> PResult<'a, P<Ty>> {
         maybe_whole!(self, NtTy, |x| x);
 
         let lo = self.span;
@@ -1612,7 +1613,7 @@ impl<'a> Parser<'a> {
 
         // Try to recover from use of `+` with incorrect priority.
         self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
-        let ty = self.maybe_recover_from_bad_qpath(ty)?;
+        let ty = self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)?;
 
         Ok(P(ty))
     }
@@ -1668,9 +1669,10 @@ impl<'a> Parser<'a> {
     }
 
     // Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`.
-    fn maybe_recover_from_bad_qpath<T: RecoverQPath>(&mut self, base: T) -> PResult<'a, T> {
+    fn maybe_recover_from_bad_qpath<T: RecoverQPath>(&mut self, base: T, allow_recovery: bool)
+                                                     -> PResult<'a, T> {
         // Do not add `::` to expected tokens.
-        if self.token != token::ModSep {
+        if !allow_recovery || self.token != token::ModSep {
             return Ok(base);
         }
         let ty = match base.to_ty() {
@@ -2004,7 +2006,7 @@ impl<'a> Parser<'a> {
                     |p| p.parse_ty())?;
                 self.bump(); // `)`
                 let output = if self.eat(&token::RArrow) {
-                    Some(self.parse_ty_no_plus()?)
+                    Some(self.parse_ty_common(false, false)?)
                 } else {
                     None
                 };
@@ -2411,7 +2413,7 @@ impl<'a> Parser<'a> {
         }
 
         let expr = Expr { node: ex, span: lo.to(hi), id: ast::DUMMY_NODE_ID, attrs };
-        let expr = self.maybe_recover_from_bad_qpath(expr)?;
+        let expr = self.maybe_recover_from_bad_qpath(expr, true)?;
 
         return Ok(P(expr));
     }
@@ -3778,7 +3780,7 @@ impl<'a> Parser<'a> {
         }
 
         let pat = Pat { node: pat, span: lo.to(self.prev_span), id: ast::DUMMY_NODE_ID };
-        let pat = self.maybe_recover_from_bad_qpath(pat)?;
+        let pat = self.maybe_recover_from_bad_qpath(pat, true)?;
 
         Ok(P(pat))
     }
diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs
index 74305b73f99..b4a59904ee4 100644
--- a/src/test/ui/did_you_mean/bad-assoc-ty.rs
+++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs
@@ -38,11 +38,9 @@ type G = 'static + (Send)::AssocTy;
 //~^ ERROR missing angle brackets in associated item path
 //~| ERROR ambiguous associated type
 
-// FIXME
 // This is actually a legal path with fn-like generic arguments in the middle!
 // Recovery should not apply in this context.
 type H = Fn(u8) -> (u8)::Output;
-//~^ ERROR missing angle brackets in associated item path
-//~| ERROR ambiguous associated type
+//~^ ERROR ambiguous associated type
 
 fn main() {}
diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
index a11be411fed..c44dc5a0468 100644
--- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr
+++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
@@ -38,13 +38,7 @@ error: missing angle brackets in associated item path
   --> $DIR/bad-assoc-ty.rs:37:10
    |
 37 | type G = 'static + (Send)::AssocTy;
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `< 'static + Send>::AssocTy`
-
-error: missing angle brackets in associated item path
-  --> $DIR/bad-assoc-ty.rs:44:20
-   |
-44 | type H = Fn(u8) -> (u8)::Output;
-   |                    ^^^^^^^^^^^^ help: try: `<(u8)>::Output`
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `<'static + Send>::AssocTy`
 
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:11:10
@@ -101,12 +95,12 @@ error[E0223]: ambiguous associated type
    = note: specify the type using the syntax `<std::marker::Send + 'static as Trait>::AssocTy`
 
 error[E0223]: ambiguous associated type
-  --> $DIR/bad-assoc-ty.rs:44:20
+  --> $DIR/bad-assoc-ty.rs:43:10
    |
-44 | type H = Fn(u8) -> (u8)::Output;
-   |                    ^^^^^^^^^^^^ ambiguous associated type
+43 | type H = Fn(u8) -> (u8)::Output;
+   |          ^^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type
    |
-   = note: specify the type using the syntax `<u8 as Trait>::Output`
+   = note: specify the type using the syntax `<std::ops::Fn(u8) -> u8 + 'static as Trait>::Output`
 
-error: aborting due to 16 previous errors
+error: aborting due to 15 previous errors