about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKivooeo <Kivooeo123@gmail.com>2025-05-02 21:28:11 +0500
committerKivooeo <Kivooeo123@gmail.com>2025-05-07 21:51:41 +0500
commit3cd065d3d358c0124368f21a7deb0e75712c286b (patch)
tree7e0ac5f923d37b886297258e3e745e651c55076f
parent862156d6f25ccb0d915d2a0c8ebab520d05e4f72 (diff)
downloadrust-3cd065d3d358c0124368f21a7deb0e75712c286b.tar.gz
rust-3cd065d3d358c0124368f21a7deb0e75712c286b.zip
macro expansion issue
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs27
-rw-r--r--tests/ui/auxiliary/delegate_macro.rs6
-rw-r--r--tests/ui/not-enough-arguments.rs52
-rw-r--r--tests/ui/not-enough-arguments.stderr94
4 files changed, 124 insertions, 55 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 8b2d9ab2979..0a0967941aa 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1546,25 +1546,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             SuggestionText::Reorder => Some("reorder these arguments".to_string()),
             SuggestionText::DidYouMean => Some("did you mean".to_string()),
         };
-        if let Some(suggestion_text) = suggestion_text {
+        if let Some(suggestion_text) = suggestion_text
+            && !full_call_span.in_external_macro(self.sess().source_map())
+        {
             let source_map = self.sess().source_map();
-            let (mut suggestion, suggestion_span) = if let Some(call_span) =
-                full_call_span.find_ancestor_inside_same_ctxt(error_span)
-            {
-                ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi()))
+            let suggestion_span = if let Some(args_span) = error_span.trim_start(full_call_span) {
+                // Span of the braces, e.g. `(a, b, c)`.
+                args_span
             } else {
-                (
-                    format!(
-                        "{}(",
-                        source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| {
-                            fn_def_id.map_or("".to_string(), |fn_def_id| {
-                                tcx.item_name(fn_def_id).to_string()
-                            })
-                        })
-                    ),
-                    error_span,
-                )
+                // The arg span of a function call that wasn't even given braces
+                // like what might happen with delegation reuse.
+                // e.g. `reuse HasSelf::method;` should suggest `reuse HasSelf::method($args);`.
+                full_call_span.shrink_to_hi()
             };
