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();
- }
- });
+ });
+ }
}
}
}
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
-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`.