Emit error for pattern arguments in trait methods
The error and check for this already existed, but the parser didn't try to parse trait method arguments as patterns, so the error was never emitted. This surfaces the error, so we get better errors than simple parse errors.
This commit is contained in:
@@ -1371,7 +1371,7 @@ impl<'a> Parser<'a> {
|
||||
let ident = self.parse_ident()?;
|
||||
let mut generics = self.parse_generics()?;
|
||||
|
||||
let d = self.parse_fn_decl_with_self(|p: &mut Parser<'a>|{
|
||||
let d = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| {
|
||||
// This is somewhat dubious; We don't want to allow
|
||||
// argument names to be left off if there is a
|
||||
// definition...
|
||||
@@ -1744,30 +1744,43 @@ impl<'a> Parser<'a> {
|
||||
fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> {
|
||||
maybe_whole!(self, NtArg, |x| x);
|
||||
|
||||
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()?;
|
||||
let parser_snapshot_before_pat = 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 = self.parse_pat()?;
|
||||
self.expect(&token::Colon)?;
|
||||
(pat, self.parse_ty()?)
|
||||
} else {
|
||||
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,
|
||||
})
|
||||
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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a single function argument
|
||||
|
||||
Reference in New Issue
Block a user