This won't help for general tail calls, but if you can just use tail recursion, you can use a combinator:
pub fn factorial(x: usize) -> usize {
tail_recurse((x, 1), |(a, b)| {
if a == 0 { RecursionResult::Return(b) }
else { RecursionResult::Continue((a - 1, a * b)) }
})
}
Amusingly, that actually generates better code than (1..=x).product()