Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Constify all the things

Metadata
Short titleConstify all the things
What and whyConst generics accept structs and enums; compile-time reflection means serialize(&my_struct) works without derives
Point of contactOliver Scherer
Task ownersBoxy, Deadbeef, Oliver Scherer

Summary

Richer const generics and compile-time reflection that works without derives.

Motivation

The status quo

Rust’s compile-time capabilities are powerful but incomplete. const fn enables compile-time evaluation, but users repeatedly hit limitations when trying to use it for real work:

  • Const generics only support primitive types. You can write Array<T, 4> but not Array<T, Dimensions { width: 4, height: 4 }>. Using associated constants as const parameters (Buffer<T, T::SIZE>) also doesn’t work. These limitations force workarounds or abandoning const generics entirely.

  • Reflection requires derives on every type. Libraries for serialization, logging, or reflection need users to add derives for each type they want to work with. This creates ecosystem friction: crate authors must choose which libraries to support, users must add boilerplate for each library, and new libraries can’t reach existing types.

  • Proc macros are the only option for code generation. When you need compile-time code generation, proc macros work but are difficult to debug, can’t access type information, and add compile-time overhead.

Extending const generics and adding compile-time reflection would address all three limitations, letting users write normal Rust code that inspects types and runs at compile time. The practical impact spans serialization (serialize(&my_struct) without derives), game engines (inspect any type’s structure directly, making #[derive(Component)] optional), dimension-checked numerics (physical dimensions as const generic structs), and protocol buffer generation (work with Rust structs at compile time without external code generators).

Design axioms

  • Extend the const boundary, don’t reinvent. Build on const fn and const generics rather than creating parallel evaluation systems. Users should write normal Rust code that happens to run at compile time.
  • Remove boilerplate, don’t shift it. Reflection should eliminate the need for derives on every type, not replace one kind of boilerplate with another.
  • Incremental delivery. Const generics and reflection are independently valuable. Ship each as it’s ready rather than waiting for the full vision.

What we are shooting for

Const generics that accept structs and enums (stable by end of 2026), and an experimental comptime reflection system validated against libraries like bevy_reflect and facet, with an RFC merged defining the stabilization path.

How we get there

GoalTimespanWhat and why
ADT const params2026Support structs, tuples, arrays in const generics.
Min generic const arguments2026Support associated constants and generic parameters embedded in other expressions.
Stabilize const traits MVP2026Finalize the RFC, complete the compiler implementation, and stabilize so const fn can call trait methods.
Architectural groundwork for expansion-time evaluation2026Lay the architectural groundwork for functions that can be evaluated during macro expansion.
Explore design space for comptime const fn2026-2028Implement and validate #[compile_time_only] attribute for const fn that enables type reflection without runtime overhead.

Const generics extends what values can be used as compile-time parameters — foundational for many advanced patterns. Reflection and comptime provides the ability to inspect types at compile time, enabling libraries that work without derives. Together they transform what’s possible at compile time: const generics let you parameterize by complex values, reflection lets you adapt to any type’s structure.

Frequently asked questions

How does reflection differ from proc macros?

Proc macros operate on syntax (tokens) before type checking. Reflection operates on types during const evaluation. Reflection can see actual type information (field types, sizes, layouts), is debuggable with standard tools, and doesn’t require proc-macro compilation overhead.

Will reflection make derives obsolete?

Not obsolete, but often optional. Derives generate specialized code and can be more efficient. Reflection offers less boilerplate with potentially some runtime cost. Many libraries will likely offer both modes.