You're correct that Rust provides NonZeroI8, which in fact I called out in my text. If you look at the source, you'll see that the Rust standard library is allowed to make this type but you can't in stable Rust,
[rustc_layout_scalar_valid_range_start(1)] means, "Hey, Rust compiler, I promise it's fine to just assume I never have this value: 0". You absolutely could write BalancedI8.... if you're the Rust standard library. Unfortunately you aren't allowed to do that in your own stable Rust software because it needs these compiler internals.
There were discussions about stabilising this idea, and they were knocked back because if you do that you're basically stuck with it forever.
One day in the future NonZeroI8 could "just" be a Pattern Type, like the ones you can make at home, but today there are no Pattern Types and NonZeroI8 needs compiler magic.
There are other Rust core types which you could make yourself, IPv4Addr for example is just a 32-bit value, you could make your own, but yours wouldn't be on everybody's Rust system. Option<&T> is just a sum type over &T and None, you genuinely could make your own, call it Maybe<&T> and it would work exactly the same - same optimisations even, although not all the compiler diagnostic messages would be as good if you use it wrong I think. But today NonZeroI8 isn't like them, it actually needs a sprinkle of compiler magic.
You're correct that Rust provides NonZeroI8, which in fact I called out in my text. If you look at the source, you'll see that the Rust standard library is allowed to make this type but you can't in stable Rust,
[rustc_layout_scalar_valid_range_start(1)] means, "Hey, Rust compiler, I promise it's fine to just assume I never have this value: 0". You absolutely could write BalancedI8.... if you're the Rust standard library. Unfortunately you aren't allowed to do that in your own stable Rust software because it needs these compiler internals.
There were discussions about stabilising this idea, and they were knocked back because if you do that you're basically stuck with it forever.
One day in the future NonZeroI8 could "just" be a Pattern Type, like the ones you can make at home, but today there are no Pattern Types and NonZeroI8 needs compiler magic.
There are other Rust core types which you could make yourself, IPv4Addr for example is just a 32-bit value, you could make your own, but yours wouldn't be on everybody's Rust system. Option<&T> is just a sum type over &T and None, you genuinely could make your own, call it Maybe<&T> and it would work exactly the same - same optimisations even, although not all the compiler diagnostic messages would be as good if you use it wrong I think. But today NonZeroI8 isn't like them, it actually needs a sprinkle of compiler magic.