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.