Skip to content

Commit

Permalink
Suggest adding &self when accessing self in static assoc fn
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Aug 14, 2020
1 parent 643258f commit 360388b
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 41 deletions.
7 changes: 7 additions & 0 deletions src/librustc_ast/visit.rs
Expand Up @@ -50,6 +50,13 @@ impl<'a> FnKind<'a> {
}
}

pub fn ident(&self) -> Option<&Ident> {
match self {
FnKind::Fn(_, ident, ..) => Some(ident),
_ => None,
}
}

pub fn decl(&self) -> &'a FnDecl {
match self {
FnKind::Fn(_, _, sig, _, _) => &sig.decl,
Expand Down
61 changes: 46 additions & 15 deletions src/librustc_resolve/late/diagnostics.rs
Expand Up @@ -175,8 +175,9 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
let code = source.error_code(res.is_some());
let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code);

let is_assoc_fn = self.self_type_is_available(span);
// Emit help message for fake-self from other languages (e.g., `this` in Javascript).
if ["this", "my"].contains(&&*item_str.as_str()) && self.self_type_is_available(span) {
if ["this", "my"].contains(&&*item_str.as_str()) && is_assoc_fn {
err.span_suggestion_short(
span,
"you might have meant to use `self` here instead",
Expand All @@ -187,25 +188,24 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
if let Some((FnKind::Fn(_, _, sig, ..), fn_span)) =
&self.diagnostic_metadata.current_function
{
if let Some(param) = sig.decl.inputs.get(0) {
err.span_suggestion_verbose(
param.span.shrink_to_lo(),
"you are also missing a `self` receiver argument",
"&self, ".to_string(),
Applicability::MaybeIncorrect,
);
let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) {
(param.span.shrink_to_lo(), "&self, ")
} else {
err.span_suggestion_verbose(
(
self.r
.session
.source_map()
.span_through_char(*fn_span, '(')
.shrink_to_hi(),
"you are also missing a `self` receiver argument",
"&self".to_string(),
Applicability::MaybeIncorrect,
);
}
"&self",
)
};
err.span_suggestion_verbose(
span,
"you are also missing a `self` receiver argument",
sugg.to_string(),
Applicability::MaybeIncorrect,
);
}
}
}
Expand Down Expand Up @@ -236,7 +236,38 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
if fn_kind.decl().inputs.get(0).map(|p| p.is_self()).unwrap_or(false) {
err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
} else {
err.span_label(*span, "this function doesn't have a `self` parameter");
let doesnt = if is_assoc_fn {
let (span, sugg) = fn_kind
.decl()
.inputs
.get(0)
.map(|p| (p.span.shrink_to_lo(), "&self, "))
.unwrap_or_else(|| {
(
self.r
.session
.source_map()
.span_through_char(*span, '(')
.shrink_to_hi(),
"&self",
)
});
err.span_suggestion_verbose(
span,
"add a `self` receiver parameter to make the associated `fn` a method",
sugg.to_string(),
Applicability::MaybeIncorrect,
);
"doesn't"
} else {
"can't"
};
if let Some(ident) = fn_kind.ident() {
err.span_label(
ident.span,
&format!("this function {} have a `self` parameter", doesnt),
);
}
}
}
return (err, Vec::new());
Expand Down
4 changes: 4 additions & 0 deletions src/test/ui/error-codes/E0424.rs
Expand Up @@ -6,6 +6,10 @@ impl Foo {
fn foo() {
self.bar(); //~ ERROR E0424
}

fn baz(_: i32) {
self.bar(); //~ ERROR E0424
}
}

fn main () {
Expand Down
40 changes: 28 additions & 12 deletions src/test/ui/error-codes/E0424.stderr
@@ -1,21 +1,37 @@
error[E0424]: expected value, found module `self`
--> $DIR/E0424.rs:7:9
|
LL | / fn foo() {
LL | | self.bar();
| | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
LL | | }
| |_____- this function doesn't have a `self` parameter
LL | fn foo() {
| --- this function doesn't have a `self` parameter
LL | self.bar();
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
|
help: add a `self` receiver parameter to make the associated `fn` a method
|
LL | fn foo(&self) {
| ^^^^^

error[E0424]: expected value, found module `self`
--> $DIR/E0424.rs:11:9
|
LL | fn baz(_: i32) {
| --- this function doesn't have a `self` parameter
LL | self.bar();
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
|
help: add a `self` receiver parameter to make the associated `fn` a method
|
LL | fn baz(&self, _: i32) {
| ^^^^^^

error[E0424]: expected unit struct, unit variant or constant, found module `self`
--> $DIR/E0424.rs:12:9
--> $DIR/E0424.rs:16:9
|
LL | / fn main () {
LL | | let self = "self";
| | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed
LL | | }
| |_- this function doesn't have a `self` parameter
LL | fn main () {
| ---- this function can't have a `self` parameter
LL | let self = "self";
| ^^^^ `self` value is a keyword and may not be bound to variables or shadowed

error: aborting due to 2 previous errors
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0424`.
27 changes: 13 additions & 14 deletions src/test/ui/resolve/issue-2356.stderr
Expand Up @@ -70,14 +70,15 @@ LL | purr();
error[E0424]: expected value, found module `self`
--> $DIR/issue-2356.rs:65:8
|
LL | / fn meow() {
LL | | if self.whiskers > 3 {
| | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
LL | |
LL | | println!("MEOW");
LL | | }
LL | | }
| |___- this function doesn't have a `self` parameter
LL | fn meow() {
| ---- this function doesn't have a `self` parameter
LL | if self.whiskers > 3 {
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
|
help: add a `self` receiver parameter to make the associated `fn` a method
|
LL | fn meow(&self) {
| ^^^^^

error[E0425]: cannot find function `grow_older` in this scope
--> $DIR/issue-2356.rs:72:5
Expand Down Expand Up @@ -112,12 +113,10 @@ LL | purr_louder();
error[E0424]: expected value, found module `self`
--> $DIR/issue-2356.rs:92:5
|
LL | / fn main() {
LL | | self += 1;
| | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
LL | |
LL | | }
| |_- this function doesn't have a `self` parameter
LL | fn main() {
| ---- this function can't have a `self` parameter
LL | self += 1;
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter

error: aborting due to 17 previous errors

Expand Down

0 comments on commit 360388b

Please sign in to comment.