Reputation: 1430
I'm trying to be generic on C
's implementation, but use individual implementations of div_array
for its member T
. For example, C::something(&self)
should use the correct implementation for the array [T; 2]
. Since T: A
, only 2 possible T
can exist: T=u32, T=u64
, so I implemented DivArray
for [u32;2]
and [u64;2]
only. While I could do a generic implementation, I really want it to be specific on each array implementation because it could use some hardware operations only available for some types, etc.
use core::marker::PhantomData;
use num_traits::Zero;
pub trait A: Zero + Copy {}
impl A for u32{}
impl A for u64{}
pub trait DivArray<'a, Rhs>: Sized + Copy {
type Output;
fn div_array(
self,
denominator: Rhs,
) -> Result<Self::Output, ()>;
}
impl<'a, Rhs: Into<Rhs>> DivArray<'a, Rhs> for [u32; 2] {
type Output = [u32; 2];
fn div_array(
self,
denominator: Rhs,
) -> Result<Self::Output, ()> {
unimplemented!();
}
}
impl<'a, Rhs: Into<Rhs>> DivArray<'a, Rhs> for [u64; 2] {
type Output = [u64; 2];
fn div_array(
self,
denominator: Rhs,
) -> Result<Self::Output, ()> {
unimplemented!();
}
}
pub struct C<T>{
_phantom: PhantomData<T>
}
impl<T: A> C<T>{
pub fn something(&self) {
let arr = [T::zero(); 2];
arr.div_array(1u64);
}
}
error[E0599]: no method named `div_array` found for array `[T; 2]` in the current scope
--> src/lib.rs:44:13
|
44 | arr.div_array(1u64);
| ^^^^^^^^^ method not found in `[T; 2]`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `DivArray` defines an item `div_array`, perhaps you need to implement it
--> src/lib.rs:9:1
|
9 | pub trait DivArray<'a, Rhs>: Sized + Copy {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
What is happening here? I clearly implemented DivArray
for all T
such that T:A
Upvotes: 1
Views: 123
Reputation: 42472
What is happening here?
Traits are not "completable" so there's no such thing as "implementing for all T: A".
Not that the compiler would care because it doesn't check: Rust typechecks generic methods as-is, before any sort of expansion, so the information it has is that that arr: [T;2]
, and it needs an impl DivArray
for that.
However all this mess seems completely unnecessary here, you can just implement your stuff for both types, possibly using a macro if you turn out to have more than two:
impl C<u32>{
pub fn something(&self) {
let arr = [0; 2];
arr.div_array(1u64);
}
}
impl C<u64>{
pub fn something(&self) {
let arr = [0; 2];
arr.div_array(1u64);
}
}
Though note that this will prevent a generic implementation: in the fulness of time an option might be specialisation (for both the original version and this one), but it's nowhere near done because it's full of unresolved soundness issues.
Upvotes: 1