请考虑以下代码:
pub trait Trait {
type Type;
const CONST: Self::Type;
}
impl<T> Trait for T {
type Type = u8;
const CONST: u8 = 42;
}
Run Code Online (Sandbox Code Playgroud)
我(不正确?)对Rust的理解是这个代码应该工作,所有Sized类型现在应该实现Trait并且具有关联的type(Type = u8)和const(CONST = 42).因为未施胶的类型不应该实行这种特质impl<T>所隐含的假设T是Sized.
但是,当我尝试编译代码时,我收到错误消息:
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`
Run Code Online (Sandbox Code Playgroud)
我的问题:
T不在Sized这里?明确陈述T: Sized没有帮助.T不是Sized.Rust为什么要关注T尺寸与否?就我所知,没有任何东西取决于它(相关的类型和const与之无关T).将代码更改为T: ?Sized有效,因此显然T未实现的实际上并不存在问题.根据这个 GitHub 问题,这似乎是一个已知的错误,至少自 Rust 1.23 以来就已经存在(我怀疑更长)。
目前尚不清楚问题的原因是什么以及何时/是否会得到解决。只有一个相当模糊的假设:
我不熟悉编译器的内部结构,但我的假设是,依赖于类型参数的关联类型和常量在常量表达式求值器中未正确求值。在这种情况下,它的关联类型不能很好地减少:
const VAL: Self::T = 5;强制 Rust 在编译时执行一些奇特类型的计算以进行类型检查,但此类计算的代码中存在错误。
有几种方法可以解决该问题:
在特征中指定具体类型:
pub trait Trait {
// type Type; // no longer used
const CONST: u8;
}
Run Code Online (Sandbox Code Playgroud)选择T退出Sized:
impl<T: ?Sized> Trait for T {
type Type = u8;
const CONST: u8 = 42;
}
Run Code Online (Sandbox Code Playgroud)使用函数而不是常量(归功于@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 }
}
Run Code Online (Sandbox Code Playgroud)