【发布时间】:2018-05-23 08:18:04
【问题描述】:
我定义了一个 trait Foo,为 [u32] 实现了这个 trait,并写了一个函数 bar 以这个 trait 作为参数 (playground):
trait Foo {
fn foo(&self) -> u32;
}
impl Foo for [u32] {
fn foo(&self) -> u32 {
self[0]
}
}
fn bar<T>(f: &T) -> u32
where
T: Foo,
{
f.foo() + 1
}
fn main() {
let f: &[u32] = &[42];
bar(f);
}
这不会编译,因为bar 隐含地期望它的参数是Sized:
error[E0277]: the trait bound `[u32]: std::marker::Sized` is not satisfied
--> src/main.rs:20:5
|
20 | bar(f);
| ^^^ `[u32]` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u32]`
note: required by `bar`
--> src/main.rs:11:1
|
11 | / fn bar<T>(f: &T) -> u32
12 | | where
13 | | T: Foo,
14 | | {
15 | | f.foo() + 1
16 | | }
| |_^
我可以用 T: Foo + ?Sized 修复它,但是我必须为 每个 函数执行此操作,期待 Foo,这很痛苦...
我是否可以一劳永逸地声明 Foo 的实现不应该是 Sized?我在第 1 行尝试了trait Foo: ?Sized,但编译器抱怨它。
这个问题和Trait implementing Sized不一样。在那个问题中,Foo 参数被移动了,所以编译器想在编译时知道它的大小是很正常的。在我的例子中,参数是一个引用,所以它不需要 来调整大小——但编译器仍然隐含地假设它是,除非明确告知(使用+ ?Sized)。我想改变的是这个隐含的假设,对于这个特殊的特征。
【问题讨论】: