I am trying to write a generic compose
function which chains two functions f
and g
together into f.g
. This works fine when the arguments and return values are all owned type.
However, when it comes to having a reference in the arguments, the returned closure binds its argument to a specific lifetime, instead of accepting any lifetime.
= note: `impl FnOnce(&'2 u8) -> u32` must implement `FnOnce<(&'1 u8,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 u8,)>`, for some specific lifetime `'2`
Is there a way to write a generic compose
function that works no matter if there is a reference in the arguments? Writing two functions is acceptable to me, but I want to know if there is an elegant way.
Here is an example of the problem I come into. I freeze one part of the compose
to easily illustrate the problem. Rust playground
fn f(x: u16) -> u32 {
x as u32
}
/// This function returns a closure with HRTB
fn compose_ref<T>(g: impl FnOnce(&T) -> u16) -> impl FnOnce(&T) -> u32 {
|x| f(g(x))
}
/// This function, when T is a reference, does not return a closure with HRTB
fn compose<T>(g: impl FnOnce(T) -> u16) -> impl FnOnce(T) -> u32 {
|x| f(g(x))
}
/// Check if a closure has HRTB
fn check_hrtb<T>(_: impl for<'a> FnOnce(&'a T) -> u32) {}
pub fn main() {
let g = |x: &u8| x.clone() as u16;
// The following line won't compile.
// check_hrtb(compose(g));
check_hrtb(compose_ref(g));
}
Please forgive me if this problem is answered somewhere else. I searched in the forum but didn't find any related topic, so I created a new one.