考虑以下代码:
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({ {1}})。未定大小的类型不应实现此特征,因为CONST = 42
隐式假定impl<T>
为T
。
但是,当我尝试compile the code时,我收到错误消息:
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`
不是T
? Explicitly stating T: Sized
doesn't help。Sized
不是T
。 Rust为何在这里关心Sized
的大小?据我所知,没有什么依赖它(关联的类型和const与T
无关)。将代码更改为T
是可行的,因此很明显T: ?Sized
的大小实际上并没有问题。答案 0 :(得分:2)
根据this GitHub issue,这似乎是至少自Rust 1.23(我怀疑更长)以来一直存在的已知错误。
目前尚不清楚是什么原因导致了该问题以及何时/是否可以解决。只有一个相当模糊的假设:
我不熟悉编译器的内部原理,但我的假设是,在常量表达式评估器中无法正确评估取决于类型参数的关联类型和常量。在这种情况下,它的关联类型不能很好地降低:
const VAL: Self::T = 5;
强制Rust在编译时进行一些奇特的计算类型以进行类型检查,但是这种计算的代码中有一个错误。
有几种方法可以解决此问题:
在特征中指定具体类型:
pub trait Trait {
// type Type; // no longer used
const CONST: u8;
}
从T
中退出Sized
:
impl<T: ?Sized> Trait for T {
type Type = u8;
const CONST: u8 = 42;
}
使用函数而不是常量(贷记到@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 }
}