Summary
When a crate defines a large number of bitflags! types, rustc memory consumption and compilation time grow approximately linearly with the number of generated types. The growth is large enough to make real-world scenarios hit practical memory limits.
The issue appears to be primarily related to the number of generated trait implementations, as the bitflags! macro generates implementations for several traits (such as Add, Sub, BitOr, etc.) for the type.
Reproducer
Cargo.toml
[package]
name = "rustc-mem-measure"
version = "0.1.0"
edition = "2024"
[dependencies]
bitflags = "2.13.0"
src/lib.rs
use bitflags::bitflags;
macro_rules! create_bitflags_instance {
($name:ident) => {
bitflags! {
pub struct $name: u64 {
const BIT0 = 1 << 0;
const BIT1 = 1 << 1;
const BIT2 = 1 << 2;
const BIT3 = 1 << 3;
const BIT4 = 1 << 4;
const BIT5 = 1 << 5;
const BIT6 = 1 << 6;
const BIT7 = 1 << 7;
}
}
};
}
create_bitflags_instance!(Type0);
create_bitflags_instance!(Type1);
create_bitflags_instance!(Type2);
create_bitflags_instance!(Type3);
create_bitflags_instance!(Type4);
create_bitflags_instance!(Type5);
create_bitflags_instance!(Type6);
create_bitflags_instance!(Type7);
create_bitflags_instance!(Type8);
create_bitflags_instance!(Type9);
// ...
Note that the create_bitflags_instance! macro is only used to simplify the example. Replacing it with manually written type definitions has only a minimal effect on resource consumption.
Observed scaling
| Type count |
Memory usage (MB) |
Time (s) |
| 1 |
33.3 |
0.2 |
| 10 |
63.2 |
1.0 |
| 100 |
393.5 |
9.7 |
| 1000 |
4391.5 |
104.6 |
Memory usage and compile time both scale approximately linearly with the number of generated bitflags! types.
Toolchain
The measurements were collected using a custom debug-built toolchain (dc375db7d8df0aa450e622c529147c95eee756f5). However, similar behavior is observed across multiple toolchain versions, including Rust 1.80 through the latest stable available at the time of writing (1.96.0 (30a34c682 2026-05-25)).
Profiling information
Using the debug-built toolchain, the largest memory consumers observed in the rustc process were:
| MB |
% of useful heap |
Consumer |
| 797.7 |
18.16% |
2,714 places below Massif threshold |
| 502.4 |
11.44% |
rustc_resolve::Module::for_each_child / Resolver::finalize_imports |
| 438.5 |
9.99% |
rustc_arena::DroplessArena::grow |
| 386.6 |
8.80% |
rustc_middle::dep_graph::CurrentDepGraph::record_edge |
| 367.7 |
8.37% |
indexmap::Core<rustc_span::SpanData, ()>::insert_full |
Real-world impact
This issue was discovered while developing the Arm system register crate: arm-sysregs The crate generates types and accessors for Armv8-A system registers. Currently only about 25% of the registers are covered, yet builds are already approaching CI memory limits (~3 GB).
The current scaling is therefore problematic because:
- Memory requirements continue to grow as more registers are added. When the crate is complete, the extrapolated memory usage of rustc will be ~12GB.
- Downstream projects compiling the crate inherit the cost.
- Parallel builds amplify the problem because multiple
rustc processes compete for memory simultaneously.
Questions
- Are there known coding patterns in
bitflags!-generated code that contribute disproportionately to memory usage and should be avoided?
- Are there ongoing or planned efforts to reduce
rustc memory consumption for workloads involving large numbers of types and trait implementations?
- The profiling results suggest significant memory usage in dependency graph tracking and related compiler infrastructure. Would it be feasible to introduce more cache-like behavior where less frequently used entries can be discarded and recomputed when necessary, rather than retaining all information for the duration of compilation?
- Are there alternative approaches, compiler flags, or code-generation patterns that could mitigate this issue?
Expected outcome
rustc memory usage for this pattern could be reduced substantially, or
- Guidance could be provided on which language/library patterns are responsible for the scaling and how generated code can be structured to avoid them.
Any suggestions for investigation or mitigation would be greatly appreciated.
Summary
When a crate defines a large number of
bitflags!types,rustcmemory consumption and compilation time grow approximately linearly with the number of generated types. The growth is large enough to make real-world scenarios hit practical memory limits.The issue appears to be primarily related to the number of generated trait implementations, as the
bitflags!macro generates implementations for several traits (such asAdd,Sub,BitOr, etc.) for the type.Reproducer
Cargo.toml
src/lib.rs
Note that the
create_bitflags_instance!macro is only used to simplify the example. Replacing it with manually written type definitions has only a minimal effect on resource consumption.Observed scaling
Memory usage and compile time both scale approximately linearly with the number of generated
bitflags!types.Toolchain
The measurements were collected using a custom debug-built toolchain (
dc375db7d8df0aa450e622c529147c95eee756f5). However, similar behavior is observed across multiple toolchain versions, including Rust 1.80 through the latest stable available at the time of writing (1.96.0 (30a34c682 2026-05-25)).Profiling information
Using the debug-built toolchain, the largest memory consumers observed in the
rustcprocess were:rustc_resolve::Module::for_each_child/Resolver::finalize_importsrustc_arena::DroplessArena::growrustc_middle::dep_graph::CurrentDepGraph::record_edgeindexmap::Core<rustc_span::SpanData, ()>::insert_fullReal-world impact
This issue was discovered while developing the Arm system register crate: arm-sysregs The crate generates types and accessors for Armv8-A system registers. Currently only about 25% of the registers are covered, yet builds are already approaching CI memory limits (~3 GB).
The current scaling is therefore problematic because:
rustcprocesses compete for memory simultaneously.Questions
bitflags!-generated code that contribute disproportionately to memory usage and should be avoided?rustcmemory consumption for workloads involving large numbers of types and trait implementations?Expected outcome
rustcmemory usage for this pattern could be reduced substantially, orAny suggestions for investigation or mitigation would be greatly appreciated.