Skip to content

koeninger/zero-cost-newtype

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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);
}

About

rust newtypes with zero additional runtime cost

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages