use param instead of ty
Signed-off-by: Alex Chi <iskyzh@gmail.com>
This commit is contained in:
parent
54c11a688f
commit
173b8567ee
4 changed files with 63 additions and 75 deletions
|
@ -547,7 +547,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
diag: &mut Diagnostic,
|
diag: &mut Diagnostic,
|
||||||
) {
|
) {
|
||||||
// 0. Extract fn_decl from hir
|
// 0. Extract fn_decl from hir
|
||||||
let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(hir::Closure { fn_decl, .. }), .. }) = hir else { return; };
|
let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(hir::Closure { body, fn_decl, .. }), .. }) = hir else { return; };
|
||||||
|
let hir::Body { params, .. } = self.tcx.hir().body(*body);
|
||||||
|
|
||||||
// 1. Get the substs of the closure.
|
// 1. Get the substs of the closure.
|
||||||
// 2. Assume exp_found is FnOnce / FnMut / Fn, we can extract function parameters from [1].
|
// 2. Assume exp_found is FnOnce / FnMut / Fn, we can extract function parameters from [1].
|
||||||
|
@ -565,7 +566,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
let mut is_first = true;
|
let mut is_first = true;
|
||||||
let mut has_suggestion = false;
|
let mut has_suggestion = false;
|
||||||
|
|
||||||
for ((expected, found), arg_hir) in expected.iter().zip(found.iter()).zip(fn_decl.inputs.iter()) {
|
for (((expected, found), param_hir), arg_hir) in expected.iter()
|
||||||
|
.zip(found.iter())
|
||||||
|
.zip(params.iter())
|
||||||
|
.zip(fn_decl.inputs.iter()) {
|
||||||
if is_first {
|
if is_first {
|
||||||
is_first = false;
|
is_first = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -579,11 +583,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
let hir::TyKind::Infer = arg_hir.kind {
|
let hir::TyKind::Infer = arg_hir.kind {
|
||||||
// If the expected region is late bound, the found region is not, and users are asking compiler
|
// If the expected region is late bound, the found region is not, and users are asking compiler
|
||||||
// to infer the type, we can suggest adding `: &_`.
|
// to infer the type, we can suggest adding `: &_`.
|
||||||
let Ok(arg) = self.tcx.sess.source_map().span_to_snippet(arg_hir.span) else { return; };
|
if param_hir.pat.span == param_hir.ty_span {
|
||||||
suggestion += &format!("{}: &_", arg);
|
// for `|x|`, `|_|`, `|x: impl Foo|`
|
||||||
|
let Ok(pat) = self.tcx.sess.source_map().span_to_snippet(param_hir.pat.span) else { return; };
|
||||||
|
suggestion += &format!("{}: &_", pat);
|
||||||
|
} else {
|
||||||
|
// for `|x: ty|`, `|_: ty|`
|
||||||
|
let Ok(pat) = self.tcx.sess.source_map().span_to_snippet(param_hir.pat.span) else { return; };
|
||||||
|
let Ok(ty) = self.tcx.sess.source_map().span_to_snippet(param_hir.ty_span) else { return; };
|
||||||
|
suggestion += &format!("{}: &{}", pat, ty);
|
||||||
|
}
|
||||||
has_suggestion = true;
|
has_suggestion = true;
|
||||||
} else {
|
} else {
|
||||||
let Ok(arg) = self.tcx.sess.source_map().span_to_snippet(arg_hir.span) else { return; };
|
let Ok(arg) = self.tcx.sess.source_map().span_to_snippet(param_hir.span) else { return; };
|
||||||
// Otherwise, keep it as-is.
|
// Otherwise, keep it as-is.
|
||||||
suggestion += &arg;
|
suggestion += &arg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
fn thing(x: impl FnOnce(&u32, &u32)) {}
|
fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let f = |_, _| ();
|
let f = | _ , y: &u32 , z | ();
|
||||||
thing(f);
|
thing(f);
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~^^ ERROR mismatched types
|
//~^^ ERROR mismatched types
|
||||||
//~^^^ ERROR implementation of `FnOnce` is not general enough
|
let f = | x, y: _ , z: u32 | ();
|
||||||
//~^^^^ ERROR implementation of `FnOnce` is not general enough
|
|
||||||
let f = |x, y| ();
|
|
||||||
thing(f);
|
thing(f);
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~^^ ERROR mismatched types
|
//~^^ ERROR mismatched types
|
||||||
|
|
|
@ -4,22 +4,22 @@ error[E0308]: mismatched types
|
||||||
LL | thing(f);
|
LL | thing(f);
|
||||||
| ^^^^^^^^ one type is more general than the other
|
| ^^^^^^^^ one type is more general than the other
|
||||||
|
|
|
|
||||||
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32)>`
|
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>`
|
||||||
found trait `FnOnce<(&u32, &u32)>`
|
found trait `for<'a> FnOnce<(&u32, &'a u32, u32)>`
|
||||||
note: this closure does not fulfill the lifetime requirements
|
note: this closure does not fulfill the lifetime requirements
|
||||||
--> $DIR/issue-105675.rs:4:13
|
--> $DIR/issue-105675.rs:4:13
|
||||||
|
|
|
|
||||||
LL | let f = |_, _| ();
|
LL | let f = | _ , y: &u32 , z | ();
|
||||||
| ^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
note: the lifetime requirement is introduced here
|
note: the lifetime requirement is introduced here
|
||||||
--> $DIR/issue-105675.rs:1:18
|
--> $DIR/issue-105675.rs:1:18
|
||||||
|
|
|
|
||||||
LL | fn thing(x: impl FnOnce(&u32, &u32)) {}
|
LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider specifying the type of the closure parameters
|
help: consider specifying the type of the closure parameters
|
||||||
|
|
|
|
||||||
LL | let f = |_: &_, _: &_| ();
|
LL | let f = |_: &_, y: &u32, z| ();
|
||||||
| ~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-105675.rs:5:5
|
--> $DIR/issue-105675.rs:5:5
|
||||||
|
@ -27,105 +27,83 @@ error[E0308]: mismatched types
|
||||||
LL | thing(f);
|
LL | thing(f);
|
||||||
| ^^^^^^^^ one type is more general than the other
|
| ^^^^^^^^ one type is more general than the other
|
||||||
|
|
|
|
||||||
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32)>`
|
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>`
|
||||||
found trait `FnOnce<(&u32, &u32)>`
|
found trait `for<'a> FnOnce<(&u32, &'a u32, u32)>`
|
||||||
note: this closure does not fulfill the lifetime requirements
|
note: this closure does not fulfill the lifetime requirements
|
||||||
--> $DIR/issue-105675.rs:4:13
|
--> $DIR/issue-105675.rs:4:13
|
||||||
|
|
|
|
||||||
LL | let f = |_, _| ();
|
LL | let f = | _ , y: &u32 , z | ();
|
||||||
| ^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
note: the lifetime requirement is introduced here
|
note: the lifetime requirement is introduced here
|
||||||
--> $DIR/issue-105675.rs:1:18
|
--> $DIR/issue-105675.rs:1:18
|
||||||
|
|
|
|
||||||
LL | fn thing(x: impl FnOnce(&u32, &u32)) {}
|
LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider specifying the type of the closure parameters
|
|
||||||
|
|
|
||||||
LL | let f = |_: &_, _: &_| ();
|
|
||||||
| ~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
error: implementation of `FnOnce` is not general enough
|
|
||||||
--> $DIR/issue-105675.rs:5:5
|
|
||||||
|
|
|
||||||
LL | thing(f);
|
|
||||||
| ^^^^^^^^ implementation of `FnOnce` is not general enough
|
|
||||||
|
|
|
||||||
= note: closure with signature `fn(&'2 u32, &u32)` must implement `FnOnce<(&'1 u32, &u32)>`, for any lifetime `'1`...
|
|
||||||
= note: ...but it actually implements `FnOnce<(&'2 u32, &u32)>`, for some specific lifetime `'2`
|
|
||||||
|
|
||||||
error: implementation of `FnOnce` is not general enough
|
|
||||||
--> $DIR/issue-105675.rs:5:5
|
|
||||||
|
|
|
||||||
LL | thing(f);
|
|
||||||
| ^^^^^^^^ implementation of `FnOnce` is not general enough
|
|
||||||
|
|
|
||||||
= note: closure with signature `fn(&u32, &'2 u32)` must implement `FnOnce<(&u32, &'1 u32)>`, for any lifetime `'1`...
|
|
||||||
= note: ...but it actually implements `FnOnce<(&u32, &'2 u32)>`, for some specific lifetime `'2`
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-105675.rs:11:5
|
--> $DIR/issue-105675.rs:9:5
|
||||||
|
|
|
|
||||||
LL | thing(f);
|
LL | thing(f);
|
||||||
| ^^^^^^^^ one type is more general than the other
|
| ^^^^^^^^ one type is more general than the other
|
||||||
|
|
|
|
||||||
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32)>`
|
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>`
|
||||||
found trait `FnOnce<(&u32, &u32)>`
|
found trait `FnOnce<(&u32, &u32, u32)>`
|
||||||
note: this closure does not fulfill the lifetime requirements
|
note: this closure does not fulfill the lifetime requirements
|
||||||
--> $DIR/issue-105675.rs:10:13
|
--> $DIR/issue-105675.rs:8:13
|
||||||
|
|
|
|
||||||
LL | let f = |x, y| ();
|
LL | let f = | x, y: _ , z: u32 | ();
|
||||||
| ^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: the lifetime requirement is introduced here
|
note: the lifetime requirement is introduced here
|
||||||
--> $DIR/issue-105675.rs:1:18
|
--> $DIR/issue-105675.rs:1:18
|
||||||
|
|
|
|
||||||
LL | fn thing(x: impl FnOnce(&u32, &u32)) {}
|
LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider specifying the type of the closure parameters
|
help: consider specifying the type of the closure parameters
|
||||||
|
|
|
|
||||||
LL | let f = |x: &_, y: &_| ();
|
LL | let f = |x: &_, y: &_, z: u32| ();
|
||||||
| ~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-105675.rs:11:5
|
--> $DIR/issue-105675.rs:9:5
|
||||||
|
|
|
|
||||||
LL | thing(f);
|
LL | thing(f);
|
||||||
| ^^^^^^^^ one type is more general than the other
|
| ^^^^^^^^ one type is more general than the other
|
||||||
|
|
|
|
||||||
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32)>`
|
= note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>`
|
||||||
found trait `FnOnce<(&u32, &u32)>`
|
found trait `FnOnce<(&u32, &u32, u32)>`
|
||||||
note: this closure does not fulfill the lifetime requirements
|
note: this closure does not fulfill the lifetime requirements
|
||||||
--> $DIR/issue-105675.rs:10:13
|
--> $DIR/issue-105675.rs:8:13
|
||||||
|
|
|
|
||||||
LL | let f = |x, y| ();
|
LL | let f = | x, y: _ , z: u32 | ();
|
||||||
| ^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: the lifetime requirement is introduced here
|
note: the lifetime requirement is introduced here
|
||||||
--> $DIR/issue-105675.rs:1:18
|
--> $DIR/issue-105675.rs:1:18
|
||||||
|
|
|
|
||||||
LL | fn thing(x: impl FnOnce(&u32, &u32)) {}
|
LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider specifying the type of the closure parameters
|
help: consider specifying the type of the closure parameters
|
||||||
|
|
|
|
||||||
LL | let f = |x: &_, y: &_| ();
|
LL | let f = |x: &_, y: &_, z: u32| ();
|
||||||
| ~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error: implementation of `FnOnce` is not general enough
|
error: implementation of `FnOnce` is not general enough
|
||||||
--> $DIR/issue-105675.rs:11:5
|
--> $DIR/issue-105675.rs:9:5
|
||||||
|
|
|
|
||||||
LL | thing(f);
|
LL | thing(f);
|
||||||
| ^^^^^^^^ implementation of `FnOnce` is not general enough
|
| ^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||||
|
|
|
|
||||||
= note: closure with signature `fn(&'2 u32, &u32)` must implement `FnOnce<(&'1 u32, &u32)>`, for any lifetime `'1`...
|
= note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`...
|
||||||
= note: ...but it actually implements `FnOnce<(&'2 u32, &u32)>`, for some specific lifetime `'2`
|
= note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2`
|
||||||
|
|
||||||
error: implementation of `FnOnce` is not general enough
|
error: implementation of `FnOnce` is not general enough
|
||||||
--> $DIR/issue-105675.rs:11:5
|
--> $DIR/issue-105675.rs:9:5
|
||||||
|
|
|
|
||||||
LL | thing(f);
|
LL | thing(f);
|
||||||
| ^^^^^^^^ implementation of `FnOnce` is not general enough
|
| ^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||||
|
|
|
|
||||||
= note: closure with signature `fn(&u32, &'2 u32)` must implement `FnOnce<(&u32, &'1 u32)>`, for any lifetime `'1`...
|
= note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`...
|
||||||
= note: ...but it actually implements `FnOnce<(&u32, &'2 u32)>`, for some specific lifetime `'2`
|
= note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2`
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -43,9 +43,9 @@ note: the lifetime requirement is introduced here
|
||||||
|
|
|
|
||||||
LL | fn take_foo(_: impl Foo) {}
|
LL | fn take_foo(_: impl Foo) {}
|
||||||
| ^^^
|
| ^^^
|
||||||
help: consider changing the type of the closure parameters
|
help: consider specifying the type of the closure parameters
|
||||||
|
|
|
|
||||||
LL | take_foo(|_: &_| a);
|
LL | take_foo(|a: &_| a);
|
||||||
| ~~~~~~~
|
| ~~~~~~~
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue