about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_resolve/late.rs5
-rw-r--r--src/librustc_resolve/late/diagnostics.rs11
-rw-r--r--src/test/ui/hygiene/missing-self-diag.rs23
-rw-r--r--src/test/ui/hygiene/missing-self-diag.stderr17
4 files changed, 52 insertions, 4 deletions
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index e541920e89e..477e3be5cc2 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -347,7 +347,7 @@ struct DiagnosticMetadata<'ast> {
     currently_processing_generics: bool,
 
     /// The current enclosing function (used for better errors).
-    current_function: Option<Span>,
+    current_function: Option<(FnKind<'ast>, Span)>,
 
     /// A list of labels as of yet unused. Labels will be removed from this map when
     /// they are used (in a `break` or `continue` statement)
@@ -466,7 +466,8 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
             FnKind::Fn(FnCtxt::Free | FnCtxt::Foreign, ..) => FnItemRibKind,
             FnKind::Fn(FnCtxt::Assoc(_), ..) | FnKind::Closure(..) => NormalRibKind,
         };
-        let previous_value = replace(&mut self.diagnostic_metadata.current_function, Some(sp));
+        let previous_value =
+            replace(&mut self.diagnostic_metadata.current_function, Some((fn_kind, sp)));
         debug!("(resolving function) entering function");
         let declaration = fn_kind.decl();
 
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index dc92b465c2b..b1a1f8725a1 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -195,8 +195,15 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
                 _ => "`self` value is a keyword only available in methods with a `self` parameter"
                      .to_string(),
             });
-            if let Some(span) = &self.diagnostic_metadata.current_function {
-                err.span_label(*span, "this function doesn't have a `self` parameter");
+            if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function {
+                // The current function has a `self' parameter, but we were unable to resolve
+                // a reference to `self`. This can only happen if the `self` identifier we
+                // are resolving came from a different hygiene context.
+                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");
+                }
             }
             return (err, Vec::new());
         }
diff --git a/src/test/ui/hygiene/missing-self-diag.rs b/src/test/ui/hygiene/missing-self-diag.rs
new file mode 100644
index 00000000000..f934f793c7f
--- /dev/null
+++ b/src/test/ui/hygiene/missing-self-diag.rs
@@ -0,0 +1,23 @@
+// Regression test for issue #66898
+// Tests that we don't emit a nonsensical error message
+// when a macro invocation tries to access `self` from a function
+// that has a 'self' parameter
+
+pub struct Foo;
+
+macro_rules! call_bar {
+    () => {
+        self.bar(); //~ ERROR expected value
+    }
+}
+
+impl Foo {
+    pub fn foo(&self) {
+        call_bar!();
+    }
+
+    pub fn bar(&self) {
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/missing-self-diag.stderr b/src/test/ui/hygiene/missing-self-diag.stderr
new file mode 100644
index 00000000000..075d6b76bb7
--- /dev/null
+++ b/src/test/ui/hygiene/missing-self-diag.stderr
@@ -0,0 +1,17 @@
+error[E0424]: expected value, found module `self`
+  --> $DIR/missing-self-diag.rs:10:9
+   |
+LL |           self.bar();
+   |           ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+...
+LL | /     pub fn foo(&self) {
+LL | |         call_bar!();
+   | |         ------------ in this macro invocation
+LL | |     }
+   | |_____- this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0424`.