类型绑定 "not implemented" 中的特征?

Trait in type bound "not implemented"?

考虑下面的代码,它使用一个特征来使数组的长度固定在类型中。

use std::marker::PhantomData;

pub trait MyLen {
    const LEN: usize;
}

pub struct Data<L: MyLen> {
    bytes: [u8; <L as MyLen>::LEN],
    _phantom: PhantomData<L>,
}

我可以发誓几天前我看到了类似的代码,但现在我看到了

   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `L: MyLen` is not satisfied
 --> src/lib.rs:8:17
  |
4 |     const LEN: usize;
  |     ----------------- required by `MyLen::LEN`
...
8 |     bytes: [u8; <L as MyLen>::LEN],
  |                 ^^^^^^^^^^^^^^^^^ the trait `MyLen` is not implemented for `L`
  |
help: consider further restricting this bound
  |
7 | pub struct Data<L: MyLen + MyLen> {
  |                          ^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground`

这个错误消息对我来说没有意义,尤其是建议。知道我做错了什么吗?

游乐场:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=49c9a11106a46125eaa9612560966bac

首先,您需要使用 const_generics feature to be able to do that. However, that's not entirely enough, as you'll also need to use the const_evaluatable_checked feature

当您添加 const_generics 功能时,问题变得更加明显,并出现更具描述性的编译器错误。

error: constant expression depends on a generic parameter
  --> src\main.rs:37:12
   |
37 |     bytes: [u8; <L as MyLen>::LEN],
   |            ^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: this may fail depending on what value the parameter takes

error: constant expression depends on a generic parameter
  --> src\main.rs:34:30
   |
34 |     [u8; <L as MyLen>::LEN]: Sized,
   |                              ^^^^^
   |
   = note: this may fail depending on what value the parameter takes

缺少的部分是 where [u8; <L as MyLen>::LEN]: (或 where [u8; <L as MyLen>::LEN]: Sized),它需要 const_evaluatable_checked 功能。需要 where 子句,以确保 LEN 不会计算为溢出或以其他方式使该数组无效的内容。

您可以在 Rust 编译器团队的 HackMD post 上阅读更多相关信息。

#![feature(const_generics)]
#![feature(const_evaluatable_checked)]
#![allow(incomplete_features)]

use std::marker::PhantomData;

pub trait MyLen {
    const LEN: usize;
}

pub struct Data<L: MyLen>
where
    [u8; <L as MyLen>::LEN]: ,
    // or
    // [u8; <L as MyLen>::LEN]: Sized,
{
    bytes: [u8; <L as MyLen>::LEN],
    _phantom: PhantomData<L>,
}

这当然需要夜间编译器来构建。