From 235905c080bf953a522ff86d4fec6134ac4fb371 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 6 Aug 2018 18:14:57 +0100 Subject: Fix handling of trait methods with bodies and improve efficiency --- src/libsyntax/parse/parser.rs | 49 ++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 19 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5a2fd5f0145..57eb1f52fb7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1744,7 +1744,16 @@ impl<'a> Parser<'a> { fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> { maybe_whole!(self, NtArg, |x| x); - let parser_snapshot_before_pat = self.clone(); + // If we see `ident :`, then we know that the argument is just of the + // form `type`, which means we won't need to recover from parsing a + // pattern and so we don't need to store a parser snapshot. + let parser_snapshot_before_pat = if + self.look_ahead(1, |t| t.is_ident()) && + self.look_ahead(2, |t| t == &token::Colon) { + None + } else { + Some(self.clone()) + }; // We're going to try parsing the argument as a pattern (even if it's not // allowed, such as for trait methods without bodies). This way we can provide @@ -1755,29 +1764,31 @@ impl<'a> Parser<'a> { (pat, self.parse_ty()?) }; - let is_named_argument = self.is_named_argument(); match pat_arg { Ok((pat, ty)) => { Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID }) } Err(mut err) => { - if require_name || is_named_argument { - Err(err) - } else { - err.cancel(); - // Recover from attempting to parse the argument as a pattern. This means - // the type is alone, with no name, e.g. `fn foo(u32)`. - mem::replace(self, parser_snapshot_before_pat); - debug!("parse_arg_general ident_to_pat"); - let ident = Ident::new(keywords::Invalid.name(), self.prev_span); - let ty = self.parse_ty()?; - let pat = P(Pat { - id: ast::DUMMY_NODE_ID, - node: PatKind::Ident( - BindingMode::ByValue(Mutability::Immutable), ident, None), - span: ty.span, - }); - Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID }) + match (require_name || self.is_named_argument(), parser_snapshot_before_pat) { + (true, _) | (_, None) => { + Err(err) + } + (false, Some(parser_snapshot_before_pat)) => { + err.cancel(); + // Recover from attempting to parse the argument as a pattern. This means + // the type is alone, with no name, e.g. `fn foo(u32)`. + mem::replace(self, parser_snapshot_before_pat); + debug!("parse_arg_general ident_to_pat"); + let ident = Ident::new(keywords::Invalid.name(), self.prev_span); + let ty = self.parse_ty()?; + let pat = P(Pat { + id: ast::DUMMY_NODE_ID, + node: PatKind::Ident( + BindingMode::ByValue(Mutability::Immutable), ident, None), + span: ty.span, + }); + Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID }) + } } } } -- cgit 1.4.1-3-g733a5