diff options
| author | varkor <github@varkor.com> | 2018-08-09 23:23:08 +0100 |
|---|---|---|
| committer | varkor <github@varkor.com> | 2018-08-11 21:08:24 +0100 |
| commit | e4c3b49fe790dd23f32acace8157d897d31c0cb3 (patch) | |
| tree | 2a7cc6356768ea527ea54277eea867dea2cefdcf /src/libsyntax/parse | |
| parent | a478cd41e3f203ec531bfce7efb8fc602aad5c7d (diff) | |
| download | rust-e4c3b49fe790dd23f32acace8157d897d31c0cb3.tar.gz rust-e4c3b49fe790dd23f32acace8157d897d31c0cb3.zip | |
Emit an error during parsing
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 104 |
1 files changed, 62 insertions, 42 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a1dbe93fdfe..9a49d705c46 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1744,54 +1744,74 @@ impl<'a> Parser<'a> { fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> { maybe_whole!(self, NtArg, |x| x); - // If we see `ident :`, then we know that the argument is not 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 - // better errors to the user. - let pat_arg: PResult<'a, (P<Pat>, P<Ty>)> = do catch { + let (pat, ty) = if require_name || self.is_named_argument() { + debug!("parse_arg_general parse_pat (require_name:{})", + require_name); let pat = self.parse_pat()?; + self.expect(&token::Colon)?; (pat, self.parse_ty()?) - }; + } else { + debug!("parse_arg_general ident_to_pat"); + + // If we see `ident :`, then we know that the argument is not 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()) + }; - match pat_arg { - Ok((pat, ty)) => { - Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID }) - } - Err(mut err) => { - 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 }) - } + // We're going to try parsing the argument as a pattern (even though it's not + // allowed). This way we can provide better errors to the user. + let pat_arg: PResult<'a, _> = do catch { + let pat = self.parse_pat()?; + self.expect(&token::Colon)?; + (pat, self.parse_ty()?) + }; + + match pat_arg { + Ok((pat, ty)) => { + let mut err = self.diagnostic() + .struct_span_err(pat.span, "patterns aren't allowed in trait methods"); + err.span_suggestion_short_with_applicability( + pat.span, + "give this argument a name or use an underscore to ignore it", + "_".to_owned(), + Applicability::MachineApplicable, + ); + err.emit(); + // Pretend the pattern is `_`, to avoid duplicate errors from AST validation. + let pat = P(Pat { + node: PatKind::Wild, + span: pat.span, + id: ast::DUMMY_NODE_ID + }); + (pat, ty) + } + Err(mut err) => { + 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.unwrap()); + 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, + }); + (pat, ty) } } - } + }; + + Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID }) } /// Parse a single function argument |
