让我们假设有一个性状Foo
:
trait Foo {
type Future: Future<Output = ()>;
fn bar(&self, a: &str) -> Self::Future;
}
其具有获取对自身的引用以及对字符串片段的引用并返回Future的所需方法bar
.
让我们为引用字符串片并返回相应future 的任何fn
实现Foo
.
impl<Fut: Future<Output = ()>> Foo for fn(&str) -> Fut {
type Future = Fut;
fn bar(&self, a: &str) -> Self::Future {
self(a)
}
}
现在,让我们try 在引用字符串片的async fn
上调用bar
.
async fn test(a: &str) {
/* ... */
}
#[tokio::main]
async fn main() {
Foo::bar(&(test as fn(&str) -> _), "Hello world");
}
尽管test
具有正确的函数签名,并且它返回正确的future ,但从test_function
到fn(&str) -> _
的类型强制转换失败.
error[E0605]: non-primitive cast: `for<'a> fn(&'a str) -> impl Future<Output = ()> {test}` as `for<'a> fn(&'a str) -> _`
--> src/main.rs:21:15
|
21 | Foo::bar(&(test as fn(&str) -> _), "Hello world");
| ^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
根据我的理解,这是将从test
返回的impl Futere
绑定到参数生存期a
的原因.
我能想到的唯一非夜间解决方案是在这一特征中引入一生.
trait Foo<'a> {
type Future: Future<Output = ()> + 'a;
fn bar(&self, a: &'a str) -> Self::Future;
}
impl<'a, Fut: Future<Output = ()> + 'a> Foo<'a> for fn(&'a str) -> Fut {
type Future = Fut;
fn bar(&self, a: &str) -> Self::Future {
self(a)
}
}
通过《夜间》中的一些非常实验性的功能,我想出了这样的 idea :
#![feature(return_position_impl_trait_in_trait)]
use std::future::Future;
trait Foo {
fn bar<'a>(&self, a: &'a str) -> impl Future<Output = ()> + 'a;
}
impl<Fut> Foo for fn(&str) -> Fut
where
for<'a> Fut: Future<Output = ()> + 'a,
{
fn bar(&self, a: &str) -> Fut {
self(a)
}
}
async fn test(a: &str) {
/* ... */
}
#[tokio::main]
async fn main() {
Foo::bar(&(test as fn(&str) -> _), "Hello world");
}
但这仍然会导致相同的非基元类型转换错误.