在 1.51 版本稳定了 const 泛型的 MVP(最小可行产品)之后,const 泛型项目组持续在 const 泛型上工作。这项工作的很大一部分被 const_generics
和 const_evaluatable_checked
特性门所限制。随着时间的推移,const_generics
特性本身变得相当无用,而 const_evaluatable_checked
的名称并不能真正体现该特性旨在做什么。
为了改进这一点,我们最近移除了 const_generics
、lazy_normalization_consts
和 const_evaluatable_checked
特性。它们已被 feature(adt_const_params)
和 feature(generic_const_exprs)
所取代。
由于 const 泛型方面有很多进展,这里快速概述一下新的和已有的特性,以及它们需要稳定化还需要做多少工作:
feature(adt_const_params)
在稳定版本中,只允许整数、char
和 bool
作为 const 参数的类型。这个特性允许使用额外的类型,例如 &'static str
和用户自定义类型。
注意,即使有了这个特性,泛型 const 参数类型,例如 struct Foo<T, const N: T> { ... }
,仍然是被禁止的。虽然允许这类特性是期望的,但这增加了超出我们当前能力的额外复杂性。
稳定化仍有两个主要障碍:
第一个障碍是 向 valtrees 的过渡。Valtrees 是一种将值表示为带有整数节点的树的结构,简化了我们与更复杂类型交互的方式。
此外,我们必须确定我们究竟想允许哪些类型作为 const 参数类型。这与关于 “结构化匹配” 的讨论相关,该讨论仍在进行中。
虽然上述问题肯定不是微不足道的,但这个特性完全有可能在几个月内准备好进行稳定化。
feature(generic_const_exprs)
在没有任何不稳定特性时,const 参数必须是完全具体的表达式或其本身是一个泛型参数,因此像 N + 1
这样的常量是被禁止的。有了这个特性,使用泛型参数的表达式成为可能。
; / 8]: Sized,
我们目前要求用户添加界限(bounds),断言泛型常量能够成功求值。对于项的 API 中可见的所有常量,这些界限会被隐式添加。
如果类型为 Foo
的常量表达式 expr
在其他情况下不会在 where
子句或函数签名中使用,我们会在项的 where
子句中添加一个提及 expr
的,否则无关紧要的界限。为此,可以定义一个 struct Evaluatable<const N: Foo>;
并使用 Evaluatable<{ expr }>:
作为界限。如果 expr
的类型是 usize
,我们倾向于使用 [u8; expr]:
或 [u8; expr]: Sized
。虽然我们未来极有可能为这些界限添加专门的语法,但我们正在等待,直到这个特性的其余部分更加成熟。
这个特性距离稳定还很远,并且有一些 重大的未解决问题。特别是对于 where
界限内的常量,有很多细微的 bug 和向后不兼容问题需要解决,然后我们才能考虑如何稳定化它。
feature(const_generics_defaults)
类似于类型参数的默认值,这个特性增加了为 const 参数声明默认值的能力。
为了允许类型参数默认值与 const 参数在同一个列表中,我们还打算移除对类型参数和 const 参数的顺序限制,允许 struct Foo<const N: usize, T = [u32; N]> { ... }
。
这个特性基本上已经准备好进行稳定化,目前正被阻碍在找出稳定化报告中任何潜在的边缘情况。
feature(generic_arg_infer)
虽然在函数体内部已经可以使用通配符 _
来表示类型参数,但 const 参数却不能。这个特性为常量增加了这个能力。
where
U: ,
这个特性尚未准备好进行稳定化,尽管目前没有已知的重大阻碍。然而,为了有信心地稳定化它,我们可能需要进行一些大规模的重构,因为目前的设置在某些方面感觉相当脆弱。