Non-zero generic

Hi, I have a partial function like:

fn foo<T1, T2>(x: T1, y: T2) -> Option<T2> where...

I've seen that I could make it total restricting the input like this:

fn foo<T1, T2>(x: T1, y: NonZero<T2>) -> T2 where...

Turning/writing functions into total ones is an excellent thing to do, in general. Good modern languages need to do all they can to help this!

But the stdlib has NonZeroXXX instead of NonZero<> (for reasons I don't know). Do you have ideas?

1 Like

What sort of operations do you need to perform on the generic types?

Reminder/division (but how is that important for the topic?)

One option would be something like this:

trait HasNonZero {
    type NonZero;
    fn from_nonzero(v: Self::NonZero) -> Self;
}

impl HasNonZero for u8 {
    type NonZero = std::num::NonZeroU8;
    fn from_nonzero(v: Self::NonZero) -> Self {
        v.get()
    }
}
impl HasNonZero for u16 {
    type NonZero = std::num::NonZeroU16;
    fn from_nonzero(v: Self::NonZero) -> Self {
        v.get()
    }
}
impl HasNonZero for u32 {
    type NonZero = std::num::NonZeroU32;
    fn from_nonzero(v: Self::NonZero) -> Self {
        v.get()
    }
}

You can now do:

fn foo<T1, T2>(x: T1, y: T2::NonZero) -> T2
where
    T2: HasNonZero,
    T1: Div<T2::NonZero, Output = T2>,
{
    x / y
}

or alternatively

fn foo<T1, T2>(x: T1, y: T2::NonZero) -> T2
where
    T2: HasNonZero,
    T1: Div<T2, Output = T2>,
{
    x / T2::from_nonzero(y)
}
1 Like