Сигнатура типа
impl<T> MyTrait<&T> for T {
fn f<TOut, F>(f: F, x: T) -> TOut
where
F: Fn(&T) -> TOut,
{
}
}
обращается к
impl<'a, T: 'a> MyTrait<&'a T> for T {
fn f<TOut, F>(f: F, x: T) -> TOut
where
F: for<'r> Fn(&'r T) -> TOut,
{
}
}
, что является более общим, чем сигнатура типа черты.Использование
impl<'a, T: 'a> MyTrait<&'a T> for T {
fn f<TOut, F>(f: F, x: T) -> TOut
where
F: Fn(&'a T) -> TOut,
{
}
}
позволило бы это скомпилировать, но ограничить реализацию либо недействительным, либо небезопасным кодом.
impl<'a, T: 'a> MyTrait<&'a T> for T {
fn f<TOut, F>(f: F, x: T) -> TOut
where
F: Fn(&'a T) -> TOut,
{
//panic!(); or
f(unsafe { &*(&x as *const T) })
}
}
Небезопасная версия может легко вызвать использование после освобождения, например
println!("{:?}", String::f(|x: &String| x, "aa".to_string()));
Вместо этого вы можете переместить границы на F
вверх ( Детская площадка )
trait MyTrait<TIn, F, TOut>
where
F: Fn(TIn) -> TOut,
{
fn f(f: F, x: Self) -> TOut;
}
impl<T, F, TOut> MyTrait<T, F, TOut> for T
where
F: Fn(T) -> TOut,
{
fn f(f: F, x: T) -> TOut {
f(x)
}
}
impl<T, F, TOut> MyTrait<T, F, TOut> for &T
where
T: Clone,
F: Fn(T) -> TOut,
{
fn f(f: F, x: &T) -> TOut {
f(x.clone())
}
}
impl<T, F, TOut> MyTrait<&T, F, TOut> for T
where
F: Fn(&T) -> TOut,
{
fn f(f: F, x: T) -> TOut {
f(&x)
}
}