< 返回版块

Lexo-0 发表于 2021-02-27 19:35

Tags:生命周期|异步

use async_trait::async_trait;
use std::future::Future;
#[async_trait]
trait Point{
    async fn call(&self,input:&mut String) -> String;
}

#[async_trait]
impl <F,Fut>Point for F
where 
    F:Send+Sync+'static+Fn(&mut String) -> Fut,
    Fut:Send+Sync+'static +Future<Output = String>
{
    async fn call(&self,input:&mut String) -> String{
        self(input).await
    }
}

fn main(){
    run(test);
}

fn run(_:impl Point){

}

async fn test(input:&mut String) -> String{
    todo!()
}


编译后报错:


error: implementation of `FnOnce` is not general enough
   --> src\life_time.rs:20:5
    |
20  |       run(test);
    |       ^^^ implementation of `FnOnce` is not general enough
    | 
   ::: C:\Users\Lexo\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\ops\function.rs:219:1
    |
219 | / pub trait FnOnce<Args> {
220 | |     /// The returned type after the call operator is used.
221 | |     #[lang = "fn_once_output"]
222 | |     #[stable(feature = "fn_once_output", since = "1.12.0")]
...   |
227 | |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
228 | | }
    | |_- trait `FnOnce` defined here
    |
    = note: `FnOnce<(&'0 mut String,)>` would have to be implemented for the type `for<'_> fn(&mut String) -> impl Future {test}`, for some specific lifetime `'0`...
    = note: ...but `FnOnce<(&mut String,)>` is actually implemented for the type `for<'_> fn(&mut String) -> impl Future {test}`

我不明白报错信息的意思?是生命周期推断失败了吗?

评论区

写评论
93996817 2021-02-28 00:20
似乎这种情况必须要加生命周期的.有个issue有说明:
use async_trait::async_trait;
use std::future::Future;
type MutString<'a> = &'a mut String;
#[async_trait]
trait Point<'a> {
    async fn call(&self, input: MutString<'a>) -> String;
}

#[async_trait]
impl<'a, F, Fut> Point<'a> for F
where
    F: Send + Sync + 'static + Fn(MutString<'a>) -> Fut,
    Fut: Send + Sync + 'static + Future<Output = String>,
{
    async fn call(&self, input: MutString<'a>) -> String {
        self(input).await
    }
}

fn main() {
    let future = run(test);
    let result = async_std::task::block_on(future);
    println!("result={:?}", result);
}

async fn run<'a>(func: impl Point<'a>) -> String {
    "asdf".to_owned()
}

async fn test(input: &mut String) -> String {
    input.to_owned()
}
E834159672 2021-02-27 22:50

高人

作者 Lexo-0 2021-02-27 20:04

use async_trait::async_trait;
use std::{future::Future, pin::Pin};

trait Point<'async_trait>{
    fn call<'life0,'life1>(&'life0 self,input:&'life1 mut String) -> Pin<Box<dyn Future<Output =String>+Send>>
    where 'life0:'async_trait,'life1:'async_trait;
}

impl <'async_trait,F,Fut>Point<'async_trait> for F
where 
    F:Send+Sync+'static+Fn(&'async_trait mut String) -> Fut,
    Fut:Send+Sync+'static +Future<Output = String>
{
    fn call<'life0,'life1>(&'life0 self,input:&'life1 mut String) -> Pin<Box<dyn Future<Output=String>+Send>>
    where
        'life0:'async_trait,
        'life1:'async_trait,
    {
        Box::pin(self(input))
    }
}

fn main(){
    run(test);
}

fn run<'async_trait>(_:impl Point<'async_trait>){

}

async fn test(input:&mut String) -> String{
    todo!()
}

如果这样做,就能通过编译了

作者 Lexo-0 2021-02-27 19:53

很奇怪的是,如果不用async,就能通过编译


use async_trait::async_trait;
use std::future::Future;
trait Point{
    fn call(&self,input:&String) -> String;
}

impl <F>Point for F
where 
    F:Send+Sync+'static+Fn(&String) -> String,
{
    fn call(&self,input:&String) -> String{
        self(input)
    }
}

fn main(){
    run(test);
}

fn run(_:impl Point){

}

fn test(input:&String) -> String{
    "todo!()".to_string()
}
1 共 4 条评论, 1 页