首页 > 解决方案 > 类型绑定中的特征“未实现”?

问题描述

考虑以下代码,它使用 trait 使数组的长度在类型中固定。

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

标签: rusttraits

解决方案


首先,您需要使用该const_generics功能才能做到这一点。但是,这还不够,因为您还需要使用该const_evaluatable_checked功能

当您添加该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 帖子中阅读更多相关信息。

#![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>,
}

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


推荐阅读