diff options
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 41 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 14 |
4 files changed, 51 insertions, 23 deletions
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 012940a2ebb..f13a4329d3b 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -20,7 +20,8 @@ use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP}; use tracing::{debug, trace}; -const TURBOFISH: &str = "use `::<...>` instead of `<...>` to specify type arguments"; +const TURBOFISH_SUGGESTION_STR: &str = + "use `::<...>` instead of `<...>` to specify type or const arguments"; /// Creates a placeholder argument. pub(super) fn dummy_arg(ident: Ident) -> Param { @@ -659,7 +660,7 @@ impl<'a> Parser<'a> { Ok(_) => { e.span_suggestion_verbose( binop.span.shrink_to_lo(), - "use `::<...>` instead of `<...>` to specify type arguments", + TURBOFISH_SUGGESTION_STR, "::".to_string(), Applicability::MaybeIncorrect, ); @@ -814,7 +815,7 @@ impl<'a> Parser<'a> { let suggest = |err: &mut DiagnosticBuilder<'_>| { err.span_suggestion_verbose( op.span.shrink_to_lo(), - TURBOFISH, + TURBOFISH_SUGGESTION_STR, "::".to_string(), Applicability::MaybeIncorrect, ); @@ -888,7 +889,7 @@ impl<'a> Parser<'a> { { // All we know is that this is `foo < bar >` and *nothing* else. Try to // be helpful, but don't attempt to recover. - err.help(TURBOFISH); + err.help(TURBOFISH_SUGGESTION_STR); err.help("or use `(...)` if you meant to specify fn arguments"); } @@ -1557,14 +1558,6 @@ impl<'a> Parser<'a> { } } - pub(super) fn expected_semi_or_open_brace<T>(&mut self) -> PResult<'a, T> { - let token_str = super::token_descr(&self.token); - let msg = &format!("expected `;` or `{{`, found {}", token_str); - let mut err = self.struct_span_err(self.token.span, msg); - err.span_label(self.token.span, "expected `;` or `{`"); - Err(err) - } - pub(super) fn eat_incorrect_doc_comment_for_param_type(&mut self) { if let token::DocComment(..) = self.token.kind { self.struct_span_err( diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 5994eda966f..c2a13d4b0de 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -831,7 +831,7 @@ impl<'a> Parser<'a> { self.struct_span_err(self.token.span, &format!("unexpected token: `{}`", actual)).emit(); } - // We need and identifier or integer, but the next token is a float. + // We need an identifier or integer, but the next token is a float. // Break the float into components to extract the identifier or integer. // FIXME: With current `TokenCursor` it's hard to break tokens into more than 2 // parts unless those parts are processed immediately. `TokenCursor` should either diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e57a2e42b5d..39d4875f37b 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1538,7 +1538,7 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; // `where T: Ord` let mut sig_hi = self.prev_token.span; - let body = self.parse_fn_body(attrs, &mut sig_hi)?; // `;` or `{ ... }`. + let body = self.parse_fn_body(attrs, &ident, &mut sig_hi)?; // `;` or `{ ... }`. let fn_sig_span = sig_lo.to(sig_hi); Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body)) } @@ -1549,12 +1549,12 @@ impl<'a> Parser<'a> { fn parse_fn_body( &mut self, attrs: &mut Vec<Attribute>, + ident: &Ident, sig_hi: &mut Span, ) -> PResult<'a, Option<P<Block>>> { - let (inner_attrs, body) = if self.check(&token::Semi) { + let (inner_attrs, body) = if self.eat(&token::Semi) { // Include the trailing semicolon in the span of the signature - *sig_hi = self.token.span; - self.bump(); // `;` + *sig_hi = self.prev_token.span; (Vec::new(), None) } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() { self.parse_inner_attrs_and_block().map(|(attrs, body)| (attrs, Some(body)))? @@ -1574,7 +1574,21 @@ impl<'a> Parser<'a> { .emit(); (Vec::new(), Some(self.mk_block_err(span))) } else { - return self.expected_semi_or_open_brace(); + if let Err(mut err) = + self.expected_one_of_not_found(&[], &[token::Semi, token::OpenDelim(token::Brace)]) + { + if self.token.kind == token::CloseDelim(token::Brace) { + // The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in + // the AST for typechecking. + err.span_label(ident.span, "while parsing this `fn`"); + err.emit(); + (Vec::new(), None) + } else { + return Err(err); + } + } else { + unreachable!() + } }; attrs.extend(inner_attrs); Ok(body) @@ -1652,10 +1666,19 @@ impl<'a> Parser<'a> { req_name: ReqName, ret_allow_plus: AllowPlus, ) -> PResult<'a, P<FnDecl>> { - Ok(P(FnDecl { - inputs: self.parse_fn_params(req_name)?, - output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes)?, - })) + let inputs = self.parse_fn_params(req_name)?; + let output = self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes)?; + + if let ast::FnRetTy::Ty(ty) = &output { + if let TyKind::Path(_, Path { segments, .. }) = &ty.kind { + if let [.., last] = &segments[..] { + // Detect and recover `fn foo() -> Vec<i32>> {}` + self.check_trailing_angle_brackets(last, &[&token::OpenDelim(token::Brace)]); + } + } + } + + Ok(P(FnDecl { inputs, output })) } /// Parses the parameter list of a function, including the `(` and `)` delimiters. diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index d42a786a18f..7a6ebca4e15 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -265,7 +265,19 @@ impl<'a> Parser<'a> { /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type. /// The opening `[` bracket is already eaten. fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> { - let elt_ty = self.parse_ty()?; + let elt_ty = match self.parse_ty() { + Ok(ty) => ty, + Err(mut err) + if self.look_ahead(1, |t| t.kind == token::CloseDelim(token::Bracket)) + | self.look_ahead(1, |t| t.kind == token::Semi) => + { + // Recover from `[LIT; EXPR]` and `[LIT]` + self.bump(); + err.emit(); + self.mk_ty(self.prev_token.span, TyKind::Err) + } + Err(err) => return Err(err), + }; let ty = if self.eat(&token::Semi) { TyKind::Array(elt_ty, self.parse_anon_const_expr()?) } else { |
