Skip to content

Commit 9765418

Browse files
committed
Tweak self arg not as first argument of a method diagnostic
Mention that `self` is only valid on "associated functions" ``` error: unexpected `self` argument in function --> $DIR/self-in-function-arg.rs:1:15 | LL | fn foo(x:i32, self: i32) -> i32 { self } | ^^^^ not valid as function argument | = note: `self` is only valid as the first argument of an associated function ``` When it is a method, mention it must be first ``` error: unexpected `self` argument in function --> $DIR/trait-fn.rs:4:20 | LL | fn c(foo: u32, self) {} | ^^^^ must be the first associated function argument ```
1 parent 02f5786 commit 9765418

File tree

10 files changed

+80
-43
lines changed

10 files changed

+80
-43
lines changed

src/libsyntax/parse/diagnostics.rs

+45
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,51 @@ impl<'a> Parser<'a> {
594594
}
595595
}
596596

597+
crate fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
598+
let pat = self.parse_pat(Some("argument name"))?;
599+
self.expect(&token::Colon)?;
600+
let ty = self.parse_ty()?;
601+
602+
let mut err = self.diagnostic().struct_span_err_with_code(
603+
pat.span,
604+
"patterns aren't allowed in methods without bodies",
605+
DiagnosticId::Error("E0642".into()),
606+
);
607+
err.span_suggestion_short(
608+
pat.span,
609+
"give this argument a name or use an underscore to ignore it",
610+
"_".to_owned(),
611+
Applicability::MachineApplicable,
612+
);
613+
err.emit();
614+
615+
// Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
616+
let pat = P(Pat {
617+
node: PatKind::Wild,
618+
span: pat.span,
619+
id: ast::DUMMY_NODE_ID
620+
});
621+
Ok((pat, ty))
622+
}
623+
624+
crate fn recover_bad_self_arg(
625+
&mut self,
626+
mut arg: ast::Arg,
627+
is_trait_item: bool,
628+
) -> PResult<'a, ast::Arg> {
629+
let sp = arg.pat.span;
630+
arg.ty.node = TyKind::Err;
631+
let mut err = self.struct_span_err(sp, "unexpected `self` argument in function");
632+
if is_trait_item {
633+
err.span_label(sp, "must be the first associated function argument");
634+
} else {
635+
err.span_label(sp, "not valid as function argument");
636+
err.note("`self` is only valid as the first argument of an associated function");
637+
}
638+
err.emit();
639+
Ok(arg)
640+
}
641+
597642
crate fn consume_block(&mut self, delim: token::DelimToken) {
598643
let mut brace_depth = 0;
599644
loop {

src/libsyntax/parse/parser.rs

+10-37
Original file line numberDiff line numberDiff line change
@@ -1805,50 +1805,23 @@ impl<'a> Parser<'a> {
18051805
}
18061806

18071807
/// This version of parse arg doesn't necessarily require identifier names.
1808-
fn parse_arg_general(&mut self, require_name: bool, is_trait_item: bool,
1809-
allow_c_variadic: bool) -> PResult<'a, Arg> {
1810-
if let Ok(Some(_)) = self.parse_self_arg() {
1811-
let mut err = self.struct_span_err(self.prev_span,
1812-
"unexpected `self` argument in function");
1813-
err.span_label(self.prev_span,
1814-
"`self` is only valid as the first argument of an associated function");
1815-
return Err(err);
1808+
fn parse_arg_general(
1809+
&mut self,
1810+
require_name: bool,
1811+
is_trait_item: bool,
1812+
allow_c_variadic: bool,
1813+
) -> PResult<'a, Arg> {
1814+
if let Ok(Some(arg)) = self.parse_self_arg() {
1815+
return self.recover_bad_self_arg(arg, is_trait_item);
18161816
}
18171817

18181818
let (pat, ty) = if require_name || self.is_named_argument() {
1819-
debug!("parse_arg_general parse_pat (require_name:{})",
1820-
require_name);
1819+
debug!("parse_arg_general parse_pat (require_name:{})", require_name);
18211820
self.eat_incorrect_doc_comment("method arguments");
18221821
let pat = self.parse_pat(Some("argument name"))?;
18231822

18241823
if let Err(mut err) = self.expect(&token::Colon) {
1825-
// If we find a pattern followed by an identifier, it could be an (incorrect)
1826-
// C-style parameter declaration.
1827-
if self.check_ident() && self.look_ahead(1, |t| {
1828-
*t == token::Comma || *t == token::CloseDelim(token::Paren)
1829-
}) {
1830-
let ident = self.parse_ident().unwrap();
1831-
let span = pat.span.with_hi(ident.span.hi());
1832-
1833-
err.span_suggestion(
1834-
span,
1835-
"declare the type after the parameter binding",
1836-
String::from("<identifier>: <type>"),
1837-
Applicability::HasPlaceholders,
1838-
);
1839-
} else if require_name && is_trait_item {
1840-
if let PatKind::Ident(_, ident, _) = pat.node {
1841-
err.span_suggestion(
1842-
pat.span,
1843-
"explicitly ignore parameter",
1844-
format!("_: {}", ident),
1845-
Applicability::MachineApplicable,
1846-
);
1847-
}
1848-
1849-
err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
1850-
}
1851-
1824+
self.argument_without_type(&mut err, pat, require_name, is_trait_item);
18521825
return Err(err);
18531826
}
18541827

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
fn a(&self) { }
22
//~^ ERROR unexpected `self` argument in function
3+
//~| NOTE not valid as function argument
34
//~| NOTE `self` is only valid as the first argument of an associated function
45

56
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
error: unexpected `self` argument in function
2-
--> $DIR/bare-fn-start.rs:1:7
2+
--> $DIR/bare-fn-start.rs:1:6
33
|
44
LL | fn a(&self) { }
5-
| ^^^^ `self` is only valid as the first argument of an associated function
5+
| ^^^^^ not valid as function argument
6+
|
7+
= note: `self` is only valid as the first argument of an associated function
68

79
error: aborting due to previous error
810

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
fn b(foo: u32, &mut self) { }
22
//~^ ERROR unexpected `self` argument in function
3+
//~| NOTE not valid as function argument
34
//~| NOTE `self` is only valid as the first argument of an associated function
45

56
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
error: unexpected `self` argument in function
2-
--> $DIR/bare-fn.rs:1:21
2+
--> $DIR/bare-fn.rs:1:16
33
|
44
LL | fn b(foo: u32, &mut self) { }
5-
| ^^^^ `self` is only valid as the first argument of an associated function
5+
| ^^^^^^^^^ not valid as function argument
6+
|
7+
= note: `self` is only valid as the first argument of an associated function
68

79
error: aborting due to previous error
810

src/test/ui/invalid-self-argument/trait-fn.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ struct Foo {}
33
impl Foo {
44
fn c(foo: u32, self) {}
55
//~^ ERROR unexpected `self` argument in function
6-
//~| NOTE `self` is only valid as the first argument of an associated function
6+
//~| NOTE must be the first associated function argument
77

88
fn good(&mut self, foo: u32) {}
99
}

src/test/ui/invalid-self-argument/trait-fn.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: unexpected `self` argument in function
22
--> $DIR/trait-fn.rs:4:20
33
|
44
LL | fn c(foo: u32, self) {}
5-
| ^^^^ `self` is only valid as the first argument of an associated function
5+
| ^^^^ must be the first associated function argument
66

77
error: aborting due to previous error
88

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn foo(x:i32, self: i32) -> i32 { self } //~ ERROR unexpected `self` argument in function
2+
3+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: unexpected `self` argument in function
2+
--> $DIR/self-in-function-arg.rs:1:15
3+
|
4+
LL | fn foo(x:i32, self: i32) -> i32 { self }
5+
| ^^^^ not valid as function argument
6+
|
7+
= note: `self` is only valid as the first argument of an associated function
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)