Zero-sized-type that implements numeric traits

Hi Everyone,

Is there a standard zero-sized-type that implements all of the numeric traits? i.e. Ord + Sub + Div + Add + AddAssign + etc.? I couldn't find one on crates.io, but perhaps I wasn't looking in the right place.

My thinking is that - since all ZST instances are identical, the result of any math operation involving the ZST is just the ZST.

I need this because I have some generic code that does a lot of math ops, and now I need to instantiate one with a "NULL" type. Unfortunately () doesn't implement any of the traits.
I could write my own but I figured I'd ask whether or not there was already one people are using.

Thank you in advance.

Not that I'm aware of.

There is no mathematical relation in your way of thinking. I could argue, that () represents 0, (()) represents 1, ((())) represents 2 and so on. They all have 0 size, but their types carry semantics and their type does have a size during compilation. Therefore, you cannot treat ZSTs like they have no meaning and treat them like they all have the same semantics as floating point NaN.

3 Likes

Perhaps I wasn't clear in how I stated my question. I didn't mean to say "All ZSTs across the entire language should behave like NaN." I was trying to ask "Is there a ZeroSizedNaN that has already been implemented in some crate somewhere?"

It only took me 20 minutes to roll my own, but I thought it's better to use the standard one than to reinvent the wheel.

Thanks for the reply.

2 Likes

In fact, this is the core operating principle of the typenum crate.

3 Likes

I think what you'd like to see is Option implementing mathematical operations for inner types, that also implement them. I do think that'd be convenient to have for integers, where there is no NaN.

P.S.: How does division by zero even work for integers? Is it a no-op or does it return either 0 or something else?

1 Like

The Rust compiler catches an impressive number of attempts to divide by zero, but for the ones it can't catch, it's a panic at runtime.

An integer-type (or other numerical type) that could also hold a nan along the lines you suggest is a cool idea. But I believe an Option will still consume, at a minimum, the storage required for the Some() variant. So my goal of a zero-sized type is somewhat different.

use core::mem::size_of;

enum Void {}

fn main() {
    println!("{}", size_of::<Option<Void>>()); // Outputs: 0
}

(playground)

Also there’s an argument for making rust have the ! type (which would take the role of Void here) automatically implement every trait where all methods take some kind of self argument. In this case, an Option implementation for these kinds of numerical operations traits would translate into the right implementaiton for Option<!>.

1 Like