Home > Software design >  Forcing two generics to be the same in impl
Forcing two generics to be the same in impl

Time:06-08

I have a Hittable trait, with a method that returns a generic implementing Material:

pub trait Hittable {
    fn hit<T>(&self -> Option<HitRecord<T>>
    where T: Material;
}

And an implementation of this trait on a Sphere<T>:

impl<T> Hittable for Sphere<T>
where T: Material
{
    fn hit(&self) -> Option<HitRecord<T>> {
        // snip
    }

I want the T in HitRecords to be the same as the T in Sphere<T>, but as of now now it will not compile because I need to annotate the hit method in the impl with a T as well. But if I do so, the 2 T's will not be forced to be the same. How do I enforce that?

CodePudding user response:

You should uplift the generic parameter from the method into the trait:

pub trait Hittable<T: Material> {
    fn hit(&self) -> Option<HitRecord<T>>;
}

impl<T: Material> Hittable<T> for Sphere<T> {
    fn hit(&self) -> Option<HitRecord<T>> {
        // snip
    }
}

Another way is to use an associated type (it models the situation better, but as long as you only implement the trait for one generic parameter it doesn't practically matter):

pub trait Hittable {
    type T: Material;
    fn hit(&self) -> Option<HitRecord<Self::T>>;
}

impl<T: Material> Hittable for Sphere<T> {
    type T = T;
    fn hit(&self) -> Option<HitRecord<T>> {
        // snip
    }
}
  • Related