Skip to content

Commit 173b856

Browse files
committed
use param instead of ty
Signed-off-by: Alex Chi <[email protected]>
1 parent 54c11a6 commit 173b856

File tree

4 files changed

+63
-75
lines changed

4 files changed

+63
-75
lines changed

compiler/rustc_infer/src/infer/error_reporting/suggest.rs

+17-5
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
547547
diag: &mut Diagnostic,
548548
) {
549549
// 0. Extract fn_decl from hir
550-
let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(hir::Closure { fn_decl, .. }), .. }) = hir else { return; };
550+
let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(hir::Closure { body, fn_decl, .. }), .. }) = hir else { return; };
551+
let hir::Body { params, .. } = self.tcx.hir().body(*body);
551552

552553
// 1. Get the substs of the closure.
553554
// 2. Assume exp_found is FnOnce / FnMut / Fn, we can extract function parameters from [1].
@@ -565,7 +566,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
565566
let mut is_first = true;
566567
let mut has_suggestion = false;
567568

568-
for ((expected, found), arg_hir) in expected.iter().zip(found.iter()).zip(fn_decl.inputs.iter()) {
569+
for (((expected, found), param_hir), arg_hir) in expected.iter()
570+
.zip(found.iter())
571+
.zip(params.iter())
572+
.zip(fn_decl.inputs.iter()) {
569573
if is_first {
570574
is_first = false;
571575
} else {
@@ -579,11 +583,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
579583
let hir::TyKind::Infer = arg_hir.kind {
580584
// If the expected region is late bound, the found region is not, and users are asking compiler
581585
// to infer the type, we can suggest adding `: &_`.
582-
let Ok(arg) = self.tcx.sess.source_map().span_to_snippet(arg_hir.span) else { return; };
583-
suggestion += &format!("{}: &_", arg);
586+
if param_hir.pat.span == param_hir.ty_span {
587+
// for `|x|`, `|_|`, `|x: impl Foo|`
588+
let Ok(pat) = self.tcx.sess.source_map().span_to_snippet(param_hir.pat.span) else { return; };
589+
suggestion += &format!("{}: &_", pat);
590+
} else {
591+
// for `|x: ty|`, `|_: ty|`
592+
let Ok(pat) = self.tcx.sess.source_map().span_to_snippet(param_hir.pat.span) else { return; };
593+
let Ok(ty) = self.tcx.sess.source_map().span_to_snippet(param_hir.ty_span) else { return; };
594+
suggestion += &format!("{}: &{}", pat, ty);
595+
}
584596
has_suggestion = true;
585597
} else {
586-
let Ok(arg) = self.tcx.sess.source_map().span_to_snippet(arg_hir.span) else { return; };
598+
let Ok(arg) = self.tcx.sess.source_map().span_to_snippet(param_hir.span) else { return; };
587599
// Otherwise, keep it as-is.
588600
suggestion += &arg;
589601
}

tests/ui/lifetimes/issue-105675.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
fn thing(x: impl FnOnce(&u32, &u32)) {}
1+
fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
22

33
fn main() {
4-
let f = |_, _| ();
4+
let f = | _ , y: &u32 , z | ();
55
thing(f);
66
//~^ ERROR mismatched types
77
//~^^ ERROR mismatched types
8-
//~^^^ ERROR implementation of `FnOnce` is not general enough
9-
//~^^^^ ERROR implementation of `FnOnce` is not general enough
10-
let f = |x, y| ();
8+
let f = | x, y: _ , z: u32 | ();
119
thing(f);
1210
//~^ ERROR mismatched types
1311
//~^^ ERROR mismatched types

tests/ui/lifetimes/issue-105675.stderr

+41-63
Original file line numberDiff line numberDiff line change
@@ -4,128 +4,106 @@ error[E0308]: mismatched types
44
LL | thing(f);
55
| ^^^^^^^^ one type is more general than the other
66
|
7-
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32)>`
8-
found trait `FnOnce<(&u32, &u32)>`
7+
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>`
8+
found trait `for<'a> FnOnce<(&u32, &'a u32, u32)>`
99
note: this closure does not fulfill the lifetime requirements
1010
--> $DIR/issue-105675.rs:4:13
1111
|
12-
LL | let f = |_, _| ();
13-
| ^^^^^^
12+
LL | let f = | _ , y: &u32 , z | ();
13+
| ^^^^^^^^^^^^^^^^^^^
1414
note: the lifetime requirement is introduced here
1515
--> $DIR/issue-105675.rs:1:18
1616
|
17-
LL | fn thing(x: impl FnOnce(&u32, &u32)) {}
18-
| ^^^^^^^^^^^^^^^^^^
17+
LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
18+
| ^^^^^^^^^^^^^^^^^^^^^^^
1919
help: consider specifying the type of the closure parameters
2020
|
21-
LL | let f = |_: &_, _: &_| ();
22-
| ~~~~~~~~~~~~~~
21+
LL | let f = |_: &_, y: &u32, z| ();
22+
| ~~~~~~~~~~~~~~~~~~~
2323

2424
error[E0308]: mismatched types
2525
--> $DIR/issue-105675.rs:5:5
2626
|
2727
LL | thing(f);
2828
| ^^^^^^^^ one type is more general than the other
2929
|
30-
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32)>`
31-
found trait `FnOnce<(&u32, &u32)>`
30+
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>`
31+
found trait `for<'a> FnOnce<(&u32, &'a u32, u32)>`
3232
note: this closure does not fulfill the lifetime requirements
3333
--> $DIR/issue-105675.rs:4:13
3434
|
35-
LL | let f = |_, _| ();
36-
| ^^^^^^
35+
LL | let f = | _ , y: &u32 , z | ();
36+
| ^^^^^^^^^^^^^^^^^^^
3737
note: the lifetime requirement is introduced here
3838
--> $DIR/issue-105675.rs:1:18
3939
|
40-
LL | fn thing(x: impl FnOnce(&u32, &u32)) {}
41-
| ^^^^^^^^^^^^^^^^^^
42-
help: consider specifying the type of the closure parameters
43-
|
44-
LL | let f = |_: &_, _: &_| ();
45-
| ~~~~~~~~~~~~~~
46-
47-
error: implementation of `FnOnce` is not general enough
48-
--> $DIR/issue-105675.rs:5:5
49-
|
50-
LL | thing(f);
51-
| ^^^^^^^^ implementation of `FnOnce` is not general enough
52-
|
53-
= note: closure with signature `fn(&'2 u32, &u32)` must implement `FnOnce<(&'1 u32, &u32)>`, for any lifetime `'1`...
54-
= note: ...but it actually implements `FnOnce<(&'2 u32, &u32)>`, for some specific lifetime `'2`
55-
56-
error: implementation of `FnOnce` is not general enough
57-
--> $DIR/issue-105675.rs:5:5
58-
|
59-
LL | thing(f);
60-
| ^^^^^^^^ implementation of `FnOnce` is not general enough
61-
|
62-
= note: closure with signature `fn(&u32, &'2 u32)` must implement `FnOnce<(&u32, &'1 u32)>`, for any lifetime `'1`...
63-
= note: ...but it actually implements `FnOnce<(&u32, &'2 u32)>`, for some specific lifetime `'2`
40+
LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
41+
| ^^^^^^^^^^^^^^^^^^^^^^^
6442

6543
error[E0308]: mismatched types
66-
--> $DIR/issue-105675.rs:11:5
44+
--> $DIR/issue-105675.rs:9:5
6745
|
6846
LL | thing(f);
6947
| ^^^^^^^^ one type is more general than the other
7048
|
71-
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32)>`
72-
found trait `FnOnce<(&u32, &u32)>`
49+
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>`
50+
found trait `FnOnce<(&u32, &u32, u32)>`
7351
note: this closure does not fulfill the lifetime requirements
74-
--> $DIR/issue-105675.rs:10:13
52+
--> $DIR/issue-105675.rs:8:13
7553
|
76-
LL | let f = |x, y| ();
77-
| ^^^^^^
54+
LL | let f = | x, y: _ , z: u32 | ();
55+
| ^^^^^^^^^^^^^^^^^^^^^
7856
note: the lifetime requirement is introduced here
7957
--> $DIR/issue-105675.rs:1:18
8058
|
81-
LL | fn thing(x: impl FnOnce(&u32, &u32)) {}
82-
| ^^^^^^^^^^^^^^^^^^
59+
LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
60+
| ^^^^^^^^^^^^^^^^^^^^^^^
8361
help: consider specifying the type of the closure parameters
8462
|
85-
LL | let f = |x: &_, y: &_| ();
86-
| ~~~~~~~~~~~~~~
63+
LL | let f = |x: &_, y: &_, z: u32| ();
64+
| ~~~~~~~~~~~~~~~~~~~~~~
8765

8866
error[E0308]: mismatched types
89-
--> $DIR/issue-105675.rs:11:5
67+
--> $DIR/issue-105675.rs:9:5
9068
|
9169
LL | thing(f);
9270
| ^^^^^^^^ one type is more general than the other
9371
|
94-
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32)>`
95-
found trait `FnOnce<(&u32, &u32)>`
72+
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>`
73+
found trait `FnOnce<(&u32, &u32, u32)>`
9674
note: this closure does not fulfill the lifetime requirements
97-
--> $DIR/issue-105675.rs:10:13
75+
--> $DIR/issue-105675.rs:8:13
9876
|
99-
LL | let f = |x, y| ();
100-
| ^^^^^^
77+
LL | let f = | x, y: _ , z: u32 | ();
78+
| ^^^^^^^^^^^^^^^^^^^^^
10179
note: the lifetime requirement is introduced here
10280
--> $DIR/issue-105675.rs:1:18
10381
|
104-
LL | fn thing(x: impl FnOnce(&u32, &u32)) {}
105-
| ^^^^^^^^^^^^^^^^^^
82+
LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
83+
| ^^^^^^^^^^^^^^^^^^^^^^^
10684
help: consider specifying the type of the closure parameters
10785
|
108-
LL | let f = |x: &_, y: &_| ();
109-
| ~~~~~~~~~~~~~~
86+
LL | let f = |x: &_, y: &_, z: u32| ();
87+
| ~~~~~~~~~~~~~~~~~~~~~~
11088

