Rust 中的“impl const”是什么?

at5*_*321 19 syntax constants traits rust

我在 Rust 代码中经常看到这种情况。以下是标准库中的一些示例:

impl<T> const Default for Option<T> {...}

impl const From<char> for u64 {...}
Run Code Online (Sandbox Code Playgroud)

什么是impl const

She*_*ter 22

如果运行代码:

\n
trait Example {}\nimpl const Example for u8 {}\n
Run Code Online (Sandbox Code Playgroud)\n

您会收到一条错误消息,为您指明正确的方向:

\n
error[E0658]: const trait impls are experimental\n --> src/lib.rs:3:6\n  |\n3 | impl const Example for u8 {}\n  |      ^^^^^\n  |\n  = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information\n  = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable\n
Run Code Online (Sandbox Code Playgroud)\n

问题 67792是RFC 2632 \xe2\x80\x94\xc2\xa0在 const fns 的泛型参数上调用方法的跟踪问题。

\n

这是一种不稳定的语法,允许定义可在const上下文中使用的特征。它与可在特征边界中使用的同样不稳定的语法配对: ~const

\n
// 1.59.0-nightly (2021-12-20 23f69235ad2eb9b44ac1)\n#![feature(const_fn_trait_bound)]\n#![feature(const_trait_impl)]\n\ntrait Example {\n    fn usage(&self) -> Self;\n}\n\nimpl const Example for u8 {\n    fn usage(&self) -> Self {\n        42\n    }\n}\n\nconst fn demo<T: ~const Example>(v: &T) -> T {\n    v.usage()\n}\n\nconst VALUE: u8 = demo(&1);\n\nfn main() {\n    dbg!(VALUE);\n}\n
Run Code Online (Sandbox Code Playgroud)\n


at5*_*321 5

我接受了 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);
}
Run Code Online (Sandbox Code Playgroud)

假设我们一开始const除了 之外没有其他 s const VALUE。如果fn demo不是const fn demo,我们会得到这个错误:

error[E0015]: cannot call non-const fn `demo::<u8>` in constants
Run Code Online (Sandbox Code Playgroud)

到目前为止,这与特征本身无关。但如果我们只是更改fn democonst 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`
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

~const仅添加绑定到的特征Example是不行的:

error: ~const can only be applied to `#[const_trait]` traits
Run Code Online (Sandbox Code Playgroud)

我们需要添加#[const_trait]trait Example更改impl Exampleimpl 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
Run Code Online (Sandbox Code Playgroud)

正如这里所解释的,要求#[const_trait]on trait Examplewhen 我们拥有的理由impl const Example是,防止添加新的默认方法Example成为重大更改(因为它可能是非常量 fn)。