Skip to content

Commit 195d837

Browse files
committed
When suggesting fn call use an appropriate number of placeholder arguments
1 parent 94fe8a3 commit 195d837

File tree

5 files changed

+148
-16
lines changed

5 files changed

+148
-16
lines changed

src/librustc_typeck/check/mod.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3833,19 +3833,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38333833
.0;
38343834
let sig = self.normalize_associated_types_in(expr.span, &sig);
38353835
if let Ok(_) = self.try_coerce(expr, sig.output(), expected, AllowTwoPhase::No) {
3836-
if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) {
3837-
err.span_suggestion(expr.span, "use parentheses to call this function", format!(
3838-
"{}({})",
3839-
code,
3840-
if sig.inputs().len() > 0 {
3841-
"..."
3842-
} else {
3843-
""
3844-
}), if sig.inputs().len() > 0 {
3845-
Applicability::MachineApplicable
3846-
} else {
3847-
Applicability::HasPlaceholders
3836+
let (mut sugg_call, applicability) = if sig.inputs().is_empty() {
3837+
(String::new(), Applicability::MachineApplicable)
3838+
} else {
3839+
("...".to_owned(), Applicability::HasPlaceholders)
3840+
};
3841+
let mut msg = "call this function";
3842+
if let ty::FnDef(def_id, ..) = found.sty {
3843+
match self.tcx.hir().get_if_local(def_id) {
3844+
Some(Node::Item(hir::Item {
3845+
node: ItemKind::Fn(.., body_id),
3846+
..
3847+
})) => {
3848+
let body = self.tcx.hir().body(*body_id);
3849+
sugg_call = body.arguments.iter()
3850+
.map(|arg| hir::print::to_string(
3851+
hir::print::NO_ANN,
3852+
|s| s.print_pat(&arg.pat),
3853+
)).collect::<Vec<_>>().join(", ");
3854+
}
3855+
Some(Node::Ctor(hir::VariantData::Tuple(field, _))) => {
3856+
sugg_call = field.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
3857+
msg = "instatiate this tuple struct";
38483858
}
3859+
_ => {}
3860+
}
3861+
};
3862+
if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) {
3863+
err.span_suggestion(
3864+
expr.span,
3865+
&format!("use parentheses to {}", msg),
3866+
format!("{}({})", code, sugg_call),
3867+
applicability,
38493868
);
38503869
return true;
38513870
}

src/test/ui/issues/issue-35241.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | fn test() -> Foo { Foo }
88
| --- ^^^
99
| | |
1010
| | expected struct `Foo`, found fn item
11-
| | help: use parentheses to call this function: `Foo(...)`
11+
| | help: use parentheses to instatiate this tuple struct: `Foo(_)`
1212
| expected `Foo` because of return type
1313
|
1414
= note: expected type `Foo`

src/test/ui/resolve/privacy-enum-ctor.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ LL | let _: Z = Z::Fn;
202202
| ^^^^^
203203
| |
204204
| expected enum `m::n::Z`, found fn item
205-
| help: use parentheses to call this function: `Z::Fn(...)`
205+
| help: use parentheses to instatiate this tuple struct: `Z::Fn(_)`
206206
|
207207
= note: expected type `m::n::Z`
208208
found type `fn(u8) -> m::n::Z {m::n::Z::Fn}`
@@ -232,7 +232,7 @@ LL | let _: E = m::E::Fn;
232232
| ^^^^^^^^
233233
| |
234234
| expected enum `m::E`, found fn item
235-
| help: use parentheses to call this function: `m::E::Fn(...)`
235+
| help: use parentheses to instatiate this tuple struct: `m::E::Fn(_)`
236236
|
237237
= note: expected type `m::E`
238238
found type `fn(u8) -> m::E {m::E::Fn}`
@@ -262,7 +262,7 @@ LL | let _: E = E::Fn;
262262
| ^^^^^
263263
| |
264264
| expected enum `m::E`, found fn item
265-
| help: use parentheses to call this function: `E::Fn(...)`
265+
| help: use parentheses to instatiate this tuple struct: `E::Fn(_)`
266266
|
267267
= note: expected type `m::E`
268268
found type `fn(u8) -> m::E {m::E::Fn}`
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
fn foo(a: usize, b: usize) -> usize { a }
2+
3+
fn bar() -> usize { 42 }
4+
5+
struct S(usize, usize);
6+
struct V();
7+
8+
trait T {
9+
fn baz(x: usize, y: usize) -> usize { x }
10+
fn bat() -> usize { 42 }
11+
}
12+
13+
fn main() {
14+
let _: usize = foo; //~ ERROR mismatched types
15+
let _: S = S; //~ ERROR mismatched types
16+
let _: usize = bar; //~ ERROR mismatched types
17+
let _: V = V; //~ ERROR mismatched types
18+
let _: usize = T::baz; //~ ERROR mismatched types
19+
let _: usize = T::bat; //~ ERROR mismatched types
20+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/fn-or-tuple-struct-without-args.rs:14:20
3+
|
4+
LL | fn foo(a: usize, b: usize) -> usize { a }
5+
| ----------------------------------- fn(usize, usize) -> usize {foo} defined here
6+
...
7+
LL | let _: usize = foo;
8+
| ^^^
9+
| |
10+
| expected usize, found fn item
11+
| help: use parentheses to call this function: `foo(a, b)`
12+
|
13+
= note: expected type `usize`
14+
found type `fn(usize, usize) -> usize {foo}`
15+
16+
error[E0308]: mismatched types
17+
--> $DIR/fn-or-tuple-struct-without-args.rs:15:16
18+
|
19+
LL | struct S(usize, usize);
20+
| ----------------------- fn(usize, usize) -> S {S} defined here
21+
...
22+
LL | let _: S = S;
23+
| ^
24+
| |
25+
| expected struct `S`, found fn item
26+
| help: use parentheses to instatiate this tuple struct: `S(_, _)`
27+
|
28+
= note: expected type `S`
29+
found type `fn(usize, usize) -> S {S}`
30+
31+
error[E0308]: mismatched types
32+
--> $DIR/fn-or-tuple-struct-without-args.rs:16:20
33+
|
34+
LL | fn bar() -> usize { 42 }
35+
| ----------------- fn() -> usize {bar} defined here
36+
...
37+
LL | let _: usize = bar;
38+
| ^^^
39+
| |
40+
| expected usize, found fn item
41+
| help: use parentheses to call this function: `bar()`
42+
|
43+
= note: expected type `usize`
44+
found type `fn() -> usize {bar}`
45+
46+
error[E0308]: mismatched types
47+
--> $DIR/fn-or-tuple-struct-without-args.rs:17:16
48+
|
49+
LL | struct V();
50+
| ----------- fn() -> V {V} defined here
51+
...
52+
LL | let _: V = V;
53+
| ^
54+
| |
55+
| expected struct `V`, found fn item
56+
| help: use parentheses to instatiate this tuple struct: `V()`
57+
|
58+
= note: expected type `V`
59+
found type `fn() -> V {V}`
60+
61+
error[E0308]: mismatched types
62+
--> $DIR/fn-or-tuple-struct-without-args.rs:18:20
63+
|
64+
LL | fn baz(x: usize, y: usize) -> usize { x }
65+
| ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here
66+
...
67+
LL | let _: usize = T::baz;
68+
| ^^^^^^
69+
| |
70+
| expected usize, found fn item
71+
| help: use parentheses to call this function: `T::baz(...)`
72+
|
73+
= note: expected type `usize`
74+
found type `fn(usize, usize) -> usize {<_ as T>::baz}`
75+
76+
error[E0308]: mismatched types
77+
--> $DIR/fn-or-tuple-struct-without-args.rs:19:20
78+
|
79+
LL | fn bat() -> usize { 42 }
80+
| ----------------- fn() -> usize {<_ as T>::bat} defined here
81+
...
82+
LL | let _: usize = T::bat;
83+
| ^^^^^^
84+
| |
85+
| expected usize, found fn item
86+
| help: use parentheses to call this function: `T::bat()`
87+
|
88+
= note: expected type `usize`
89+
found type `fn() -> usize {<_ as T>::bat}`
90+
91+
error: aborting due to 6 previous errors
92+
93+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)