mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-01 11:13:43 +00:00
Emit an error during parsing
This commit is contained in:
parent
a478cd41e3
commit
e4c3b49fe7
@ -336,24 +336,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
|
||||
self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness);
|
||||
self.check_trait_fn_not_const(sig.header.constness);
|
||||
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
|
||||
if mut_ident {
|
||||
if block.is_none() {
|
||||
if block.is_none() {
|
||||
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
|
||||
if mut_ident {
|
||||
self.session.buffer_lint(
|
||||
lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
trait_item.id, span,
|
||||
"patterns aren't allowed in trait methods");
|
||||
} else {
|
||||
struct_span_err!(self.session, span, E0642,
|
||||
"patterns aren't allowed in trait methods").emit();
|
||||
}
|
||||
} else {
|
||||
let mut err = struct_span_err!(self.session, span, E0642,
|
||||
"patterns aren't allowed in trait methods");
|
||||
let suggestion = "give this argument a name or use an \
|
||||
underscore to ignore it instead of using a \
|
||||
tuple pattern";
|
||||
err.span_suggestion(span, suggestion, "_".to_owned());
|
||||
err.emit();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
||||
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 })
|
||||
}
|
||||
// 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 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
|
||||
|
@ -1,23 +1,22 @@
|
||||
error[E0642]: patterns aren't allowed in trait methods
|
||||
error: patterns aren't allowed in trait methods
|
||||
--> $DIR/E0642.rs:12:12
|
||||
|
|
||||
LL | fn foo((x, y): (i32, i32)); //~ ERROR patterns aren't allowed in trait methods
|
||||
| ^^^^^^
|
||||
help: give this argument a name or use an underscore to ignore it instead of using a tuple pattern
|
||||
help: give this argument a name or use an underscore to ignore it
|
||||
|
|
||||
LL | fn foo(_: (i32, i32)); //~ ERROR patterns aren't allowed in trait methods
|
||||
| ^
|
||||
|
||||
error[E0642]: patterns aren't allowed in trait methods
|
||||
error: patterns aren't allowed in trait methods
|
||||
--> $DIR/E0642.rs:16:12
|
||||
|
|
||||
LL | fn bar((x, y): (i32, i32)) {} //~ ERROR patterns aren't allowed in trait methods
|
||||
| ^^^^^^
|
||||
help: give this argument a name or use an underscore to ignore it instead of using a tuple pattern
|
||||
help: give this argument a name or use an underscore to ignore it
|
||||
|
|
||||
LL | fn bar(_: (i32, i32)) {} //~ ERROR patterns aren't allowed in trait methods
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0642`.
|
||||
|
Loading…
Reference in New Issue
Block a user