error: implementation of `FnOnce` is not general enough
呼出可能型 (Fn, FnMut, FnOnce の実装型) に HRTB が含まれ、その箇所を型推論している。
『HRTB - 型推論』で紹介する通り、型推論の結果に HRTB は含まれない。
これは呼出可能型に限った話ではないが、呼出可能型では専用のメッセージになる。
呼出可能型にクロージャが指定され、その引数が問題になるパターン。
以下では、関数 callback のコールバック引数 f は HRTB を含む引数をとる。
しかし、クロージャ nop の引数 _ は型推論されているため HRTB を含めない。
fn main() {
let nop = |_| {};
callback(nop, &42);
}
fn callback(f: impl FnOnce(&i32), x: &i32) {
f(&x)
}
error: implementation of `FnOnce` is not general enough --> src/main.rs:3:5 | 3 | callback(nop, &42); | ^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | = note: closure with signature `fn(&'2 i32)` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2`
問題を起こしている推論箇所を省略しないようにする。
fn main() {
let nop = |_: &_| {};
callback(nop, &42);
}
fn callback(f: impl FnOnce(&i32), x: &i32) {
f(&x)
}
呼出可能型にメソッドが指定され、その self 引数が問題になるパターン。
以下では、関数 callback のコールバック引数 f は HRTB を含む引数をとる。
しかし、メソッド MyRef::work は MyRef の型パラメタ 'a を HRTB として扱えない。
fn main() {
let x = MyRef(&42);
callback(MyRef::work, x);
}
fn callback(f: impl FnOnce(MyRef<'_>), x: MyRef<'_>) {
f(x);
}
struct MyRef<'a>(&'a i32);
impl<'a> MyRef<'a> {
fn work(self) {
dbg!(self.0);
}
}
error: implementation of `FnOnce` is not general enough
--> src/main.rs:3:5
|
3 | callback(MyRef::work, x);
| ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: `fn(MyRef<'2>) {MyRef::<'2>::work}` must implement `FnOnce<(MyRef<'1>,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(MyRef<'2>,)>`, for some specific lifetime `'2`
対象のメソッドの呼出を適切にラップする。
fn main() {
let x = MyRef(&42);
callback(|x| MyRef::work(x), x);
}
fn callback(f: impl FnOnce(MyRef<'_>), x: MyRef<'_>) {
f(x);
}
struct MyRef<'a>(&'a i32);
impl<'a> MyRef<'a> {
fn work(self) {
dbg!(self.0);
}
}