Нет простого способа заставить helper
работать в текущем Rust, даже если вы удалите все for<'a> A: Debug + 'a,
границы (которые только дополнительно ограничивают , какие типы A
могут быть, тогда как вы хотите разрешить больше ).
Это так просто, как я могу привести ваш пример:
struct S<A> {
f: Box<Fn(A) -> i32>,
}
impl<A> S<A> {
fn call(&self, a: A) {
println!("Return {:?}", (self.f)(a));
}
}
fn create<A>(f: Box<Fn(A) -> i32>) -> S<A> {
S { f }
}
fn helper() {
let x = create(Box::new(|x: &i32| *x * 2));
let arg = 333;
x.call(&arg);
}
fn main() {
helper();
}
Причина, по которой это не работает, заключается в том, что A
"приходит извне ", и Rust не может сделать вывод, что вы хотите for<'a> S<&'a A>
, он даже не может говорить о таком типе.
Обратите внимание, что если let arg = 333;
находится над let x
, этот пример делает компиляцию (потому что она выводит ссылку на arg
, в частности , а не for<'a>
).
На сегодняшний день вы можете получить ближайший связанный типtrait с параметром времени жизни, например:
// Emulating `type Type<'a>` by moving `'a` to the trait.
trait Apply<'a> {
type Type;
}
struct Plain<T>(std::marker::PhantomData<T>);
impl<'a, T> Apply<'a> for Plain<T> {
type Type = T;
}
struct Ref<T: ?Sized>(std::marker::PhantomData<T>);
impl<'a, T: ?Sized + 'a> Apply<'a> for Ref<T> {
type Type = &'a T;
}
struct S<A: for<'a> Apply<'a>> {
f: Box<for<'a> Fn(<A as Apply<'a>>::Type) -> i32>,
}
impl<A: for<'a> Apply<'a>> S<A> {
fn call<'a>(&self, a: <A as Apply<'a>>::Type) {
println!("Return {:?}", (self.f)(a));
}
}
fn create<A: for<'a> Apply<'a>>(
f: Box<for<'a> Fn(<A as Apply<'a>>::Type) -> i32>,
) -> S<A> {
S { f }
}
fn helper() {
let x = create::<Ref<i32>>(Box::new(|x: &i32| *x * 2));
let arg = 333;
x.call(&arg);
}
fn main() {
helper();
}
Однако, оказывается, что эта кодировка соответствует https://github.com/rust-lang/rust/issues/52812,, поэтому в данный момент она фактически не используется (и я не знаю обходного пути)).