use async_trait::async_trait;
use tokio;
use core::future::Future;
async fn tester(string:&String) -> String{
string.into()
}
static dyn_tester:&dyn App=&tester;
#[tokio::main]
async fn main() {
let string=String::from("233");
dyn_tester.call(&string).await;
}
#[async_trait]
trait App:Sync{
async fn call(&self,value:&String) -> String;
}
#[async_trait]
impl <T,Fut>App for T
where
T:Send+Sync+Fn(&String) -> Fut,
Fut:Send+Sync+Future<Output=String>,
{
async fn call(&self,value:&String) -> String{
self(value).await
}
}
如果这样,无法通过编译。错误是 error: implementation of
FnOnce is not general enough
,我在https://rustcc.cn/article?id=2af9e290-bc1b-442a-ae90-39f98787675e询问过,@93996817的建议是加生命周期,于是变成这样:
use async_trait::async_trait;
use tokio;
use core::future::Future;
async fn tester(string:&String) -> String{
string.into()
}
static dyn_tester:&dyn App=&tester;//这里看起来好像只要把static去掉,放到局部作用域就行。但实际上只是因为这只是个示例,没涉及具体逻辑。我实际使用的时候,dyn_tester的确可能是必须'static的
#[tokio::main]
async fn main() {
let string=String::from("233");
dyn_tester.call(&string).await;
}
#[async_trait]
trait App<'a>:Sync{
async fn call(&self,value:&'a String) -> String;
}
#[async_trait]
impl <'a,T,Fut>App<'a> for T
where
T:Send+Sync+Fn(&'a String) -> Fut,
Fut:Send+Sync+Future<Output=String>,
{
async fn call(&self,value:&'a String) -> String{
self(value).await
}
}
error[E0597]: `string` does not live long enough
--> src/main.rs:14:21
|
14 | dyn_tester.call(&string).await;
| ----------------^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `string` is borrowed for `'static`
15 | }
| - `string` dropped here while still borrowed
这次我就算不用async_trait自己手写也无法解决问题了
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fa1e7bcd9ad966c8dadb7f9748e1956a
希望能得到各位的指导。
Ext Link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fa1e7bcd9ad966c8dadb7f9748e1956a
1
共 2 条评论, 1 页
评论区
写评论这个问题的核心在于这句:
dyn_tester.call(&string).await;
,这里必须保证&'x string
的生命周期必须大于或等于&'static
的dyn_tester
。所以第一步需要改的是传入
&'static
的string。由于第一步的需要,那么说明一个问题
App trait
的生命周期要和其call
方法中value
的生命周期形成关联(value
的生命周期要大于等App trait
),所以第二步我们给App trait
加上生命周期。最后代码如下:
考虑
T
的App
实现,为了让这个call
能够满足生命周期限制,我们需要&self
上的'_
长于'a
Self
的生命周期长于'a
目前
&dyn App
是'static
的,意味着trait实现里的'a
都需要延长到'static
,所以本地变量的&String
不够长。所以第一步要考虑把&String
上的生命周期和Self
的生命周期分开。一个很显然的想法是去掉App
上的生命周期限制,下放到for<'a> Fn(&'a String) -> Fut
但这样会出现
not general enough
的报错,参考这个回答和这个issue,workaround是套一个trait