Tweak invalid fn
header and body parsing
* Recover empty `fn` bodies when encountering `}` * Recover trailing `>` in return types * Recover from non-type in array type `[<BAD TOKEN>; LEN]`
This commit is contained in:
parent
040f568815
commit
ff61949860
7 changed files with 53 additions and 27 deletions
|
@ -1538,7 +1538,7 @@ impl<'a> Parser<'a> {
|
||||||
generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
|
generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
|
||||||
|
|
||||||
let mut sig_hi = self.prev_token.span;
|
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);
|
let fn_sig_span = sig_lo.to(sig_hi);
|
||||||
Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body))
|
Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body))
|
||||||
}
|
}
|
||||||
|
@ -1549,6 +1549,7 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_fn_body(
|
fn parse_fn_body(
|
||||||
&mut self,
|
&mut self,
|
||||||
attrs: &mut Vec<Attribute>,
|
attrs: &mut Vec<Attribute>,
|
||||||
|
ident: &Ident,
|
||||||
sig_hi: &mut Span,
|
sig_hi: &mut Span,
|
||||||
) -> PResult<'a, Option<P<Block>>> {
|
) -> PResult<'a, Option<P<Block>>> {
|
||||||
let (inner_attrs, body) = if self.eat(&token::Semi) {
|
let (inner_attrs, body) = if self.eat(&token::Semi) {
|
||||||
|
@ -1573,9 +1574,21 @@ impl<'a> Parser<'a> {
|
||||||
.emit();
|
.emit();
|
||||||
(Vec::new(), Some(self.mk_block_err(span)))
|
(Vec::new(), Some(self.mk_block_err(span)))
|
||||||
} else {
|
} else {
|
||||||
return self
|
if let Err(mut err) =
|
||||||
.expected_one_of_not_found(&[], &[token::Semi, token::OpenDelim(token::Brace)])
|
self.expected_one_of_not_found(&[], &[token::Semi, token::OpenDelim(token::Brace)])
|
||||||
.map(|_| None);
|
{
|
||||||
|
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);
|
attrs.extend(inner_attrs);
|
||||||
Ok(body)
|
Ok(body)
|
||||||
|
@ -1653,10 +1666,19 @@ impl<'a> Parser<'a> {
|
||||||
req_name: ReqName,
|
req_name: ReqName,
|
||||||
ret_allow_plus: AllowPlus,
|
ret_allow_plus: AllowPlus,
|
||||||
) -> PResult<'a, P<FnDecl>> {
|
) -> PResult<'a, P<FnDecl>> {
|
||||||
Ok(P(FnDecl {
|
let inputs = self.parse_fn_params(req_name)?;
|
||||||
inputs: self.parse_fn_params(req_name)?,
|
let output = self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes)?;
|
||||||
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.
|
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
|
||||||
|
|
|
@ -265,7 +265,19 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.
|
/// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.
|
||||||
/// The opening `[` bracket is already eaten.
|
/// The opening `[` bracket is already eaten.
|
||||||
fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
|
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) {
|
let ty = if self.eat(&token::Semi) {
|
||||||
TyKind::Array(elt_ty, self.parse_anon_const_expr()?)
|
TyKind::Array(elt_ty, self.parse_anon_const_expr()?)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
|
fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
|
||||||
//~| ERROR expected one of `)`, `,`, `->`, `;`, `where`, or `{`, found `]`
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -4,11 +4,5 @@ error: expected type, found `0`
|
||||||
LL | fn foo(a: [0; 1]) {}
|
LL | fn foo(a: [0; 1]) {}
|
||||||
| ^ expected type
|
| ^ expected type
|
||||||
|
|
||||||
error: expected one of `)`, `,`, `->`, `;`, `where`, or `{`, found `]`
|
error: aborting due to previous error
|
||||||
--> $DIR/issue-39616.rs:1:16
|
|
||||||
|
|
|
||||||
LL | fn foo(a: [0; 1]) {}
|
|
||||||
| ^ expected one of `)`, `,`, `->`, `;`, `where`, or `{`
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
// Verify that '>' is not both expected and found at the same time, as it used
|
// Verify that '>' is not both expected and found at the same time, as it used
|
||||||
// to happen in #24780. For example, following should be an error:
|
// to happen in #24780. For example, following should be an error:
|
||||||
// expected one of ..., `>`, ... found `>`
|
// expected one of ..., `>`, ... found `>`. No longer exactly this, but keeping for posterity.
|
||||||
|
|
||||||
fn foo() -> Vec<usize>> {
|
fn foo() -> Vec<usize>> { //~ ERROR unmatched angle bracket
|
||||||
//~^ ERROR expected one of `!`, `+`, `::`, `;`, `where`, or `{`, found `>`
|
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: expected one of `!`, `+`, `::`, `;`, `where`, or `{`, found `>`
|
error: unmatched angle bracket
|
||||||
--> $DIR/issue-24780.rs:5:23
|
--> $DIR/issue-24780.rs:5:23
|
||||||
|
|
|
|
||||||
LL | fn foo() -> Vec<usize>> {
|
LL | fn foo() -> Vec<usize>> {
|
||||||
| ^ expected one of `!`, `+`, `::`, `;`, `where`, or `{`
|
| ^^ help: remove extra angle bracket
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,9 @@ error: expected one of `->`, `;`, `where`, or `{`, found `}`
|
||||||
--> $DIR/issue-6610.rs:1:20
|
--> $DIR/issue-6610.rs:1:20
|
||||||
|
|
|
|
||||||
LL | trait Foo { fn a() }
|
LL | trait Foo { fn a() }
|
||||||
| - ^
|
| - ^ expected one of `->`, `;`, `where`, or `{`
|
||||||
| | |
|
| |
|
||||||
| | expected one of `->`, `;`, `where`, or `{`
|
| while parsing this `fn`
|
||||||
| | the item list ends here
|
|
||||||
| while parsing this item list starting here
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue