无法确定为什么rust-capnp的帮助器函数保留借用引用的时间过长

lstz6jyr  于 2022-12-19  发布在  其他
关注(0)|答案(1)|浏览(97)

我尝试为rust-capnp创建一个helper方法,它接受一个初始化函数并返回一个包含消息序列化版本的Vec<u8>

fn construct_serialized_capnp_into<'a, 'b, A, T, F>(
    mut builder: capnp::message::Builder<A>,
    init: F,
) -> Vec<u8>
where
    'a: 'b,
    A: for<'c> capnp::message::Allocator + 'a,
    T: capnp::traits::FromPointerBuilder<'b> + 'b,
    F: FnOnce(&'b mut T),
{
    let serialized_length = {
      let mut root = builder.init_root::<T>();
        init(&mut root);
        capnp::serialize::compute_serialized_size_in_words(&builder)
             * std::mem::size_of::<capnp::Word>()
    };
    let mut buf = Vec::with_capacity(serialized_length);
    buf.resize(serialized_length, 0);
    capnp::serialize::write_message(Cursor::new(buf.as_mut_slice()), &builder).unwrap();
    buf
}

pub(crate) fn construct_serialized_capnp<'a, 'b, T, F>(
    dest: &DmaFile,
    scratch_space: Option<&'a mut [u8]>,
    init: F,
) -> Vec<u8>
where
    'a: 'b,
    T: capnp::traits::FromPointerBuilder<'b> + 'b,
    F: FnOnce(&'b mut T),
{
    match scratch_space {
        Some(space) => construct_serialized_capnp_into(
            capnp::message::Builder::new(capnp::message::ScratchSpaceHeapAllocator::new(space)),
            init,
        ),
        None => construct_serialized_capnp_into(capnp::message::Builder::new_default(), init),
    }
}

这在4行上失败。init_root失败,并显示:

76 | fn construct_serialized_capnp_into<'a, 'b, A, T, F>(
   |                                        -- lifetime `'b` defined here
...
87 |       let mut root = builder.init_root::<T>();
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^
   |                      |
   |                      borrowed value does not live long enough
   |                      argument requires that `builder` is borrowed for `'b`
...
95 | }
   | - `builder` dropped here while still borrowed

调用init函数失败,并显示:

76 | fn construct_serialized_capnp_into<'a, 'b, A, T, F>(
   |                                        -- lifetime `'b` defined here
...
88 |         init(&mut root);
   |         -----^^^^^^^^^-
   |         |    |
   |         |    borrowed value does not live long enough
   |         argument requires that `root` is borrowed for `'b`
...
91 |     };
   |     - `root` dropped here while still borrowed

然后还有两个关于尝试不可变地借用builder,因为(如上所述)我没有让Rust正确地解释借用生存期:

error[E0502]: cannot borrow `builder` as immutable because it is also borrowed as mutable
   |
76 | fn construct_serialized_capnp_into<'a, 'b, A, T, F>(
   |                                        -- lifetime `'b` defined here
...
87 |       let mut root = builder.init_root::<T>();
   |                      ------------------------
   |                      |
   |                      mutable borrow occurs here
   |                      argument requires that `builder` is borrowed for `'b`
88 |         init(&mut root);
89 |         capnp::serialize::compute_serialized_size_in_words(&builder)
   |                                                            ^^^^^^^^ immutable borrow occurs here

error[E0502]: cannot borrow `builder` as immutable because it is also borrowed as mutable
   |
76 | fn construct_serialized_capnp_into<'a, 'b, A, T, F>(
   |                                        -- lifetime `'b` defined here
...
87 |       let mut root = builder.init_root::<T>();
   |                      ------------------------
   |                      |
   |                      mutable borrow occurs here
   |                      argument requires that `builder` is borrowed for `'b`
...
93 |     capnp::serialize::write_message(Cursor::new(buf.as_mut_slice()), &builder).unwrap();
   |                                                                      ^^^^^^^^ immutable borrow occurs here

任何Rust/rust-capnpMaven可以帮助我了解如何修复这个问题(或者确认是否不可能实现这样的功能)吗?

cczfrluj

cczfrluj1#

如果去掉所有显式生存期参数,它就会编译:

use std::io::Cursor;

struct DmaFile {}

fn construct_serialized_capnp_into<A, T, F>(
    mut builder: capnp::message::Builder<A>,
    init: F,
) -> Vec<u8>
where
    A: for<'c> capnp::message::Allocator,
    T: for<'a> capnp::traits::FromPointerBuilder<'a>,
    F: FnOnce(&mut T),
{
    let serialized_length = {
      let mut root = builder.init_root::<T>();
        init(&mut root);
        capnp::serialize::compute_serialized_size_in_words(&builder)
             * std::mem::size_of::<capnp::Word>()
    };
    let mut buf = Vec::with_capacity(serialized_length);
    buf.resize(serialized_length, 0);
    capnp::serialize::write_message(Cursor::new(buf.as_mut_slice()), &builder).unwrap();
    buf
}

pub(crate) fn construct_serialized_capnp<T, F>(
    dest: &DmaFile,
    scratch_space: Option<&mut [u8]>,
    init: F,
) -> Vec<u8>
where
    T: for<'a> capnp::traits::FromPointerBuilder<'a>,
    F: FnOnce(&mut T),
{
    match scratch_space {
        Some(space) => construct_serialized_capnp_into(
            capnp::message::Builder::new(capnp::message::ScratchSpaceHeapAllocator::new(space)),
            init,
        ),
        None => construct_serialized_capnp_into(capnp::message::Builder::new_default(), init),
    }
}

相关问题