about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJanusz Marcinkiewicz <virrages@gmail.com>2019-11-30 18:59:51 +0100
committerJanusz Marcinkiewicz <virrages@gmail.com>2019-12-23 11:57:08 +0100
commit8d189ed2f1db856adc9745099d078d46fe54a087 (patch)
tree6b321df808d53123376b3301bb13d95fdf4c7444
parenta916ac22b9f7f1f0f7aba0a41a789b3ecd765018 (diff)
downloadrust-8d189ed2f1db856adc9745099d078d46fe54a087.tar.gz
rust-8d189ed2f1db856adc9745099d078d46fe54a087.zip
Suggest calling method when first argument is `self`
m---------src/doc/rustc-guide0
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs10
-rw-r--r--src/librustc_resolve/late.rs2
-rw-r--r--src/librustc_resolve/late/diagnostics.rs31
-rw-r--r--src/test/ui/self/suggest-self-2.rs22
-rw-r--r--src/test/ui/self/suggest-self-2.stderr28
6 files changed, 87 insertions, 6 deletions
diff --git a/src/doc/rustc-guide b/src/doc/rustc-guide
-Subproject 7c56708aab7986ca390221e8e8902f7de7f9b07
+Subproject 934380b7cfceaaa4e1b9bb0de4a372f32725520
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index fed4202d961..c356a7e31b1 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -759,8 +759,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             // These items live in both the type and value namespaces.
             ItemKind::Struct(ref vdata, _) => {
                 // Define a name in the type namespace.
-                let def_id = self.r.definitions.local_def_id(item.id);
-                let res = Res::Def(DefKind::Struct, def_id);
+                let item_def_id = self.r.definitions.local_def_id(item.id);
+                let res = Res::Def(DefKind::Struct, item_def_id);
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
 
                 // Record field names for error reporting.
@@ -798,12 +798,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             }
 
             ItemKind::Union(ref vdata, _) => {
-                let def_id = self.r.definitions.local_def_id(item.id);
-                let res = Res::Def(DefKind::Union, def_id);
+                let item_def_id = self.r.definitions.local_def_id(item.id);
+                let res = Res::Def(DefKind::Union, item_def_id);
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
 
                 // Record field names for error reporting.
-                self.insert_field_names_local(def_id, vdata);
+                self.insert_field_names_local(item_def_id, vdata);
             }
 
             ItemKind::Trait(..) => {
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 898ab6ae322..dd1bef0c297 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -345,7 +345,7 @@ struct DiagnosticMetadata {
     /// The current self item if inside an ADT (used for better errors).
     current_self_item: Option<NodeId>,
 
-    /// The current enclosing funciton (used for better errors).
+    /// The current enclosing function (used for better errors).
     current_function: Option<Span>,
 
     /// A list of labels as of yet unused. Labels will be removed from this map when
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index 6fb5c2f2de3..e40c6fa7088 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -259,6 +259,37 @@ impl<'a> LateResolutionVisitor<'a, '_> {
                 }
                 return (err, candidates);
             }
+
+            // Check if the first argument is `self` and suggest calling a method.
+            let mut has_self_arg = false;
+            if let PathSource::Expr(parent) = source {
+                match &parent.map(|p| &p.kind) {
+                    Some(ExprKind::Call(_, args)) if args.len() > 0 => {
+                        let mut expr_kind = &args.first().unwrap().kind;
+                        loop {
+                            match expr_kind {
+                                ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => {
+                                    has_self_arg = arg_name.segments[0].ident.name == kw::SelfLower;
+                                    break;
+                                },
+                                ExprKind::AddrOf(_, _, expr) => { expr_kind = &expr.kind; }
+                                _ => break,
+                            }
+                        }
+                    }
+                    _ => (),
+                }
+            };
+
+            if has_self_arg {
+                err.span_suggestion(
+                    span,
+                    &"try calling method instead of passing `self` as parameter",
+                    format!("self.{}", path_str),
+                    Applicability::MachineApplicable,
+                );
+                return (err, candidates);
+            }
         }
 
         // Try Levenshtein algorithm.
diff --git a/src/test/ui/self/suggest-self-2.rs b/src/test/ui/self/suggest-self-2.rs
new file mode 100644
index 00000000000..1926ebe4b83
--- /dev/null
+++ b/src/test/ui/self/suggest-self-2.rs
@@ -0,0 +1,22 @@
+struct Foo {}
+
+impl Foo {
+    fn foo(&self) {
+        bar(self);
+        //~^ ERROR cannot find function `bar` in this scope
+        //~| HELP try calling method instead of passing `self` as parameter
+
+
+        bar(&self);
+        //~^ ERROR cannot find function `bar` in this scope
+        //~| HELP try calling method instead of passing `self` as parameter
+
+        bar();
+        //~^ ERROR cannot find function `bar` in this scope
+
+        self.bar();
+        //~^ ERROR no method named `bar` found for type
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/self/suggest-self-2.stderr b/src/test/ui/self/suggest-self-2.stderr
new file mode 100644
index 00000000000..84dbaa96378
--- /dev/null
+++ b/src/test/ui/self/suggest-self-2.stderr
@@ -0,0 +1,28 @@
+error[E0425]: cannot find function `bar` in this scope
+  --> $DIR/suggest-self-2.rs:5:9
+   |
+LL |         bar(self);
+   |         ^^^ help: try calling method instead of passing `self` as parameter: `self.bar`
+
+error[E0425]: cannot find function `bar` in this scope
+  --> $DIR/suggest-self-2.rs:10:9
+   |
+LL |         bar(&self);
+   |         ^^^ help: try calling method instead of passing `self` as parameter: `self.bar`
+
+error[E0425]: cannot find function `bar` in this scope
+  --> $DIR/suggest-self-2.rs:14:9
+   |
+LL |         bar();
+   |         ^^^ not found in this scope
+
+error[E0599]: no method named `bar` found for type `&Foo` in the current scope
+  --> $DIR/suggest-self-2.rs:17:14
+   |
+LL |         self.bar();
+   |              ^^^ method not found in `&Foo`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0425, E0599.
+For more information about an error, try `rustc --explain E0425`.