Generic Const Args and You
Generic Const Args and You
通用常量参数(Generic Const Args)与你
Oct. 2, 2026 · BoxyUwU on behalf of The Const Generics Project Group 2026年10月2日 · BoxyUwU 代表常量泛型项目组
Back in June of 2024 at RustFest Zürich, the Const Generics project group first discussed a new design for supporting more complex uses of generic parameters in Const Generics. Since then, we’ve continued to refine the initial design and have implemented the new design as a family of features dubbed “Generic Const Arguments” (GCA for short). 早在2024年6月的苏黎世 RustFest 上,常量泛型(Const Generics)项目组首次讨论了一种新设计,旨在支持常量泛型中更复杂的泛型参数用法。自那时起,我们不断完善最初的设计,并将这一新设计实现为一组名为“通用常量参数”(Generic Const Arguments,简称 GCA)的特性。
These features are intended to replace the existing generic_const_exprs feature which has existed in some form or another since min_const_generics was stabilized back in 2021. Even though GCA obviates generic_const_exprs it was still incredibly valuable to have invested the time into it that we did as the design and implementation of GCA was informed quite significantly by generic_const_exprs.
这些特性旨在取代现有的 generic_const_exprs 特性,后者自 2021 年 min_const_generics 稳定以来就以各种形式存在。尽管 GCA 取代了 generic_const_exprs,但我们之前投入的时间依然非常有价值,因为 GCA 的设计和实现很大程度上借鉴了 generic_const_exprs 的经验。
Each feature in the GCA family introduces support for a specific set of expressions to be used in Const Generics with generic parameters. This post will go over all of the features part of the GCA family and explain their design and how to use them. GCA 系列中的每个特性都引入了对特定表达式集合的支持,使其能够与泛型参数一起用于常量泛型中。本文将介绍 GCA 系列的所有特性,并解释其设计理念及使用方法。
A huge thanks to @camelid for doing almost all of the initial implementation work for the GCA prototype. Without him GCA would have stayed just a vague concept rather than anything tangible. Additionally, a huge thanks to @khyperia who has done a significant amount of the implementation and design work required to go from the original GCA prototype to the fully featured family that it is now. Finally there have been a tonne of other people who have made contributions to getting GCA to where it is today. For a full list of everyone and all of their contributions, see the Full Const Generics project goal. 非常感谢 @camelid 完成了 GCA 原型几乎所有的初始实现工作。没有他,GCA 可能仍只是一个模糊的概念,而非切实可行的方案。此外,还要特别感谢 @khyperia,他完成了从最初的 GCA 原型到如今功能完备的特性系列所需的大量实现和设计工作。最后,还有许多人为 GCA 达到今天的成就做出了贡献。有关所有贡献者及其贡献的完整列表,请参阅“完整常量泛型项目目标”。
What is GCA
什么是 GCA
On stable, only generic parameters by themselves (e.g. { N }) or fully concrete constants (e.g. { 1 + 1 }) are supported by Const Generics. It’s not possible to have arrays like [u8; T::NUM_BYTES] or [u8; N + 1]. This limitation prevents a lot of useful abstractions and pushes users to rely on the typenum crate instead.
在稳定版中,常量泛型仅支持单独的泛型参数(例如 { N })或完全具体的常量(例如 { 1 + 1 })。目前无法使用诸如 [u8; T::NUM_BYTES] 或 [u8; N + 1] 这样的数组。这一限制阻碍了许多有用的抽象,并迫使用户转而依赖 typenum crate。
Generic Const Arguments is a family of features introducing support for more kinds of expressions involving generic parameters to Const Generics. For example, the gca_adts feature adds support for Struct Expressions involving generic parameters to Const Generics:
通用常量参数是一系列特性,旨在为常量泛型引入对更多涉及泛型参数的表达式的支持。例如,gca_adts 特性增加了对涉及泛型参数的结构体表达式的支持:
#![feature(adt_const_params, gca_adts)]
use core::gca;
/* some details omitted */
struct Bar<const N: Foo>;
type BarWrapper<const N: usize> = Bar<gca!(Foo { field: N })>;
In this example the gca!(Foo { field: N }) is the new functionality introduced by gca_adts. The adt_const_params feature is separate and instead allows defining the const N: Foo generic parameter. All GCA features require any newly supported expressions to be written inside of a gca! macro call. We are aware that this requirement poses significant ergonomic problems and are currently looking into ways to avoid this, though have not arrived at a good solution yet (more on this later).
在这个例子中,gca!(Foo { field: N }) 是由 gca_adts 引入的新功能。adt_const_params 是一个独立的特性,它允许定义 const N: Foo 泛型参数。所有 GCA 特性都要求任何新支持的表达式必须写在 gca! 宏调用内部。我们意识到这一要求带来了显著的人体工程学问题,目前正在寻找避免此限制的方法,尽管尚未找到完美的解决方案(稍后会详细说明)。
gca!
gca! 宏
Const Arguments have slightly different semantics than other const arguments. First, gca!(..) Const Arguments allow for uses of generic parameters within them, Const Arguments are otherwise usually not allowed to do so. In the above example the usage of the Const Parameter N in gca!(Foo { field: N }) is legal as it is within a gca!(..) expression, if we had written Bar<{ Foo { field: N } }> then the compiler would error.
常量参数的语义与其他常量参数略有不同。首先,gca!(..) 常量参数允许在其中使用泛型参数,而普通的常量参数通常不允许这样做。在上面的例子中,在 gca!(Foo { field: N }) 中使用常量参数 N 是合法的,因为它位于 gca!(..) 表达式内;如果我们写成 Bar<{ Foo { field: N } }>,编译器将会报错。
Secondly, gca!(..) Const Arguments support much fewer kinds of expressions inside them than normal Const Arguments do. For example at the time of writing gca! arguments do not support arithmetic or function calls. Writing gca!(1 + 1) or gca!(foo()) would result in an error, but just writing { 1 + 1 } or { foo() } would not. Using such unsupported expressions while also using generic parameters can be accomplished via the gca_const_items feature which we will talk more about later.
其次,gca!(..) 常量参数内部支持的表达式种类远少于普通常量参数。例如,在撰写本文时,gca! 参数不支持算术运算或函数调用。编写 gca!(1 + 1) 或 gca!(foo()) 会导致错误,但直接写 { 1 + 1 } 或 { foo() } 则不会。若要在使用泛型参数的同时使用这些不支持的表达式,可以通过稍后讨论的 gca_const_items 特性来实现。
ADT Generic Const Args
ADT 通用常量参数
Support for constructing arrays, tuples, and ADTs are all lumped into the gca_adts feature. We might split this into multiple features at some point but for now it’s just the one. Constructing enums and structs is supported regardless of the syntax they’re defined with (i.e. unit, tuple or struct syntax):
构建数组、元组和 ADT(代数数据类型)的支持都被归入 gca_adts 特性中。我们可能会在未来将其拆分为多个特性,但目前它们合并在一起。无论枚举和结构体以何种语法定义(即单元结构体、元组结构体或普通结构体语法),都支持对其进行构造:
#![feature(gca_adts, adt_const_params)]
use core::gca;
#[derive(ConstParamTy, Eq, PartialEq)]
struct TupleStruct(usize);
fn accepts<const N: TupleStruct>() {}
fn example<const N: usize>() {
accepts::<gca!(TupleStruct(N))>();
}
#![feature(gca_adts, adt_const_params)]
use core::gca;
#[derive(ConstParamTy, Eq, PartialEq)]
enum MyEnum { Record { x: usize }, }
fn accepts<const E: MyEnum>() {}
fn example<const N: usize>() {
accepts::<gca!(MyEnum::Record { x: N })>();
}
And lastly support for constructing arrays and tuples: 最后是构建数组和元组的支持:
#![feature(gca_adts, adt_const_params)]
use core::gca;
fn accepts_arrays<const N: [usize; 2]>() {}
fn example<const N1: usize>() {
accepts_arrays::<gca!([N1, 12])>();
}
#![feature(gca_adts, adt_const_params)]
use core::gca;
fn accepts_tuple<const N: (usize, usize)>() {}
fn example<const N1: usize>() {
accepts_tuple::<gca!((N1, 12))>();
}
We currently do not support array repeat expressions but do intend to support this at some point: 我们目前不支持数组重复表达式,但打算在未来某个时间点提供支持:
#![feature(gca_adts, adt_const_params)]
use core::gca;
fn accepts_arrays<const N: [usize; 2]>() {}
fn example<const N1: usize>() {
// currently disallowed :(
accepts_arrays::<gca!([N1; 2])>();
}
Const Item Generic Const Args
常量项通用常量参数
Support for using const items in the type system is part of the gca_const_items feature. This feature also requires the -Znext-solver unstable flag to be enabled. By allowing arbitrary const items to be used in the type system, we are allowing arbitrary expressions to indirectly be used in the type system. For example gca!(N + 1) cannot be used in the type system, but a const item defined as const FOO: usize = N + 1; can be. Using an associated constant as a const argument looks like the following:
在类型系统中使用常量项的支持是 gca_const_items 特性的一部分。该特性还需要启用 -Znext-solver 不稳定标志。通过允许在类型系统中使用任意常量项,我们间接地允许了在类型系统中使用任意表达式。例如,gca!(N + 1) 不能直接用于类型系统,但定义为 const FOO: usize = N + 1; 的常量项则可以。使用关联常量作为常量参数的示例如下:
#![feature(gca_const_items)]
use core::gca;
trait Trait { const ASSOC: usize }
fn example<T: Trait>() -> [u8; gca!(T::ASSOC)] {
[0x1; _]
}