]> git.lizzy.rs Git - rust.git/commitdiff
Fix parsing of paths with fn-like generic arguments
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Mon, 18 Dec 2017 20:59:31 +0000 (23:59 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Wed, 20 Dec 2017 19:55:57 +0000 (22:55 +0300)
src/libsyntax/parse/parser.rs
src/test/ui/did_you_mean/bad-assoc-ty.rs
src/test/ui/did_you_mean/bad-assoc-ty.stderr

index 010ab3c27810a3a7b4aaeb501471c4882d4f239f..2dfcd1a2b2b14db707ede75c982456b0590bd4c5 100644 (file)
@@ -1467,7 +1467,7 @@ pub fn parse_ret_ty(&mut self) -> PResult<'a, FunctionRetTy> {
 
     // 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 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
     /// 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 @@ fn parse_ty_common(&mut self, allow_plus: bool) -> PResult<'a, P<Ty>> {
 
         // 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 @@ fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PRe
     }
 
     // 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 @@ fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
                     |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 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
         }
 
         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 @@ pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> {
         }
 
         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))
     }
index 74305b73f99c0ab337517871c4f523086df3eac3..b4a59904ee4b56198e9ce8664db3577463e8fbf5 100644 (file)
 //~^ 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() {}
index a11be411fed9d1017c8aee776ed9f1db8f21c542..c44dc5a0468809a0496c0fb3a433c1b7107d9db5 100644 (file)
@@ -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