FnMut 似乎捕获了它的调用参数?

Áko*_*dra 4 rust

在 ffi(嵌入式)环境中,当 C 代码需要函数指针(和可选的,通常是 *void 参数)时,通常会使用蹦床,但我们希望让它调用 rust 闭包。

蹦床是一个fn,而一个盒装闭包作为参数提供。fn 代码只是调用闭包。

然而,我似乎无法让借用检查器相信以下代码是安全的,并且似乎认为在对闭包的调用返回后,作为参数给闭包提供的引用(未由闭包捕获)仍然是借用的。

我不确定为什么会出现这种情况,有人可以帮忙如何编译吗?

// Workaround for unstable feature 'trait_alias'
pub trait Callback<'a>: FnMut(&'a mut Context<'a>) {}

impl<'a, T> Callback<'a> for T where T: FnMut(&'a mut Context<'a>) {}

pub fn trampoline(cb_ptr: *mut c_void ) {
    let s = "foo";
    let mut ctx = Context { s };

    unsafe {
        let cb = cb_ptr as *mut Box<dyn Callback<'_>>;
        (*cb)(&mut ctx);
    }

    let Context { s, .. } = ctx;

    info!("s = {}", &s);

}
Run Code Online (Sandbox Code Playgroud)

错误:

error[E0503]: cannot use `ctx.s` because it was mutably borrowed
  --> temp.rs:91:19
   |
88 |         (*cb)(&mut ctx);
   |               -------- borrow of `ctx` occurs here
...
91 |     let Context { s, .. } = ctx;
   |                   ^
   |                   |
   |                   use of borrowed `ctx`
   |                   borrow later used here

For more information about this error, try `rustc --explain E0503`.

Run Code Online (Sandbox Code Playgroud)

Pit*_*taJ 5

问题似乎出在&'a mut Context<'a>. 这就是说,对上下文的引用需要与上下文中的引用一样长。然而,您实际上并不关心对上下文的引用的生命周期;它只需要在调用闭包期间持续。

更改&'a mut为似乎&mut可以解决问题:

// Workaround for unstable feature 'trait_alias'
pub trait Callback<'a>: FnMut(&mut Context<'a>) {}

impl<'a, T> Callback<'a> for T where T: FnMut(&mut Context<'a>) {}

pub fn trampoline(cb_ptr: *mut c_void ) {
    let s = "foo";
    let mut ctx = Context { s };

    unsafe {
        let cb = cb_ptr as *mut Box<dyn Callback<'_>>;
        (*cb)(&mut ctx);
    }

    let Context { s, .. } = ctx;

    info!("s = {}", &s);

}
Run Code Online (Sandbox Code Playgroud)

操场