Nutype 0.7.0 - conditional derives with cfg_attr and more
Serhii Potapov April 25, 2026 #rust #macro #newtype #nutypeI'm happy to announce the release of Nutype v0.7.0! This release brings one of the most-requested features (conditional derives via cfg_attr) along with a handful of smaller but useful additions. The full release notes are on GitHub.
What is Nutype?
Nutype is a Rust procedural macro for type-driven domain modeling. It takes the classic newtype pattern and turns it into a tool for encoding business rules directly into the type system, in the spirit of "parse, don't validate" and making illegal states unrepresentable.
You declare sanitizers (trim, lowercase, custom transformations) and validators (length, range, regex, predicates, custom error types) once, and nutype generates a refined wrapper type around your primitive (String, i32, f64, generics, anything). The generated constructor is the single gate: once a value is inside, it carries its invariants with it across function boundaries, API layers, configuration loaders, serde deserialization, FromStr parsing, and arbitrary fuzzing. So if a function takes a Username, you know it is a valid username, no defensive checks, no scattered assertions, no "did someone already trim this?" questions.
What's new in Nutype 0.7.0
Conditional derives via cfg_attr
Until now, every trait in derive(...) was unconditionally derived. With v0.7.0 you can gate any subset of traits behind a cfg predicate, mirroring the standard #[cfg_attr(...)] syntax:
;
Here Serialize and Deserialize are only derived when the serde feature is enabled. The same pattern works with cfg(test), with complex predicates like all(...), any(...), not(...), and with multiple cfg_attr(..) lines stacked together.
where clauses in generic newtypes
Generic newtypes now accept full where clauses, including Higher-Ranked Trait Bounds:
where
for<'a> &'a C: IntoIterator;
Constructor visibility
You can now control the visibility of the generated ::new() / ::try_new() constructors:
;
Any standard Rust visibility is accepted: pub, pub(crate), pub(super), pub(in path), and private. With private, the constructor is only callable from the module where the type is defined, which is handy for types that should only be obtained through a higher-level factory.
UTF-16 length validators
For interop with JavaScript and similar ecosystems that count string length in UTF-16 code units, v0.7.0 introduces two new validators: len_utf16_min and len_utf16_max.
;
These complement the existing len_char_min / len_char_max (Unicode chars) validators.
Deriving Valuable
Behind the valuable feature flag you can now derive Valuable, which is useful for structured logging with tracing and similar instrumentation:
;
Breaking change: derive_unsafe is now derive_unchecked
The derive_unsafe feature flag and attribute introduced in v0.6.2 have been renamed to derive_unchecked. The mechanism does not involve unsafe Rust at all, so the new name reflects what it actually does: bypass nutype's internal safety checks.