为什么 Rust 在实现具有关联类型的关联 const 时希望 Self 被调整大小?



请考虑以下代码:

pub trait Trait {
type Type;
const CONST: Self::Type;
}
impl<T> Trait for T {
type Type = u8;
const CONST: u8 = 42;
}

我对 Rust 的(不正确的?(理解是这段代码应该工作,并且所有Sized类型现在都应该实现Trait并具有关联的类型 (Type = u8( 和 const (CONST = 42(。未调整大小的类型不应实现此特征,因为impl<T>隐式假定TSized

但是,当我尝试编译代码时,我收到错误消息:

error[E0277]: the size for value values of type `T` cannot be known at compilation time
--> src/main.rs:8:3
|
8 |   const CONST: u8 = 42;
|   ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `T`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: consider adding a `where T: std::marker::Sized` bound
= note: required because of the requirements on the impl of `Trait` for `T`

我的问题:

  • 为什么 Rust 认为T不在这里Sized?明确说明T: Sized无济于事。
  • 让我们假装T不是Sized.为什么 Rust 关心T在这里的大小是否合适?据我所知,没有什么取决于它(关联的类型和常量与T无关(。将代码更改为T: ?Sized有效,因此显然T未调整大小实际上没有问题。

根据这个 GitHub 问题,这似乎是一个已知的错误,至少从 Rust 1.23 开始就存在了(我怀疑更长(。

目前尚不清楚导致问题的原因以及何时/是否会修复。只有一个相当模糊的假设:

我不熟悉编译器内部结构,但我的假设是,依赖于类型参数的关联类型和常量在常量表达式计算器中未正确计算。在这种情况下,它是关联的类型,不能很好地减少:const VAL: Self::T = 5;迫使 Rust 在编译时做一些花哨的计算,以便进行类型检查,但此类计算的代码中存在错误。

有几种方法可以解决此问题:

  1. 在特征中指定具体类型:

    pub trait Trait {
    // type Type;  // no longer used
    const CONST: u8;
    }
    
  2. 选择退出TSized

    impl<T: ?Sized> Trait for T {
    type Type = u8;
    const CONST: u8 = 42;
    }
    
  3. 使用函数而不是常量(功劳归@PeterHall(:

    pub trait Trait {
    type Type;
    fn const_val() -> Self::Type;
    }
    impl<T> Trait for T {
    type Type = u8;
    fn const_val() -> Self::Type { 42 }
    }
    

最新更新