11189
error: implementation of `FnOnce` is not general enough
112-
--> $DIR/issue-105675.rs:11:5
90+
--> $DIR/issue-105675.rs:9:5
11391
|
11492
LL | thing(f);
11593
| ^^^^^^^^ implementation of `FnOnce` is not general enough
11694
|
117-
= note: closure with signature `fn(&'2 u32, &u32)` must implement `FnOnce<(&'1 u32, &u32)>`, for any lifetime `'1`...
118-
= note: ...but it actually implements `FnOnce<(&'2 u32, &u32)>`, for some specific lifetime `'2`
95+
= note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`...
96+
= note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2`
11997

12098
error: implementation of `FnOnce` is not general enough
121-
--> $DIR/issue-105675.rs:11:5
99+
--> $DIR/issue-105675.rs:9:5
122100
|
123101
LL | thing(f);
124102
| ^^^^^^^^ implementation of `FnOnce` is not general enough
125103
|
126-
= note: closure with signature `fn(&u32, &'2 u32)` must implement `FnOnce<(&u32, &'1 u32)>`, for any lifetime `'1`...
127-
= note: ...but it actually implements `FnOnce<(&u32, &'2 u32)>`, for some specific lifetime `'2`
104+
= note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`...
105+
= note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2`
128106

129-
error: aborting due to 8 previous errors
107+
error: aborting due to 6 previous errors
130108

131109
For more information about this error, try `rustc --explain E0308`.

tests/ui/lifetimes/issue-79187-2.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ note: the lifetime requirement is introduced here
4343
|
4444
LL | fn take_foo(_: impl Foo) {}
4545
| ^^^
46-
help: consider changing the type of the closure parameters
46+
help: consider specifying the type of the closure parameters
4747
|
48-
LL | take_foo(|_: &_| a);
48+
LL | take_foo(|a: &_| a);
4949
| ~~~~~~~
5050

5151
error[E0308]: mismatched types

0 commit comments

Comments
 (0)