I think this is an abitrary and unneccasary restriction within the Rust compiler. You can implement a method within a trait. This method is a 'Material' and thus &self only must map to an &dyn Material to execute the method properly. Now I get you can't have a generic unimplemented trait method because you have to guarantee everything that implements that trait must have a generic mapped method or else you might not be able to dispatch it correctly. A method in a separate dll could fail since it wouldn't know to implement some generic versions then when it is passed in as a vtable it could fail.
However, an implemented generic method will work with any &dyn Material. Therefore you can always know what method to dispatch to. It doesn't EVER need to use a vtable dispatch. It's already implemented to take any &dyn Material.
Is there a reason I'm not understanding why this is 'bad'? This seems just like a silly restriction that solves no problems. Is there a place to make a proposal for implemented generic trait methods? Seems like a powerful addition to traits.
pub trait Material : Sync + Send
{
fn as_vulkan_material(&self) -> &VulkanMaterial;
fn set_value_by_ptr(&self, name: &str, ptr: *const u8, size: usize);
fn upload_uniforms(&self);
fn set_matrix(&self, name: &str, matrix: Mat4) {
unsafe
{
let ptr = std::mem::transmute::<*const Mat4,*const u8>(&matrix as *const Mat4);
self.set_value_by_ptr(name, ptr, std::mem::size_of::<Mat4>())
}
}
fn set_values<T: Sized + Copy>(&self, name: &str, value: T) {
unsafe
{
let ptr = std::mem::transmute::<*const T,*const u8>(&value as *const T);
self.set_value_by_ptr(name, ptr, std::mem::size_of::<T>())
}
}
}
error[E0038]: the trait `Material` cannot be made into an object
--> rcubed\src\rendering\material.rs:39:61
|
39 | pub fn create(options: &MaterialCreationOptions) -> Arc<dyn Material> {
| ^^^^^^^^^^^^ `Material` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> rcubed\src\rendering\material.rs:19:8
|
5 | pub trait Material : Sync + Send
| -------- this trait cannot be made into an object...
...
19 | fn set_values<T: Sized + Copy>(&self, name: &str, value: T)
| ^^^^^^^^^^ ...because method `set_values` has generic type parameters
= help: consider moving `set_values` to another trait