From 9a68098e87bdc5a73c6714064eb1627590b4c0bc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 18 Dec 2017 23:26:59 +0300 Subject: Move impls for qpath recovery trait from `ast.rs` --- src/libsyntax/parse/parser.rs | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 74ec11b83c7..010ab3c2781 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -169,11 +169,49 @@ enum PrevTokenKind { Other, } -pub(crate) trait RecoverQPath: Sized { +trait RecoverQPath: Sized { + const PATH_STYLE: PathStyle = PathStyle::Expr; fn to_ty(&self) -> Option>; fn to_recovered(&self, qself: Option, path: ast::Path) -> Self; fn to_string(&self) -> String; - const PATH_STYLE: PathStyle = PathStyle::Expr; +} + +impl RecoverQPath for Ty { + const PATH_STYLE: PathStyle = PathStyle::Type; + fn to_ty(&self) -> Option> { + Some(P(self.clone())) + } + fn to_recovered(&self, qself: Option, path: ast::Path) -> Self { + Self { span: path.span, node: TyKind::Path(qself, path), id: self.id } + } + fn to_string(&self) -> String { + pprust::ty_to_string(self) + } +} + +impl RecoverQPath for Pat { + fn to_ty(&self) -> Option> { + self.to_ty() + } + fn to_recovered(&self, qself: Option, path: ast::Path) -> Self { + Self { span: path.span, node: PatKind::Path(qself, path), id: self.id } + } + fn to_string(&self) -> String { + pprust::pat_to_string(self) + } +} + +impl RecoverQPath for Expr { + fn to_ty(&self) -> Option> { + self.to_ty() + } + fn to_recovered(&self, qself: Option, path: ast::Path) -> Self { + Self { span: path.span, node: ExprKind::Path(qself, path), + id: self.id, attrs: self.attrs.clone() } + } + fn to_string(&self) -> String { + pprust::expr_to_string(self) + } } /* ident is handled by common.rs */ -- cgit 1.4.1-3-g733a5 From d333752f5c6553e005fa7694837723b08ec8f13e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 18 Dec 2017 23:59:31 +0300 Subject: Fix parsing of paths with fn-like generic arguments --- src/libsyntax/parse/parser.rs | 20 +++++++++++--------- src/test/ui/did_you_mean/bad-assoc-ty.rs | 4 +--- src/test/ui/did_you_mean/bad-assoc-ty.stderr | 18 ++++++------------ 3 files changed, 18 insertions(+), 24 deletions(-) (limited to 'src/libsyntax/parse') 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> { - 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> { - self.parse_ty_common(false) + self.parse_ty_common(false, true) } - fn parse_ty_common(&mut self, allow_plus: bool) -> PResult<'a, P> { + fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool) + -> PResult<'a, P> { 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(&mut self, base: T) -> PResult<'a, T> { + fn maybe_recover_from_bad_qpath(&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 `::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 `::Output` + = note: specify the type using the syntax ` u8 + 'static as Trait>::Output` -error: aborting due to 16 previous errors +error: aborting due to 15 previous errors -- cgit 1.4.1-3-g733a5