Why the code use Option here?

Code from axum:

pub(crate) fn try_downcast<T, K>(k: K) -> Result<T, K>
where
    T: 'static,
    K: Send + 'static,
{
    let mut k = Some(k);
    if let Some(k) = <dyn std::any::Any>::downcast_mut::<Option<T>>(&mut k) {
        Ok(k.take().unwrap())
    } else {
        Err(k.unwrap())
    }
}

I can't understand it well. Especially, the using of Option in the code. Why it can't be just:

pub(crate) fn try_downcast<T, K>(k: K) -> Result<T, K>
where
    T: 'static,
    K: Send + 'static,
{
    let mut k1 = k;
    if let Some(k) = <dyn std::any::Any>::downcast_mut::<T>(&mut k1) {
        Ok(k)
    } else {
        Err(k1)
    }
}

?

The Ok(k) line here has the wrong type, because k has type &mut T while you need to return a T:

You can fix the type by writing Ok(*k) but then you will get an error that you can’t move out of a borrowed reference.

Using Option lets you conditionally move the T out without consuming the Option itself, by using Option::take.

2 Likes

Ok, After compiling the code, I found the reason.

Option provides a way to steal T from &mut T returned from downcast_mut.

Yes, this is a coding skill.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.