Skip to content

Latest commit

 

History

History
45 lines (36 loc) · 1.61 KB

README.md

File metadata and controls

45 lines (36 loc) · 1.61 KB

The newtype pattern in Rust won't always generate the same code as the equivalent primitive type, https://blog.polybdenum.com/2021/08/09/when-zero-cost-abstractions-aren-t-zero-cost.html

This library provides macros to work around that. It generates a typesafe tuple struct in debug mode, and a type alias in release mode which should perform exactly the same as the primitive type.

All of the operators from newtype_derive_2018 are available.

Example:

mod types {
    // you want everything in scope because the macro expansion depends on macro_attr_2018
    use zero_cost_newtype::*;

    // in debug mode this is `struct Price(i32)` and a macro Price! as a constructor
    // in release mode `type Price = i32`
    newtype! {
      #[derive(Debug, Clone, Copy, PartialEq, NewtypeAdd!, NewtypeDisplay!)]
      Price: i32
    }
}

fn main() {
    // see issue #52234
    use crate::*;
    use types::Price;
    use zero_cost_newtype::cast;

    // in debug mode this is `= Price(23)`, in release mode `= 23`
    let p: Price = Price!(23);
    let p2 = Price!(7);
    assert_eq!(p + p2, Price!(30));
    println!("display works {p2}");

    // won't compile in debug mode, can't accidentally add unrelated types.
    // in release mode it would compile,  but you're safe as
    // long as you compiled in debug during development.
    //
    // let result = 42 + p;

    // if you need an escape hatch use cast! rather than .0 or .into or .from;
    // it's a no-op in release mode and .0 in debug mode.
    let result = 42 + cast!(p);
    assert_eq!(result, 65);
}