Summary
Remove the 'static bound from the type_id intrinsic so users can experiment with reflection over non-static types.
Motivation
A common method for storing a map of arbitrary data is to use something like a HashMap<TypeId, Box<Any>>. The problem is that a TypeId can only be constructed for a static type. This is a reasonable constraint for the stable API, because lifetimes may need to play a part in equality checks by type id. However there are cases where a user is boxing trait objects to work around lifetimes, so they only need to guarantee that data stored with a particular key is of a particular type.
This can be worked around on Rust now by using a trait with an associated type that’s expected to be a 'static version of the implementor:
unsafe trait Keyed {
type Key: 'static;
}
struct NonStaticStruct<'a> {
a: &'a str
}
unsafe impl <'a> Keyed for NonStaticStruct<'a> {
type Key = NonStaticStruct<'static>;
}
The Keyed trait needs to be marked as unsafe because it could lead to undefined behaviour if implemented incorrectly and used for transmuting memory.
This RFC proposes simply removing the 'static bound from the type_id intrinsic, leaving the stable TypeId and Any traits unchanged. That way users who opt-in to unstable intrinsics can build the type equality guarantees they need without waiting for stable API support.
This is an important first step in expanding the tools available to users at runtime to reason about their data. With the ability to fetch a unique type_id for non-static types, users can build out their own TypeId or Any traits.
Detailed design
Remove the 'static bound from the type_id intrinsic in libcore.
How We Teach This
This changes an unstable compiler intrinsic so we don’t need to teach it.
Drawbacks
Alternatives
Create a new intrinsic that’s specifically designed never to take lifetime information into account. This intrinsic would behave exactly as type_id does now. Having a totally separate intrinsic means type_id could evolve without breaking existing expectations.