Skip to content

Commit 3cd065d

Browse files
committed
macro expansion issue
1 parent 862156d commit 3cd065d

File tree

4 files changed

+124
-55
lines changed

4 files changed

+124
-55
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+11-16
Original file line numberDiff line numberDiff line change
@@ -1546,25 +1546,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15461546
SuggestionText::Reorder => Some("reorder these arguments".to_string()),
15471547
SuggestionText::DidYouMean => Some("did you mean".to_string()),
15481548
};
1549-
if let Some(suggestion_text) = suggestion_text {
1549+
if let Some(suggestion_text) = suggestion_text
1550+
&& !full_call_span.in_external_macro(self.sess().source_map())
1551+
{
15501552
let source_map = self.sess().source_map();
1551-
let (mut suggestion, suggestion_span) = if let Some(call_span) =
1552-
full_call_span.find_ancestor_inside_same_ctxt(error_span)
1553-
{
1554-
("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi()))
1553+
let suggestion_span = if let Some(args_span) = error_span.trim_start(full_call_span) {
1554+
// Span of the braces, e.g. `(a, b, c)`.
1555+
args_span
15551556
} else {
1556-
(
1557-
format!(
1558-
"{}(",
1559-
source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| {
1560-
fn_def_id.map_or("".to_string(), |fn_def_id| {
1561-
tcx.item_name(fn_def_id).to_string()
1562-
})
1563-
})
1564-
),
1565-
error_span,
1566-
)
1557+
// The arg span of a function call that wasn't even given braces
1558+
// like what might happen with delegation reuse.
1559+
// e.g. `reuse HasSelf::method;` should suggest `reuse HasSelf::method($args);`.
1560+
full_call_span.shrink_to_hi()
15671561
};
1562+
let mut suggestion = "(".to_owned();
15681563
let mut needs_comma = false;
15691564
for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
15701565
if needs_comma {

tests/ui/auxiliary/delegate_macro.rs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#[macro_export]
2+
macro_rules! delegate {
3+
($method:ident) => {
4+
<Self>::$method(8)
5+
};
6+
}

tests/ui/not-enough-arguments.rs

+37-15
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
1+
//@ aux-build: delegate_macro.rs
2+
extern crate delegate_macro;
3+
use delegate_macro::delegate;
4+
15
// Check that the only error msg we report is the
26
// mismatch between the # of params, and not other
37
// unrelated errors.
4-
5-
fn foo(a: isize, b: isize, c: isize, d:isize) {
6-
panic!();
8+
fn foo(a: isize, b: isize, c: isize, d: isize) {
9+
panic!();
710
}
811

912
// Check that all arguments are shown in the error message, even if they're across multiple lines.
10-
fn bar(
11-
a: i32,
12-
b: i32,
13-
c: i32,
14-
d: i32,
15-
e: i32,
16-
f: i32,
17-
) {
13+
fn bar(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) {
1814
println!("{}", a);
1915
println!("{}", b);
2016
println!("{}", c);
@@ -23,9 +19,35 @@ fn bar(
2319
println!("{}", f);
2420
}
2521

22+
macro_rules! delegate_local {
23+
($method:ident) => {
24+
<Self>::$method(8)
25+
//~^ ERROR function takes 2 arguments but 1
26+
};
27+
}
28+
29+
macro_rules! delegate_from {
30+
($from:ident, $method:ident) => {
31+
<$from>::$method(8)
32+
//~^ ERROR function takes 2 arguments but 1
33+
};
34+
}
35+
36+
struct Bar;
37+
38+
impl Bar {
39+
fn foo(a: u8, b: u8) {}
40+
fn bar() {
41+
delegate_local!(foo);
42+
delegate!(foo);
43+
//~^ ERROR function takes 2 arguments but 1
44+
delegate_from!(Bar, foo);
45+
}
46+
}
47+
2648
fn main() {
27-
foo(1, 2, 3);
28-
//~^ ERROR function takes 4 arguments but 3
29-
bar(1, 2, 3);
30-
//~^ ERROR function takes 6 arguments but 3
49+
foo(1, 2, 3);
50+
//~^ ERROR function takes 4 arguments but 3
51+
bar(1, 2, 3);
52+
//~^ ERROR function takes 6 arguments but 3
3153
}

tests/ui/not-enough-arguments.stderr

+70-24
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,88 @@
1+
error[E0061]: this function takes 2 arguments but 1 argument was supplied
2+
--> $DIR/not-enough-arguments.rs:24:9
3+
|
4+
LL | <Self>::$method(8)
5+
| ^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing
6+
...
7+
LL | delegate_local!(foo);
8+
| -------------------- in this macro invocation
9+
|
10+
note: associated function defined here
11+
--> $DIR/not-enough-arguments.rs:39:8
12+
|
13+
LL | fn foo(a: u8, b: u8) {}
14+
| ^^^ -----
15+
= note: this error originates in the macro `delegate_local` (in Nightly builds, run with -Z macro-backtrace for more info)
16+
help: provide the argument
17+
|
18+
LL | <Self>::$method(8, /* u8 */)
19+
| ++++++++++
20+
21+
error[E0061]: this function takes 2 arguments but 1 argument was supplied
22+
--> $DIR/not-enough-arguments.rs:42:9
23+
|
24+
LL | delegate!(foo);
25+
| ^^^^^^^^^^^^^^ argument #2 of type `u8` is missing
26+
|
27+
note: associated function defined here
28+
--> $DIR/not-enough-arguments.rs:39:8
29+
|
30+
LL | fn foo(a: u8, b: u8) {}
31+
| ^^^ -----
32+
= note: this error originates in the macro `delegate` (in Nightly builds, run with -Z macro-backtrace for more info)
33+
34+
error[E0061]: this function takes 2 arguments but 1 argument was supplied
35+
--> $DIR/not-enough-arguments.rs:31:9
36+
|
37+
LL | <$from>::$method(8)
38+
| ^^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing
39+
...
40+
LL | delegate_from!(Bar, foo);
41+
| ------------------------ in this macro invocation
42+
|
43+
note: associated function defined here
44+
--> $DIR/not-enough-arguments.rs:39:8
45+
|
46+
LL | fn foo(a: u8, b: u8) {}
47+
| ^^^ -----
48+
= note: this error originates in the macro `delegate_from` (in Nightly builds, run with -Z macro-backtrace for more info)
49+
help: provide the argument
50+
|
51+
LL | <$from>::$method(8, /* u8 */)
52+
| ++++++++++
53+
154
error[E0061]: this function takes 4 arguments but 3 arguments were supplied
2-
--> $DIR/not-enough-arguments.rs:27:3
55+
--> $DIR/not-enough-arguments.rs:49:5
356
|
4-
LL | foo(1, 2, 3);
5-
| ^^^--------- argument #4 of type `isize` is missing
57+
LL | foo(1, 2, 3);
58+
| ^^^--------- argument #4 of type `isize` is missing
659
|
760
note: function defined here
8-
--> $DIR/not-enough-arguments.rs:5:4
61+
--> $DIR/not-enough-arguments.rs:8:4
962
|
10-
LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
11-
| ^^^ -------
63+
LL | fn foo(a: isize, b: isize, c: isize, d: isize) {
64+
| ^^^ --------
1265
help: provide the argument
1366
|
14-
LL | foo(1, 2, 3, /* isize */);
15-
| +++++++++++++
67+
LL | foo(1, 2, 3, /* isize */);
68+
| +++++++++++++
1669

1770
error[E0061]: this function takes 6 arguments but 3 arguments were supplied
18-
--> $DIR/not-enough-arguments.rs:29:3
71+
--> $DIR/not-enough-arguments.rs:51:5
1972
|
20-
LL | bar(1, 2, 3);
21-
| ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing
73+
LL | bar(1, 2, 3);
74+
| ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing
2275
|
2376
note: function defined here
24-
--> $DIR/not-enough-arguments.rs:10:4
77+
--> $DIR/not-enough-arguments.rs:13:4
2578
|
26-
LL | fn bar(
27-
| ^^^
28-
...
29-
LL | d: i32,
30-
| ------
31-
LL | e: i32,
32-
| ------
33-
LL | f: i32,
34-
| ------
79+
LL | fn bar(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) {
80+
| ^^^ ------ ------ ------
3581
help: provide the arguments
3682
|
37-
LL | bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */);
38-
| +++++++++++++++++++++++++++++++++
83+
LL | bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */);
84+
| +++++++++++++++++++++++++++++++++
3985

40-
error: aborting due to 2 previous errors
86+
error: aborting due to 5 previous errors
4187

4288
For more information about this error, try `rustc --explain E0061`.

0 commit comments

Comments
 (0)