+            let mut suggestion = "(".to_owned();
             let mut needs_comma = false;
             for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
                 if needs_comma {
diff --git a/tests/ui/auxiliary/delegate_macro.rs b/tests/ui/auxiliary/delegate_macro.rs
new file mode 100644
index 00000000000..0d752e12039
--- /dev/null
+++ b/tests/ui/auxiliary/delegate_macro.rs
@@ -0,0 +1,6 @@
+#[macro_export]
+macro_rules! delegate {
+    ($method:ident) => {
+        <Self>::$method(8)
+    };
+}
diff --git a/tests/ui/not-enough-arguments.rs b/tests/ui/not-enough-arguments.rs
index 4a2ea5e44c7..ec660a1de81 100644
--- a/tests/ui/not-enough-arguments.rs
+++ b/tests/ui/not-enough-arguments.rs
@@ -1,20 +1,16 @@
+//@ aux-build: delegate_macro.rs
+extern crate delegate_macro;
+use delegate_macro::delegate;
+
 // Check that the only error msg we report is the
 // mismatch between the # of params, and not other
 // unrelated errors.
-
-fn foo(a: isize, b: isize, c: isize, d:isize) {
-  panic!();
+fn foo(a: isize, b: isize, c: isize, d: isize) {
+    panic!();
 }
 
 // Check that all arguments are shown in the error message, even if they're across multiple lines.
-fn bar(
-    a: i32,
-    b: i32,
-    c: i32,
-    d: i32,
-    e: i32,
-    f: i32,
-) {
+fn bar(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) {
     println!("{}", a);
     println!("{}", b);
     println!("{}", c);
@@ -23,9 +19,35 @@ fn bar(
     println!("{}", f);
 }
 
+macro_rules! delegate_local {
+    ($method:ident) => {
+        <Self>::$method(8)
+        //~^ ERROR function takes 2 arguments but 1
+    };
+}
+
+macro_rules! delegate_from {
+    ($from:ident, $method:ident) => {
+        <$from>::$method(8)
+        //~^ ERROR function takes 2 arguments but 1
+    };
+}
+
+struct Bar;
+
+impl Bar {
+    fn foo(a: u8, b: u8) {}
+    fn bar() {
+        delegate_local!(foo);
+        delegate!(foo);
+        //~^ ERROR function takes 2 arguments but 1
+        delegate_from!(Bar, foo);
+    }
+}
+
 fn main() {
-  foo(1, 2, 3);
-  //~^ ERROR function takes 4 arguments but 3
-  bar(1, 2, 3);
-  //~^ ERROR function takes 6 arguments but 3
+    foo(1, 2, 3);
+    //~^ ERROR function takes 4 arguments but 3
+    bar(1, 2, 3);
+    //~^ ERROR function takes 6 arguments but 3
 }
diff --git a/tests/ui/not-enough-arguments.stderr b/tests/ui/not-enough-arguments.stderr
index 099d82eb935..908d0273bbe 100644
--- a/tests/ui/not-enough-arguments.stderr
+++ b/tests/ui/not-enough-arguments.stderr
@@ -1,42 +1,88 @@
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/not-enough-arguments.rs:24:9
+   |
+LL |         <Self>::$method(8)
+   |         ^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing
+...
+LL |         delegate_local!(foo);
+   |         -------------------- in this macro invocation
+   |
+note: associated function defined here
+  --> $DIR/not-enough-arguments.rs:39:8
+   |
+LL |     fn foo(a: u8, b: u8) {}
+   |        ^^^        -----
+   = note: this error originates in the macro `delegate_local` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: provide the argument
+   |
+LL |         <Self>::$method(8, /* u8 */)
+   |                          ++++++++++
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/not-enough-arguments.rs:42:9
+   |
+LL |         delegate!(foo);
+   |         ^^^^^^^^^^^^^^ argument #2 of type `u8` is missing
+   |
+note: associated function defined here
+  --> $DIR/not-enough-arguments.rs:39:8
+   |
+LL |     fn foo(a: u8, b: u8) {}
+   |        ^^^        -----
+   = note: this error originates in the macro `delegate` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/not-enough-arguments.rs:31:9
+   |
+LL |         <$from>::$method(8)
+   |         ^^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing
+...
+LL |         delegate_from!(Bar, foo);
+   |         ------------------------ in this macro invocation
+   |
+note: associated function defined here
+  --> $DIR/not-enough-arguments.rs:39:8
+   |
+LL |     fn foo(a: u8, b: u8) {}
+   |        ^^^        -----
+   = note: this error originates in the macro `delegate_from` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: provide the argument
+   |
+LL |         <$from>::$method(8, /* u8 */)
+   |                           ++++++++++
+
 error[E0061]: this function takes 4 arguments but 3 arguments were supplied
-  --> $DIR/not-enough-arguments.rs:27:3
+  --> $DIR/not-enough-arguments.rs:49:5
    |
-LL |   foo(1, 2, 3);
-   |   ^^^--------- argument #4 of type `isize` is missing
+LL |     foo(1, 2, 3);
+   |     ^^^--------- argument #4 of type `isize` is missing
    |
 note: function defined here
-  --> $DIR/not-enough-arguments.rs:5:4
+  --> $DIR/not-enough-arguments.rs:8:4
    |
-LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
-   |    ^^^                               -------
+LL | fn foo(a: isize, b: isize, c: isize, d: isize) {
+   |    ^^^                               --------
 help: provide the argument
    |
-LL |   foo(1, 2, 3, /* isize */);
-   |              +++++++++++++
+LL |     foo(1, 2, 3, /* isize */);
+   |                +++++++++++++
 
 error[E0061]: this function takes 6 arguments but 3 arguments were supplied
-  --> $DIR/not-enough-arguments.rs:29:3
+  --> $DIR/not-enough-arguments.rs:51:5
    |
-LL |   bar(1, 2, 3);
-   |   ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing
+LL |     bar(1, 2, 3);
+   |     ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing
    |
 note: function defined here
-  --> $DIR/not-enough-arguments.rs:10:4
+  --> $DIR/not-enough-arguments.rs:13:4
    |
-LL | fn bar(
-   |    ^^^
-...
-LL |     d: i32,
-   |     ------
-LL |     e: i32,
-   |     ------
-LL |     f: i32,
-   |     ------
+LL | fn bar(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) {
+   |    ^^^                         ------  ------  ------
 help: provide the arguments
    |
-LL |   bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */);
-   |              +++++++++++++++++++++++++++++++++
+LL |     bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */);
+   |                +++++++++++++++++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0061`.