Skip to content

Commit 9784d35

Browse files
committed
parser: Tweak function parameter parsing to avoid rollback on succesfull path
1 parent 2fa1390 commit 9784d35

File tree

1 file changed

+26
-36
lines changed

1 file changed

+26
-36
lines changed

src/libsyntax/parse/parser.rs

+26-36
Original file line numberDiff line numberDiff line change
@@ -1780,27 +1780,32 @@ impl<'a> Parser<'a> {
17801780
(pat, self.parse_ty()?)
17811781
} else {
17821782
debug!("parse_arg_general ident_to_pat");
1783+
let parser_snapshot_before_ty = self.clone();
1784+
let mut ty = self.parse_ty();
1785+
if ty.is_ok() && self.token == token::Colon {
1786+
// This wasn't actually a type, but a pattern looking like a type,
1787+
// so we are going to rollback and re-parse for recovery.
1788+
ty = self.unexpected();
1789+
}
1790+
match ty {
1791+
Ok(ty) => {
1792+
let ident = Ident::new(keywords::Invalid.name(), self.prev_span);
1793+
let pat = P(Pat {
1794+
id: ast::DUMMY_NODE_ID,
1795+
node: PatKind::Ident(
1796+
BindingMode::ByValue(Mutability::Immutable), ident, None),
1797+
span: ty.span,
1798+
});
1799+
(pat, ty)
1800+
}
1801+
Err(mut err) => {
1802+
// Recover from attempting to parse the argument as a type without pattern.
1803+
err.cancel();
1804+
mem::replace(self, parser_snapshot_before_ty);
1805+
let pat = self.parse_pat()?;
1806+
self.expect(&token::Colon)?;
1807+
let ty = self.parse_ty()?;
17831808

1784-
let parser_snapshot_before_pat = self.clone();
1785-
1786-
// Once we can use edition 2018 in the compiler,
1787-
// replace this with real try blocks.
1788-
macro_rules! try_block {
1789-
($($inside:tt)*) => (
1790-
(||{ ::std::ops::Try::from_ok({ $($inside)* }) })()
1791-
)
1792-
}
1793-
1794-
// We're going to try parsing the argument as a pattern (even though it's not
1795-
// allowed). This way we can provide better errors to the user.
1796-
let pat_arg: PResult<'a, _> = try_block! {
1797-
let pat = self.parse_pat()?;
1798-
self.expect(&token::Colon)?;
1799-
(pat, self.parse_ty()?)
1800-
};
1801-
1802-
match pat_arg {
1803-
Ok((pat, ty)) => {
18041809
let mut err = self.diagnostic().struct_span_err_with_code(
18051810
pat.span,
18061811
"patterns aren't allowed in methods without bodies",
@@ -1813,6 +1818,7 @@ impl<'a> Parser<'a> {
18131818
Applicability::MachineApplicable,
18141819
);
18151820
err.emit();
1821+
18161822
// Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
18171823
let pat = P(Pat {
18181824
node: PatKind::Wild,
@@ -1821,22 +1827,6 @@ impl<'a> Parser<'a> {
18211827
});
18221828
(pat, ty)
18231829
}
1824-
Err(mut err) => {
1825-
err.cancel();
1826-
// Recover from attempting to parse the argument as a pattern. This means
1827-
// the type is alone, with no name, e.g. `fn foo(u32)`.
1828-
mem::replace(self, parser_snapshot_before_pat);
1829-
debug!("parse_arg_general ident_to_pat");
1830-
let ident = Ident::new(keywords::Invalid.name(), self.prev_span);
1831-
let ty = self.parse_ty()?;
1832-
let pat = P(Pat {
1833-
id: ast::DUMMY_NODE_ID,
1834-
node: PatKind::Ident(
1835-
BindingMode::ByValue(Mutability::Immutable), ident, None),
1836-
span: ty.span,
1837-
});
1838-
(pat, ty)
1839-
}
18401830
}
18411831
};
18421832

0 commit comments

Comments
 (0)