概览: if
和 match
现在可以在最新的 nightly 版本中的常量中使用。
因此,你现在可以编写如下代码,并在编译时执行:
static PLATFORM: &str = if cfg! else if cfg! else ;
const _: = assert!;
if
和 match
也可以在 const fn
的函数体中使用
const
这里到底发生了什么?
以下表达式,
match
if
和if let
&&
和||
现在可以出现在以下任何上下文中,
const fn
函数体const
和 associatedconst
初始化表达式static
和static mut
初始化表达式- 数组初始化表达式
- const 泛型(实验性)
如果你的 crate 启用了 #![feature(const_if_match)]
。
你可能已经注意到,短路逻辑运算符 &&
和 ||
在 const
或 static
中已经是合法的了。这是通过将它们翻译成非短路等价形式 &
和 |
来实现的。启用该 feature gate 将关闭这个 hack,并使 &&
和 ||
按你预期的方式工作。
这些变化的一个副作用是,如果同时启用 #![feature(const_panic)]
,则 assert
和 debug_assert
宏可以在 const 上下文中使用。然而,其他 assert 宏(例如 assert_eq
、debug_assert_ne
)仍然被禁止,因为它们需要对其参数调用 Debug::fmt
。
循环构造 while
、for
和 loop
也被禁止,并将通过独立的 feature gate 启用。正如你在上面看到的,循环可以作为临时措施通过递归来模拟。然而,非递归版本通常会更有效率,因为 Rust(据我所知)不做尾调用优化。
最后,?
运算符在 const 上下文中仍然被禁止,因为它解糖后包含对 From::from
的调用。const
trait 方法的设计仍在讨论中,而 ?
和解糖后调用 IntoIterator::into_iter
的 for
,直到最终决定做出后才能使用。
下一步是什么?
这一改变将允许标准库中的大量函数变为 const
。你可以帮助完成这个过程!这里有一份数字函数列表,可以轻松地进行 const 化。转换为 const fn
需要两个步骤。首先,在函数定义中添加 const
和 #[rustc_const_unstable]
属性。这允许 nightly 用户在 const 上下文中调用它。然后,经过一段实验期后,移除该属性并稳定该函数的 const 属性。请参阅#61635 了解第一步的示例,参阅#64028 了解第二步的示例。
就我个人而言,我期待这个 feature 已经很久了,迫不及待地想开始试玩它。如果你也有同感,我将非常感谢你测试这个 feature 的极限!试着将 Cell
和带有 Drop
实现的类型潜入不应该出现的地方,用实现糟糕的递归函数(参见上面的 gcd
)撑爆栈,如果出现严重问题,请告诉我们。
为什么花了这么长时间?
Miri 引擎是 Rust 内部用于编译时函数求值的工具,它已经具备这个能力一段时间了。然而,Rust 需要静态地保证 const
中变量的某些属性,例如它们是否允许内部可变性或是否具有需要调用的 Drop
实现。例如,我们必须拒绝以下代码,因为它会导致 const
在运行时可变!
const CELL: & Cell = & new; // Not allowed...
然而,有时 const
包含对可能具有内部可变性的*类型*的引用是可以的,只要我们能证明该类型的实际*值*不具有。这对于带有“单元变体”(例如 Option::None
)的 enum
尤其有用。
const NO_CELL: = None; // OK
关于 const 上下文中 Drop
的规则 和 内部可变性的规则 的更详细(但非规范性)的处理可以在 const-eval
仓库中找到。
当涉及复杂的控制流(如循环和条件语句)时,保证变量值的属性并非易事。实现此 feature 需要扩展 Rust 中现有的数据流框架,以便我们能够正确跟踪控制流图中的每个局部变量的值。目前,分析非常保守,尤其是在值移进和移出复合数据类型时。例如,即使启用了 feature gate,以下代码也不会编译:
const
尽管 Vec::new
创建的 Vec
在 const fn
内部永远不会实际被 drop,但我们没有检测到 tuple
的所有字段都已移出,因此保守地假设 tuple
的 drop 实现将会运行。虽然这个特定情况很简单,但还有其他更复杂的情况需要更全面的解决方案。关于我们需要在此处有多精确是一个悬而未决的问题,因为更高的精度意味着更长的编译时间,即使对于不需要更多表达能力的用户也是如此。