non_zero/lib.rs
1#![no_std]
2//! # non-zero
3//!
4//! A macro for creating constant non-zero integers (with type inference).
5//!
6//! There are multiple crates that address the issue of initialising non-zero integers.
7//! However, most of them lack type inference.
8//! This is why I created `non_zero!`.
9//! It uses `const` blocks to evaluate the literals at compile time whilst achieving type inference.
10//!
11//! The definition is essentially this:
12//!
13//! ```
14//! macro_rules! non_zero {
15//! ($n:expr) => {
16//! const {
17//! NonZero::new($n).unwrap()
18//! }
19//! };
20//! }
21//! ```
22//!
23//! Some things of note:
24//!
25//! - `$n:expr` allows for any expression to be passed to the macro, so long as it is evaluable in a `const` context.
26//! - The `const` block is discussed above.
27//! - `NonZero` is the `std` generic non-zero type to which all `NonZero***` are aliased.
28//! The generic argument can be inferred, not only from `$n` but also from the macro's usage.
29//! - `.unwrap()` inside the `const` block will cause a compile-time error, not a runtime one.
30//!
31//! The above implementation is somewhat simplified;
32//! the real definition produces prettier errors than `unwrap` and is more hygienic.
33//!
34//! ## Naming
35//!
36//! This crate uses the same name as `std` does for its types.
37//! Namely, with a hyphen between "non" and "zero".
38//! In `snake_case` the hyphen becomes an underscore and in `PascalCase` it creates a word break.
39
40/// A macro for creating non-zero integers.
41///
42/// See the [crate level docs](crate).
43#[macro_export]
44macro_rules! non_zero {
45 ($n:expr) => {
46 const {
47 // prettier errors
48 if $n == 0 {
49 panic!("tried initialising a non-zero value to zero")
50 }
51 ::core::num::NonZero::new($n).unwrap()
52 }
53 };
54}