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;
}
有关如何使用它的示例:
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)
}
}
这有效:
当回调获取引用时,问题就出现了:
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)
}
}
现在失败了:
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
所以看来 Rust 假设CallbackResult
可以保留参考v
。有没有办法告诉编译器它没有?我尝试添加一个界限CallbackResult: 'static
到关联的类型,但这没有什么区别。