使用具有生命周期的参数包装函数时,类型不够通用错误
Type is not generic enough error when wrapping a function with parameters with lifetimes
我在一个外部库中有一个通用的高阶函数,它接受一个 FnMut
,包装它,并且 returns 类似于:
fn foo<T>(mut f:impl FnMut(T) -> T) -> impl FnMut(T)-> T{
move |t|f(t)
}
我决定编写一个包装器来处理特定情况:
fn bar(f:impl FnMut(&str) -> &str) -> impl FnMut(&str) -> &str{
foo(f)
}
但是,编译器错误地指出其中一种类型不够通用:
error[E0308]: mismatched types
--> src/main.rs:4:39
|
1 | fn foo<T>(mut f:impl FnMut(T) -> T) -> impl FnMut(T)-> T{
| -----------------
| |
| the expected opaque type
| the found opaque type
...
4 | fn bar(f:impl FnMut(&str) -> &str) -> impl FnMut(&str) -> &str{
| ^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected associated type `<impl FnMut<(&str,)> as FnOnce<(&str,)>>::Output`
found associated type `<impl FnMut<(&str,)> as FnOnce<(&str,)>>::Output`
如果我使用像 i32
这样没有生命周期的类型,它编译得很好,并且写出 HRTB 不会改变错误。据我所知,编译器无法匹配函数输出的生命周期,但我无法弄清楚为什么会遇到问题以及如何解决它。
不幸的是,Rust 目前不允许您为您的 bar
示例创建足够通用的 foo
。
但是如果您修改 bar
以便调用者选择 f
的生命周期,而不是它在所有生命周期中都是通用的,您可以使其与当前的 foo
一起工作:
fn foo<T>(mut f: impl FnMut(T) -> T) -> impl FnMut(T)-> T {
move |t| f(t)
}
fn bar<'a>(f: impl FnMut(&'a str) -> &'a str) -> impl FnMut(&'a str) -> &'a str {
foo(f)
}
这在技术上更具限制性,但对于大多数用例来说,它应该是等效的。
我在一个外部库中有一个通用的高阶函数,它接受一个 FnMut
,包装它,并且 returns 类似于:
fn foo<T>(mut f:impl FnMut(T) -> T) -> impl FnMut(T)-> T{
move |t|f(t)
}
我决定编写一个包装器来处理特定情况:
fn bar(f:impl FnMut(&str) -> &str) -> impl FnMut(&str) -> &str{
foo(f)
}
但是,编译器错误地指出其中一种类型不够通用:
error[E0308]: mismatched types
--> src/main.rs:4:39
|
1 | fn foo<T>(mut f:impl FnMut(T) -> T) -> impl FnMut(T)-> T{
| -----------------
| |
| the expected opaque type
| the found opaque type
...
4 | fn bar(f:impl FnMut(&str) -> &str) -> impl FnMut(&str) -> &str{
| ^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected associated type `<impl FnMut<(&str,)> as FnOnce<(&str,)>>::Output`
found associated type `<impl FnMut<(&str,)> as FnOnce<(&str,)>>::Output`
如果我使用像 i32
这样没有生命周期的类型,它编译得很好,并且写出 HRTB 不会改变错误。据我所知,编译器无法匹配函数输出的生命周期,但我无法弄清楚为什么会遇到问题以及如何解决它。
不幸的是,Rust 目前不允许您为您的 bar
示例创建足够通用的 foo
。
但是如果您修改 bar
以便调用者选择 f
的生命周期,而不是它在所有生命周期中都是通用的,您可以使其与当前的 foo
一起工作:
fn foo<T>(mut f: impl FnMut(T) -> T) -> impl FnMut(T)-> T {
move |t| f(t)
}
fn bar<'a>(f: impl FnMut(&'a str) -> &'a str) -> impl FnMut(&'a str) -> &'a str {
foo(f)
}
这在技术上更具限制性,但对于大多数用例来说,它应该是等效的。