error: implementation of `FnOnce` is not general enough
呼出可能型 (Fn
, FnMut
, FnOnce
の実装型) の引数に汎用性が足りない。
呼出可能型の指定において、HRTB に対応すべき箇所がそうでないと、このエラーになる。
(注: ライフタイム省略により for<...>
構文を使わない 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)
}
呼出可能型にメソッドを指定しているパターン。メソッドは引数だけでなく型そのものが持つライフタイムがあり、それは HRTB として扱えない。
以下では、関数 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);
}
}