nestum
nestum makes nested enum paths and matches feel natural, so you can codify invariants by nesting related enums while keeping ergonomic construction and matching.
Instead of:
Documents
you can write:
Update
The biggest win is matching:
nested!
It works by generating a shadow module hierarchy and wrapper constructors, plus a match macro that rewrites nested patterns.
Where this pays off:
- Event routing and message buses.
- Permission or policy trees (resource + action).
- Parsers/compilers (node + kind).
- UIs with nested state machines.
The point is to encode invariants as nested enums (this variant always contains this family of sub-variants) without paying a readability or ergonomics tax when constructing or matching.
Quick Start
use nestum;
Concepts
Shadow module
When #[nestum] is applied to an enum, the macro replaces it with a module of the same name.
Inside that module, it re-emits the original enum and creates submodules for nested variants.
Those submodules expose wrapper constructors that build the outer enum.
This means the enum type itself is accessed as EnumName::EnumName.
Nested variant detection
A variant is treated as nested if and only if:
- it is a tuple variant with exactly one field, and
- the inner field’s type is a simple enum ident that is also marked with
#[nestum]in the same module.
This keeps nesting explicit without requiring per-variant annotations.
Cross-module nesting
To nest an enum declared in a different module file, use an external path on the variant:
use nestum;
This resolves crate::inner::Inner to src/inner.rs or src/inner/mod.rs and generates wrappers.
API Summary
#[nestum] on enums
Enables shadow-module generation and wrapper constructors.
#[nestum(external = "path::to::Enum")] on variants
Opt-in support for nesting an enum in another module file.
nestum_match! { match value { ... } } / nested! { match value { ... } }
Macro that rewrites nested patterns (like Enum1::Variant1::VariantA) into real enum patterns.
Examples
Basic nesting
let _ = Update;
let _ = Delete;
Cross-module nesting
let _ = A;
Nested match patterns (front and center)
use ;
let event = Update;
nested!
Limitations
- External crates are not supported (proc macros can’t reliably inspect other crates’ ASTs).
- The macro only resolves enums from source files in the current crate.
#[path = "..."],include!(), and complexcfglayouts may not be resolved.
Error Messages
nestum emits detailed compile-time errors, including:
- invalid
#[nestum(...)]usage, - misuse on variants,
- external path mismatches,
- missing module files or enums.
FAQ
Why does the enum type become EnumName::EnumName?
Because nestum replaces the enum with a module of the same name. The original enum is re-emitted inside it.
How do I pattern match with nested paths?
Use nested! (or nestum_match!) so paths like Event::Documents::Update are rewritten to the real enum pattern.
Why not support external crates?
The macro would need to discover and parse dependency source files, which is brittle and not reliably possible in stable proc-macro APIs.
License
MIT