Why is it that we're only able to downcast 'static types? (Any requires 'static)
I understand that lifetimes are erased, so it's not possible to check at runtime whether a certain type has the expected lifetime, but if I can prove at compile time that my type is : 'a, why I am not allowed to downcast to T<'a>? In other words, why would the following be unsound?
// assuming `Any` does not require `'static`
// and has a lifetime parameter instead
impl<'a> Any<'a> {
fn downcast_ref<T: 'a>(&self) -> Option<&T> { ... }
}
impl<'a, T: 'a> Any<'a> for T {}
Note: the alternative without a lifetime parameter,
is unsound because of contravariance: one could cast &fn(&'static str) → &'static Any → &'a Any → &'a fn(&'a str); while trait objects are, I believe, invariant over their lifetime parameters (since PhantomFn was removed), so doing something like this is impossible.
&'a i32 and &'static i32 will have the same TypeId (because lifetimes are erased at runtime) and both have the : 'a bound. Therefore you'll be able to upcast &&'a i32 to &Any<'a> and then downcast it to &&'static i32. As references are Copy it allows conversion from &'a i32 into &'static i32 and it's apparently unsound.
However, Any<'a> is not the only way to achieve non-static downcasting. The 'static bound on type_id is removed to test such safe variants of non-static downcasting.