This is my first RFC, providing a way for a trait to get the TypeId when Self: 'static
while still being sound, and without breaking backwards compatibility. Could I get some feedback? Thanks! https://github.com/leo60228/rfcs/blob/master/text/0000-knowntypeid.md
I don't really understand how this can be more sound than Any
if it's almost the same as Any
except that it removes a restriction from implementors. Any
requires Self: 'static
for a good reason: there's currently no way to express the difference (at runtime) between types of the same base type but different lifetimes using a TypeId
. Thus, allowing non-'static
types to be downcast based on identical TypeId
s would enable one to essentially transmute away lifetimes. AFAICT the addition of an Any
-like trait without this restriction would only introduce a soundness hole.
This isn't more sound than Any
, but it is easier to use because it doesn't require 'static
at the trait level. What this allows is making other traits act like Any
by just adding it as a bound on other traits. For example, this would allow sound Error
downcasting without a breaking change. This seems like a good idea, and I think that we should consider this a bit more.
The Self: 'static
bound was not removed, it was moved to KnownTypeId::type_id
.
Oh, right. It seems that I completely missed that part.
The trait KnownTypeId
is implemented for all T
so it can not be manually implemented at all (contrary to Error
which can). And even if specialization were to allow it, it was marked unsafe
so that providing such an implementation could be defined as not being sound.
I think the RFC could do with maybe a short example of how a library could use this to provide downcasting on a trait that doesn't require Any
.
Downcasting isn't even available on a trait that explicitly requires Any
as downcast_ref
is only on dyn Any
directly, not the trait and upcasting isn't a thing yet.
So with or without this we still need an easy and safe way to do downcasting on other traits.
I try making some generic free functions but since dyn NotAny + 'static
impls Any
no error message is given for missuses.
I've added an example of this.
The goal of this was to make it possible to soundly support downcasting on an arbitrary trait, not safely. As far as I understand, it's not possible to automatically support downcasting on any trait object without a macro (which could be trivially implemented with this RFC).
Traits wanting to support downcasting can add it as a supertrait, without breaking backwards compatibility.
If it is implemented for all types, why does it even have to be added as a supertrait?
Oh, I guess the point is that self.type_id
will consult the vtable to figure out the ID of the "actual" type. It took me a bit of staring at this and wondering why you couldn't just call that. This should be explained better in the RFC.
I added a sentence and playground link explaining this.
I wasn't aware that was possible. Thanks! I'll update the examples.
Never mind, I misunderstood your post. Sorry!
Thanks!
I think it would be a good idea to also add a comment saying basically the same thing in your code in fn is
, to answer the question right at the place where it comes up instead of 5 paragraphs later.
Done.
Do you guys think this looks ready to PR?
Could we move the is
function into the trait like so
trait WithTypeId {
fn tye_id(&self) -> TypeId where Self: 'static {
TypeId::of::<Self>()
}
fn is<T: 'static>(&self) -> bool where Self: 'static {
self.type_id() == TypeId::of::<T>()
}
}
That wouldn't work, since is
wouldn't be object safe.
Right, forgot about that!