genericsrusttraits

Idiomatic solution to enforce trait bounds


So I have a struct WeatherStation which consists of a name: String and probability distribution function which should implement the rand::distr::Distribution trait. It look something like this:

struct WeatherStation<'a, D> {
    name: &'a str,
    distribution: D,
}

I also have 2 methods on that struct:

impl<'a, D> WeatherStation<'a, D> {
    fn new(name: &'a str, distribution: D) -> Self {
        Self {
            name,
            distribution,
            _marker: PhantomData
        }
    }

    fn measurement<T>(&self) -> T
    where
        T: Float,
        D: Distribution<T>
    {
        self.distribution.sample(&mut rand::rng())
    }
}

My question is how should I best enforce these trait bounds.

Here are my ideas:

Which one of these should I use and why? Is there a more idiomatic way to do this?


Solution

  • Your "idea 1" is the most idiomatic Rust. Note in particular that the standard library takes this approach -- for example, HashMap::new does not require any particular bounds, but anything that could actually fetch/insert will require K: Hash + Eq.

    As far as whether T should be part of the type, that ultimately depends on factors not apparent from your question. For example, if you are relying on a specific WeatherStation instantiation to convey information about the type of the distribution that should be used in all cases, then you could do this (though I would use PhantomData<fn() -> T> as this helps the borrow checker know that your type doesn't actually contain a T). You could also need to do this in particular trait implementation scenarios, where you need to add another type to be able to differentiate blanket impls.