< 返回版块

songzhi 发表于 2020-10-27 23:28

Tags:问答, 生命周期

代码如下:

use smol::io::{AsyncWrite, Cursor};
use std::fmt::Debug;
use std::future::Future;

#[derive(Eq, PartialEq, Debug)]
struct Data {}

impl Data {
    async fn serialize<W: AsyncWrite>(&self, _: &mut W) {}
    fn deserialize(_: &[u8]) -> Self {
        todo!()
    }
}

fn test_serialization<'a, V: 'a, S, O, D>(v: V, serialize: S, deserialize: D)
where
    for<'b> S: FnOnce(&'a V, &'b mut Cursor<Vec<u8>>) -> O,
    O: Future,
    D: FnOnce(&[u8]) -> V,
    V: Eq + Debug,
{
    let mut buf = vec![0;4096];
    serialize(&v, &mut Cursor::new(buf));
    let parsed = deserialize(&buf);
    assert_eq!(v, parsed);
}

fn main() {
    let data = Data {};
    test_serialization(data, Data::serialize, Data::deserialize);
}

这段代码过不了编译, 错误是

error: implementation of `FnOnce` is not general enough
   --> xxx.rs:30:5
    |
30  |       test_serialization(data, Data::serialize, Data::deserialize);
    |       ^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    | 
   ::: /home/xxx/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/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<(&Data, &'0 mut smol::io::Cursor<Vec<u8>>)>` would have to be implemented for the type `for<'_, '_> fn(&Data, &mut smol::io::Cursor<Vec<u8>>) -> impl Future {Data::serialize::<smol::io::Cursor<Vec<u8>>>}`, for some specific lifetime `'0`...
    = note: ...but `FnOnce<(&Data, &'b mut smol::io::Cursor<Vec<u8>>)>` is actually implemented for the type `for<'_, '_> fn(&Data, &mut smol::io::Cursor<Vec<u8>>) -> impl Future {Data::serialize::<smol::io::Cursor<Vec<u8>>>}`

如果我把for<'b> S: FnOnce(&'a V, &'b mut Cursor<Vec<u8>>) -> O,改成S: FnOnce(&'a V, &'a mut Cursor<Vec<u8>>) -> O, 那么调用那里不会报错了,但是函数内部会报cursor生命周期不够长的错。这段代码到底该怎么改?难道只能用宏?我觉得这个需求实在不是特别刁钻。

评论区

写评论
作者 songzhi 2020-10-28 20:18

然后问题就变成了下面这个函数不能用,最后我还是用宏解决了。

fn sync_ser<V, O: Future>(
    ser: impl FnOnce(&V, &mut Cursor<Vec<u8>>) -> O,
) -> impl FnOnce(&V, &mut Cursor<Vec<u8>>) {
    |v, c| {
        smol::block_on(ser(v, c));
    }
}
93996817 2020-10-28 13:48

这样是可以的:

use std::fmt::Debug;
use futures_lite::io::{ AsyncWriteExt, Cursor};
#[derive(Eq, PartialEq, Debug)]
struct Data {
    name:String
}

impl Data {
       fn  serialize(&self,_buf:&mut Cursor<Vec<u8>>) { 
        smol::block_on(
             async {
                println!("serialize name={}",self.name);
                     let _= _buf.write_all(self.name.as_bytes()).await;
                }
            );
          }
       fn  deserialize(_data:&[u8]) -> Self { 
        
        let _name=String::from_utf8(_data.to_owned()).unwrap();
        println!("deserialize name={}",_name);
        Data{name:_name} 
    
    }
}
fn my_test<TData>(val:&TData,ser:impl FnOnce(&TData,&mut Cursor<Vec<u8>>),des:impl FnOnce(&[u8])->TData)
where TData:Eq +Debug ,
{
       let  buf = vec![];
       let mut cur=Cursor::new(buf);
       ser(val,&mut cur)   ;
       let data:TData=des(cur.get_mut());
       assert_eq!(*val,data);
       println!("{:?}",data);
}

fn main() {
    let data = Data { name:"张三".to_owned() };
    my_test (&data,Data::serialize,Data::deserialize);

    /*
     run result 
     Finished dev [unoptimized + debuginfo] target(s) in 1.63s
     
     serialize name=张三
     deserialize name=张三
     Data { name: "张三" }
    */
   
}
 

作者 songzhi 2020-10-28 08:49

改了还是不行

--
👇
tcz717: 你的闭包函数参数是mut借用 得改成FnMut

tcz717 2020-10-28 07:19

你的闭包函数参数是mut借用 得改成FnMut

1 共 4 条评论, 1 页