The trait Any
has a method is
. If I define another trait trait Trait: Any
. &Trait
does not get the is
method. play
I know that Trait: Any
just means that anything which implements Trait
also implements Any
. So anywhere you use Trait
, you can call methods defined on Any
as well.
Since All Trait
is also an Any
, I don't understand why it's not possible to call is
on it.
Can anyone explain? I couldn't find any resources about this inherent Trait methods anywhere.
Trait objects like &Trait
can't call generic methods like is<T>
, because the vtable would need individual function pointers for all possible T
!
edit: this may not be the whole story, because a non-object fn foo<T: Trait>(x: &T)
also can't call x.is::<i32>()
.
is
isn't in the vtable though. It's an inherent method of the Trait object.
Before you could consider having Any::is
be automatically promoted to Trait::is
, you'd need some way to coerce an &Trait
to an &Any
. Try it, it just doesn't work. Absent that coercion, there's no way you could call Any::is
with an &Trait
argument, so there's no way that Trait::is
could be implemented in terms of Any::is
. There's an open issue for adding this kind of coercion to the language, but it hasn't really been touched for a while (note the wonky ancient syntax in the original issue).
1 Like
Ah, thanks, I missed that detail.
Thanks. I've decided to add a as_any
method to the trait and implement it for all types via a macro.
You don't need a macro. You can do it if you use a helper trait:
trait AsAny {
fn as_any(&self) -> &Any;
}
impl<T> AsAny for T
where
T: Sized + 'static,
{
fn as_any(&self) -> &Any { self }
}
trait Trait: AsAny {}
2 Likes
That's great. I'll use that. Thanks a lot.
I have one more question: Using Self: Sized on the Trait would fix the problem but using that makes it unable to make the trait into a trait object. It seems counter-intuitive to me as unsized objects cannot be made into a trait object anyway 
The Trait
object type itself (let's call it dyn Trait
) is unsized, and it has to implement Trait
. If you had Self: Sized
then you couldn't have dyn Trait: Trait
. Technically, it could still work that way, but it was decided that having dyn Trait: Trait
only some of the time would be confusing, and it's definitely desirable that generic methods can work with object types.