Static trait methods, that is, those without a self
argument (associated functions), are currently considered non-object safe. The reason is there is no self
argument to do dynamic dispatch on.
However, it would be possible to allow those associated functions callable on trait objects, by taking &dyn Trait
as the first argument, and looking up the function pointer in the vtable. For example:
trait Trait {
fn associated_function(x: i32) -> i32;
fn takes_raw_pointer(trait_object: &dyn Trait) {
let y = Trait::associated_function(trait_object, 3);
println!("y = {}", y);
}
}
In fact, this is already sort of possible, in a hacky, unstable way, using raw-pointer receivers (enabled by the arbitrary_self_types
feature).
trait Trait {
fn associated_function(x: i32) -> i32 where Self: Sized;
fn takes_raw_pointer(self: *const Self, x: i32) -> i32 {
Self::associated_function(x)
}
}
fn takes_trait_object(trait_object: &dyn Trait) {
let y = Trait::takes_raw_pointer(self as *const Self, 3);
println!("y = {}", y);
}
EDIT: after posting, I realized that takes_raw_pointer
could be replaced with a method taking &self
, and it would also work, and not need any unstable features. I guess I wanted to call to attention the fact that you can create a null trait object and still call takes_raw_pointer
on that. For example, you could do (ptr::null::<!> as *const Trait).takes_raw_pointer()
, even though there exists no value of type !
.
Since this only requires a valid vtable, this could be extended to let the function be called on *const dyn Trait
, or the vtable itself.
Is there any interest in this?