告诉编译器泛型返回类型不借用任何对参数的引用?

Hei*_*nzi 6 reference callback rust borrow-checker

tldr;> 给定一个接受通用回调参数并返回关联类型的特征函数,编译器会抱怨关联类型可能从回调函数借用参数。有没有办法告诉编译器事实并非如此?

详细信息:我计划实现一个接受回调参数的特征函数,并希望强制该特征函数的实现实际调用该回调。我通过让回调返回一个只能通过调用此回调来构造的类型,并强制特征函数返回该类型来实现此目的。

/// If this type is used as a generic argument in a trait function and that trait function
/// returns `CallbackResult`, then that enforces that any implementation of that
/// trait function must call the callback.
pub trait Callback<T> {
    type CallbackResult;

    fn call(self, v: T) -> Self::CallbackResult;
}
Run Code Online (Sandbox Code Playgroud)

有关如何使用它的示例:

trait MyTrait {
  fn func<C>(&self, callback: C) -> C::CallbackResult
  where
    C: Callback<i32>;
}

struct MyStruct {}
impl MyTrait for MyStruct {
  fn func<C>(&self, callback: C) -> C::CallbackResult
  where
    C: Callback<i32>,
  {
    // The compiler forces us to call callback because that's the only way
    // for us to create a value of type C::CallbackResult.
    let v = 42;
    callback.call(v)
  }
}
Run Code Online (Sandbox Code Playgroud)

这有效:游乐场

当回调获取引用时,问题就出现了:

trait MyTrait {
  fn func<C>(&self, callback: C) -> <C as Callback<&i32>>::CallbackResult
  where
    C: for <'a> Callback<&'a i32>;
}

struct MyStruct {}
impl MyTrait for MyStruct {
  fn func<C>(&self, callback: C) -> <C as Callback<&i32>>::CallbackResult
  where
    C: for<'a> Callback<&'a i32>,
  {
    // The compiler forces us to call callback because that's the only way
    // for us to create a value of type C::CallbackResult.
    let v = 42;
    callback.call(&v)
  }
}
Run Code Online (Sandbox Code Playgroud)

现在失败了:

error[E0515]: cannot return value referencing local variable `v`
  --> src/lib.rs:22:5
   |
22 |     callback.call(&v)
   |     ^^^^^^^^^^^^^^--^
   |     |             |
   |     |             `v` is borrowed here
   |     returns a value referencing data owned by the current function

For more information about this error, try `rustc --explain E0515`.
error: could not compile `playground` (lib) due to previous error
Run Code Online (Sandbox Code Playgroud)

操场

所以看来 Rust 假设CallbackResult可能会保留对 的引用v。有没有办法告诉编译器它没有?我尝试向关联类型添加绑定CallbackResult: 'static,但这没有什么区别。