rrevenantt / better_any

Better type id and Any for Rust
Apache License 2.0
11 stars 5 forks source link

Static TypeId #8

Open stepancheg opened 1 year ago

stepancheg commented 1 year ago

If TypeId::of accepted non-static types, better_any implementation would be much simpler, right?

If so, should we try to ask rust-lang team to accept non-static types in TypeId::of?

Context: we are not using better_any, but we have similar implementation in our library. We looked at better_any to fix unsoundness issue in our implementation. We could not find unsoundness in better_any (and in our fixed implementation).

dtolnay commented 6 months ago

TypeId already works for non-static types by doing this:

use core::any::TypeId;
use core::marker::PhantomData;
use core::mem;

pub fn non_static_type_id<T: ?Sized>() -> TypeId {
    trait NonStaticAny {
        fn get_type_id(&self) -> TypeId where Self: 'static;
    }

    impl<T: ?Sized> NonStaticAny for PhantomData<T> {
        fn get_type_id(&self) -> TypeId where Self: 'static {
            TypeId::of::<T>()
        }
    }

    let phantom_data = PhantomData::<T>;
    NonStaticAny::get_type_id(unsafe {
        mem::transmute::<&dyn NonStaticAny, &(dyn NonStaticAny + 'static)>(&phantom_data)
    })
}

This produces TypeId values which are 100% compatible with ones obtained in the usual way.

fn assert_t_is_str<T>() {
    assert_eq!(non_static_type_id::<T>(), TypeId::of::<&str>());
}

fn main() {
    assert_t_is_str::<&str>();
}
stepancheg commented 6 months ago

@dtolnay thanks!

It is even optimized properly (compiler explorer).

And even works in const context if we add

#![feature(const_trait_impl)]
#![feature(effects)]