我在 Rust 代码中经常看到这种情况。以下是标准库中的一些示例:
impl<T> const Default for Option<T> {...}
impl const From<char> for u64 {...}
什么是
impl const
?
如果运行代码:
trait Example {}
impl const Example for u8 {}
您会收到一条错误消息,为您指明正确的方向:
error[E0658]: const trait impls are experimental
--> src/lib.rs:3:6
|
3 | impl const Example for u8 {}
| ^^^^^
|
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
问题 67792 是 RFC 2632 的跟踪问题 — 在 const fns 的泛型参数上调用方法。
这是一种不稳定语法,允许定义可在
const
上下文中使用的特征。它与同样 不稳定 ~const
语法配对,可用于特征边界:
// 1.59.0-nightly (2021-12-20 23f69235ad2eb9b44ac1)
#![feature(const_fn_trait_bound)]
#![feature(const_trait_impl)]
trait Example {
fn usage(&self) -> Self;
}
impl const Example for u8 {
fn usage(&self) -> Self {
42
}
}
const fn demo<T: ~const Example>(v: &T) -> T {
v.usage()
}
const VALUE: u8 = demo(&1);
fn main() {
dbg!(VALUE);
}
我接受了 Shepmaster 的回答,但随着这个问题越来越受欢迎,我认为对这些
const
规则添加更多见解可能也很有用。我将使用 Shepmaster 提供的相同示例。自他发布以来,一些事情发生了变化,所以我用评论更新了示例。
// 1.68.0-nightly (2022-12-11 bdb07a8ec8e77aa10fb8)
//#![feature(const_fn_trait_bound)] <-- Not needed since Rust 1.61
#![feature(const_trait_impl)] // const trait impls are (still) experimental/unstable
#[const_trait] // This is needed now
trait Example {
fn usage(&self) -> Self;
}
impl const Example for u8 {
fn usage(&self) -> Self {
42
}
}
const fn demo<T: ~const Example>(v: &T) -> T {
v.usage()
}
const VALUE: u8 = demo(&1);
fn main() {
dbg!(VALUE);
}
假设我们一开始除了
const
之外没有其他 const VALUE
。如果 fn demo
不是 const fn demo
,我们会得到这个错误:
error[E0015]: cannot call non-const fn `demo::<u8>` in constants
到目前为止,这与特质本身无关。但如果我们只是将
fn demo
更改为 const fn demo
,编译器会抱怨:
error[E0277]: the trait bound `T: ~const Example` is not satisfied
note: the trait `Example` is implemented for `T`, but that implementation is not `const`
和
error[E0015]: cannot call non-const fn `<T as Example>::usage` in constant functions
note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
仅将特征绑定
~const
添加到 Example
是行不通的:
error: ~const can only be applied to `#[const_trait]` traits
我们需要将
#[const_trait]
添加到 trait Example
并将 impl Example
更改为 impl const Example
。
#[const_trait]
最近添加,现在 Trait
需要 impl const Trait
。
缺少
#[const_trait]
时编译器提供的更多信息:
error: const `impl` for trait `Example` which is not marked with `#[const_trait]`
|
7 | trait Example {
| - help: mark `Example` as const: `#[const_trait]`
...
11 | impl const Example for u8 {
| ^^^^^^^
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
= note: adding a non-const method body in the future would be a breaking change
正如here所解释的,当我们有
#[const_trait]
时,在 trait Example
上要求 impl const Example
背后的理由是,防止向 Example
添加新的默认方法成为重大更改(因为它可能是非常量 fn)。