Open
Description
use std::any::TypeId;
/// The type does not have any free lifetimes.
///
/// Necessary as `TypeId` cannot distinguish between
/// `&'a str` and `&'static str` and we must not cast
/// between these types.
unsafe trait NoFreeLifetimes: 'static {}
unsafe impl<T: NoFreeLifetimes> NoFreeLifetimes for Vec<T> {}
unsafe impl NoFreeLifetimes for u32 {}
unsafe impl NoFreeLifetimes for String {}
fn try_downcast_ref<'a, S, T: NoFreeLifetimes>(x: &S) -> Option<&T> {
if non_static_type_id::<S>() == non_static_type_id::<T>() {
Some(unsafe { &*(x as *const S).cast() })
} else {
None
}
}
fn non_static_type_id<T>() -> TypeId {
type_id_of_val(|| ())
}
fn type_id_of_val<T: 'static>(_: T) -> TypeId {
TypeId::of::<T>()
}
fn foo<T>(x: &T) {
if let Some(s) = try_downcast_ref::<_, String>(x) {
println!("{s}");
} else if let Some(v) = try_downcast_ref::<_, Vec<u32>>(x) {
println!("{v:?}");
} else {
println!("unknown");
}
}
fn main() {
foo(&String::from("hello"));
foo(&"unknown");
foo(&vec![1u32]);
foo(&vec![1i32]);
}
relies on an implementation detail of rustc for soundness, would need to either be a blessed part of std or requires strong regression tests. Please do not use this in production :3
The idea is that closures inherit the type parameters of the current body without considering them for outlives constraints.
Metadata
Metadata
Assignees
Labels
No labels