Hi,
I was trying to do something like this:
fn first_zero_or_self_bad<'a>(xs: &'a mut Vec<u8>)
-> Either<&'a mut Vec<u8>, &'a mut u8>
{
if let Some(x) = xs.iter_mut().find(|x| **x == 0)
{ Either::Right(x) }
else
{ Either::Left(xs) }
}
And variants with different lifetime signatures, e.g.
fn first_zero_or_self_bad<'b, 'a: 'b>(xs: &'a mut Vec<u8>)
-> Either<&'a mut Vec<u8>, &'b mut u8>
But the code just cannot be compiled because of different yet related lifetimes of xs
and xs.iter_mut()
. I think that it is quite a safe thing to do, but I understand that Rust does not reason about Either<A, B>
with a knowledge that A
and B
will be mutually exclusive and that's why I have to persuade it.
I've came up with a workaround:
struct Ptr<'a, T>{x: *mut T, life: PhantomData<&'a ()>}
fn first_zero_or_self<'a>(xs: &'a mut Vec<u8>)
-> Either<&'a mut Vec<u8>, Ptr<'a, u8>>
{
if let Some(x) = xs.iter_mut().find(|x| **x == 0)
{ Either::Right(Ptr{x: &mut *x, life: PhantomData}) }
else
{ Either::Left(xs) }
}
My questions are:
- Is there some other more elegant solution or more standard practice that I'm missing?
- Is my workaround a safe thing to do? (I will not publish the fields of the Ptr struct and the published functions that use the Ptr will not leak the pointer)
Let's say I need Vec to implement a trait implemented by other structures, so the type signature of the function should remain in the form fn(&mut Self) -> Either<Self::A<'_>, Self::B<'_>>
.
In advance, thank you very much for your replies and opinions.
Here's my playground: Rust Playground