【发布时间】:2019-08-07 15:47:14
【问题描述】:
在下面的代码中,不可能从实现相同特征的动态大小类型的引用中获得对特征对象的引用。为什么会这样? &dyn Trait 和 &(?Sized + Trait) 如果我可以同时使用两者来调用 trait 方法,究竟有什么区别?
实现FooTraitContainerTrait 的类型可能例如有type Contained = dyn FooTrait 或type Contained = T 其中T 是实现FooTrait 的具体类型。在这两种情况下,获取&dyn FooTrait 都很简单。我想不出另一种这种方法行不通的情况。为什么在FooTraitContainerTrait 的一般情况下这不可能?
trait FooTrait {
fn foo(&self) -> f64;
}
///
trait FooTraitContainerTrait {
type Contained: ?Sized + FooTrait;
fn get_ref(&self) -> &Self::Contained;
}
///
fn foo_dyn(dyn_some_foo: &dyn FooTrait) -> f64 {
dyn_some_foo.foo()
}
fn foo_generic<T: ?Sized + FooTrait>(some_foo: &T) -> f64 {
some_foo.foo()
}
///
fn foo_on_container<C: FooTraitContainerTrait>(containing_a_foo: &C) -> f64 {
let some_foo = containing_a_foo.get_ref();
// Following line doesn't work:
//foo_dyn(some_foo)
// Following line works:
//some_foo.foo()
// As does this:
foo_generic(some_foo)
}
取消注释foo_dyn(some_foo) 行会导致编译器错误
error[E0277]: the size for values of type `<C as FooTraitContainerTrait>::Contained` cannot be known at compilation time
--> src/main.rs:27:22
|
27 | foo_dyn(contained)
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `<C as FooTraitContainerTrait>::Contained`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= help: consider adding a `where <C as FooTraitContainerTrait>::Contained: std::marker::Sized` bound
= note: required for the cast to the object type `dyn FooTrait`
【问题讨论】:
-
&dyn Trait是一个带有额外动态调度信息的胖指针。您的some_foo只是一个常规参考(指针)。类型的大小对此有所说明:Playground -
我猜你永远不会做这种类型的演员:see this basic example。只有绑定了
Sized(删除+?Sized),转换才能成功。 -
因为从技术上讲,目前我认为
some_foo有足够的信息来从中创建一个特征对象。如果它没有大小,则它是一个胖指针,并且已经包含所需的 vtable 指针。如果调整了大小,演员表可以计算 vtable 指针,因为它现在是单态化期间的具体类型,对吧? -
现在不能写答案,但考虑
impl FooTrait for [i32] {...}。您仍然无法将&[i32]转换为&dyn FooTrait,因为&[i32]已经是一个胖指针;没有地方可以放置 vtable。 (为此,您需要“肥胖指针”。) -
@trentcl 有趣。所以这是不支持的,否则当你对这些动态大小的类型进行“更深的嵌套”时,你可能会得到任意大的指针?
标签: generics rust polymorphism trait-objects