Skip to content

Commit f13b8fb

Browse files
committed
Suggest calling method when first argument is self
1 parent 8960acf commit f13b8fb

File tree

6 files changed

+95
-14
lines changed

6 files changed

+95
-14
lines changed

src/doc/rustc-guide

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -719,8 +719,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
719719
// These items live in both the type and value namespaces.
720720
ItemKind::Struct(ref vdata, _) => {
721721
// Define a name in the type namespace.
722-
let def_id = self.r.definitions.local_def_id(item.id);
723-
let res = Res::Def(DefKind::Struct, def_id);
722+
let item_def_id = self.r.definitions.local_def_id(item.id);
723+
let res = Res::Def(DefKind::Struct, item_def_id);
724724
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
725725

726726
// Record field names for error reporting.
@@ -757,12 +757,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
757757
}
758758

759759
ItemKind::Union(ref vdata, _) => {
760-
let def_id = self.r.definitions.local_def_id(item.id);
761-
let res = Res::Def(DefKind::Union, def_id);
760+
let item_def_id = self.r.definitions.local_def_id(item.id);
761+
let res = Res::Def(DefKind::Union, item_def_id);
762762
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
763763

764764
// Record field names for error reporting.
765-
self.insert_field_names_local(def_id, vdata);
765+
self.insert_field_names_local(item_def_id, vdata);
766766
}
767767

768768
ItemKind::Impl(.., ref impl_items) => {

src/librustc_resolve/late.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ struct DiagnosticMetadata {
345345
/// The current self item if inside an ADT (used for better errors).
346346
current_self_item: Option<NodeId>,
347347

348-
/// The current enclosing funciton (used for better errors).
348+
/// The current enclosing function (used for better errors).
349349
current_function: Option<Span>,
350350

351351
/// A list of labels as of yet unused. Labels will be removed from this map when

src/librustc_resolve/late/diagnostics.rs

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,37 @@ impl<'a> LateResolutionVisitor<'a, '_> {
253253
}
254254
return (err, candidates);
255255
}
256+
257+
// Check if the first argument is `self` and suggest calling a method.
258+
let mut has_self_arg = false;
259+
if let PathSource::Expr(parent) = source {
260+
match &parent.map(|p| &p.kind) {
261+
Some(ExprKind::Call(_, args)) if args.len() > 0 => {
262+
let mut expr_kind = &args.first().unwrap().kind;
263+
loop {
264+
match expr_kind {
265+
ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => {
266+
has_self_arg = arg_name.segments[0].ident.name == kw::SelfLower;
267+
break;
268+
},
269+
ExprKind::AddrOf(_, _, expr) => { expr_kind = &expr.kind; }
270+
_ => break,
271+
}
272+
}
273+
}
274+
_ => (),
275+
}
276+
};
277+
278+
if has_self_arg {
279+
err.span_suggestion(
280+
span,
281+
&"try calling method instead of passing `self` as parameter",
282+
format!("self.{}", path_str),
283+
Applicability::MachineApplicable,
284+
);
285+
return (err, candidates);
286+
}
256287
}
257288

258289
// Try Levenshtein algorithm.
@@ -553,13 +584,13 @@ impl<'a> LateResolutionVisitor<'a, '_> {
553584
// Look for associated items in the current trait.
554585
if let Some((module, _)) = self.current_trait_ref {
555586
if let Ok(binding) = self.r.resolve_ident_in_module(
556-
ModuleOrUniformRoot::Module(module),
557-
ident,
558-
ns,
559-
&self.parent_scope,
560-
false,
561-
module.span,
562-
) {
587+
ModuleOrUniformRoot::Module(module),
588+
ident,
589+
ns,
590+
&self.parent_scope,
591+
false,
592+
module.span,
593+
) {
563594
let res = binding.res();
564595
if filter_fn(res) {
565596
return Some(if self.r.has_self.contains(&res.def_id()) {

src/test/ui/self/suggest-self-2.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
struct Foo {}
2+
3+
impl Foo {
4+
fn foo(&self) {
5+
bar(self);
6+
//~^ ERROR cannot find function `bar` in this scope
7+
//~| HELP try calling method instead of passing `self` as parameter
8+
9+
10+
bar(&self);
11+
//~^ ERROR cannot find function `bar` in this scope
12+
//~| HELP try calling method instead of passing `self` as parameter
13+
14+
bar();
15+
//~^ ERROR cannot find function `bar` in this scope
16+
17+
self.bar();
18+
//~^ ERROR no method named `bar` found for type
19+
}
20+
}
21+
22+
fn main() {}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error[E0425]: cannot find function `bar` in this scope
2+
--> $DIR/suggest-self-2.rs:5:9
3+
|
4+
LL | bar(self);
5+
| ^^^ help: try calling method instead of passing `self` as parameter: `self.bar`
6+
7+
error[E0425]: cannot find function `bar` in this scope
8+
--> $DIR/suggest-self-2.rs:10:9
9+
|
10+
LL | bar(&self);
11+
| ^^^ help: try calling method instead of passing `self` as parameter: `self.bar`
12+
13+
error[E0425]: cannot find function `bar` in this scope
14+
--> $DIR/suggest-self-2.rs:14:9
15+
|
16+
LL | bar();
17+
| ^^^ not found in this scope
18+
19+
error[E0599]: no method named `bar` found for type `&Foo` in the current scope
20+
--> $DIR/suggest-self-2.rs:17:14
21+
|
22+
LL | self.bar();
23+
| ^^^ method not found in `&Foo`
24+
25+
error: aborting due to 4 previous errors
26+
27+
Some errors have detailed explanations: E0425, E0599.
28+
For more information about an error, try `rustc --explain E0425`.

0 commit comments

Comments
 (0)