# How to limit a generic in the function for an implementation

I could use some help figuring out the best way in rust to implement a function that requires different implementations for different generic types of numbers. See this code, which compiles and runs fine:

``````use rand::Rng;
use rand::prelude::Distribution;
use rand::distributions::Standard;
use geo::{ Point, CoordNum};

trait RandomPoint
{
type CoordType;

fn random() -> Self;

fn random_ceil(max: Self::CoordType) -> Self;
}

impl<T: num_traits::Signed> RandomPoint for Point<T>
where T: CoordNum + rand::distributions::uniform::SampleUniform, Standard: Distribution<T>,
{
type CoordType = T;

fn random() -> Point<T> {
Point::new(rng.gen(), rng.gen())
}

fn random_ceil(max: T) -> Point<T>
//		where T: num_traits::Signed, // cannot have both
{
let min = -max; // cannot apply unary operator `-` unless limited to <T: num_traits:Signed> as above
Point::new(rng.gen_range(min..=max),
rng.gen_range(min..=max))
}
}

fn main() {
let p1 = Point::new(1., 2.);
let p2 = Point::new(1, 2);
let p_random: Point<f32> = Point::random();
let p_random2: Point<i32> = Point::random();
let p_rand_ceil: Point<i32> = Point::random_ceil(10);

dbg!(p1);
dbg!(p2);
dbg!(p_random);
dbg!(p_random2);
dbg!(p_rand_ceil);
}
``````

Right now, the above implementation of `RandomPoint` is limited to Signed coordinates. I would like to know the best way to implement the `random_ceil` function so that it can handle both Signed and Unsigned.

Do I need to write a whole second implementation, like:

``````impl<T: num_traits::Unsigned> RandomPoint for Point<T>
...
``````

It doesn't seem like that is possible, as I get "conflicting implementations of trait `RandomPoint` for type `geo::Point<_>" from the compiler if I try to implement it twice.

So is there a better way to accomplish this? Could I limit the `random_ceil` function instead, so that I can have two different `random_ceil` functions in the same implementation, one for `Signed` and one for `Unsigned` coordinates (presumably for unsigned, min would be set to 0 somehow)? Any suggestions would be much appreciated!

For this particular case, you could use `Zero` and `SaturatingSub`.

``````// (Some code elided)
impl<T> RandomPoint for Point<T>
where
T: num_traits::SaturatingSub + num_traits::Zero,
{
fn random_ceil(max: T) -> Point<T>	{
let min = T::zero().saturating_sub(&max);
Point::new(
rng.gen_range(min..=max),
rng.gen_range(min..=max),
)
}
}
``````

Intriguing, but `SaturatingSub` appears to be only implemented for integers, not for floats. So I am still stuck with having `random_ceil` either handle signed number or handling integers, but not able to handle all numbers. Short of adding a second function, something like, `random_ceil_min0`, is there a better way to handle all numbers in `random_ceil`?

Upon further investigation, enabling `core_intrinsics` and using `cargo +nightly run` will work. Please feel free to suggest a better solution that does not require this unstable feature! Example code:

``````#![feature(core_intrinsics)]

use rand::Rng;
use rand::prelude::Distribution;
use rand::distributions::Standard;
use geo::{ Point, CoordNum};

trait RandomPoint
{
type CoordType;

fn random() -> Self;

fn random_ceil(max: Self::CoordType) -> Self;
}

impl<T> RandomPoint for Point<T>
where T:  CoordNum + rand::distributions::uniform::SampleUniform, Standard: Distribution<T>,
{
type CoordType = T;

fn random() -> Point<T> {
Point::new(rng.gen(), rng.gen())
}

fn random_ceil(max: T) -> Point<T>
{

let min = std::intrinsics::saturating_sub(T::zero(), max); // -max or 0
Point::new(rng.gen_range(min..=max),
rng.gen_range(min..=max))
}
}

fn main() {
let p1 = Point::new(1., 2.);
let p2 = Point::new(1, 2);
let p_random: Point<f32> = Point::random();
let p_random2: Point<i32> = Point::random();
let p_rand_ceil: Point<i32> = Point::random_ceil(10);
let p_rand_uint: Point<u8> = Point::random_ceil(10);

dbg!(p1);
dbg!(p2);
dbg!(p_random);
dbg!(p_random2);
dbg!(p_rand_ceil);
dbg!(p_rand_uint);
}
``````

Tried it and still doesn't work.. When I actually try to pass a float to `random_ceil`, I get:

error[E0511] : invalid monomorphization of `saturating_sub` intrinsic: expected basic integer type, found `f32`

So even though I thought `saturating sub` took all numbers, it apparently balks at floats. So I still don't know how to handle both floats and non-floats at the same time.

Ah, sorry about that. I guess you need a different motley collection of ops. Does this cover all the types you need?

``````// Assumes `max >= 0`, perhaps return `max` itself is < 0
// (e.g. `-128i8` will overflow)
fn min_from<T>(max: T) -> T
where
T: Num + Bounded + PartialOrd,
{
let zero = T::zero();
if T::min_value() < zero {
// Signed
zero - max
} else {
// Unsigned
zero
}
}
``````

As for the original question, Rust doesn't have mutually exclusive traits yet, so it can't understand that an implementation bounded on `Signed` cannot overlap with one bounded on `Unsigned`. Thus two generic implementations will overlap -- what if something implements both `Signed` and `Unsigned`? (There's no way to express that it is impossible yet.)