为什么生成器函数需要 sized trait 来生成 Rc<T>?
Why sized trait is required for a builder function to generate Rc<T>?
这段代码工作正常(playground):
use std::rc::Rc;
trait Foo {
fn foo(&self);
}
struct Bar<T> {
v: Rc<T>,
}
impl<T> Bar<T> where
T: Foo {
fn new(rhs: Rc<T>) -> Bar<T> {
Bar{v: rhs}
}
}
struct Zzz {
}
impl Zzz {
fn new() -> Zzz {
Zzz{}
}
}
impl Foo for Zzz {
fn foo(&self) {
println!("Zzz foo");
}
}
fn make_foo() -> Rc<Foo> {
Rc::new(Zzz{})
}
fn main() {
let a = Bar::new(Rc::new(Zzz::new()));
a.v.as_ref().foo()
}
但是如果我制作一个包装器来生成如下所示的 Rc,编译器会抱怨缺少大小特征 (playground)
fn make_foo() -> Rc<dyn Foo> {
Rc::new(Zzz::new())
}
fn main() {
let a = Bar::new(make_foo());
a.v.as_ref().foo()
}
在这两种情况下,Bar::new 接收到相同类型 Rc 的参数,为什么 rust 编译器的反应不同?
默认情况下,所有类型变量都假定为Sized
。例如,在 Bar
结构体的定义中,有一个隐含的 Sized
约束,像这样:
struct Bar<T: Sized> {
v: Rc<T>,
}
对象 dyn Foo
不能 是 Sized
因为 Foo
的每个可能实现可能有不同的大小,所以没有可以选择的一种尺寸。但是您正在尝试实例化 Bar<dyn Foo>
.
修复方法是选择退出 T
的 Sized
特征:
struct Bar<T: ?Sized> {
v: Rc<T>,
}
并且在实现的上下文中:
impl<T: ?Sized> Bar<T>
where
T: Foo
?Sized
其实不是约束,而是放宽了已有的Sized
约束,所以不需要了。
选择退出 Sized
的结果是 impl
块中 Bar
的方法中的 none 可以使用 T
,除了参考。
这段代码工作正常(playground):
use std::rc::Rc;
trait Foo {
fn foo(&self);
}
struct Bar<T> {
v: Rc<T>,
}
impl<T> Bar<T> where
T: Foo {
fn new(rhs: Rc<T>) -> Bar<T> {
Bar{v: rhs}
}
}
struct Zzz {
}
impl Zzz {
fn new() -> Zzz {
Zzz{}
}
}
impl Foo for Zzz {
fn foo(&self) {
println!("Zzz foo");
}
}
fn make_foo() -> Rc<Foo> {
Rc::new(Zzz{})
}
fn main() {
let a = Bar::new(Rc::new(Zzz::new()));
a.v.as_ref().foo()
}
但是如果我制作一个包装器来生成如下所示的 Rc,编译器会抱怨缺少大小特征 (playground)
fn make_foo() -> Rc<dyn Foo> {
Rc::new(Zzz::new())
}
fn main() {
let a = Bar::new(make_foo());
a.v.as_ref().foo()
}
在这两种情况下,Bar::new 接收到相同类型 Rc 的参数,为什么 rust 编译器的反应不同?
默认情况下,所有类型变量都假定为Sized
。例如,在 Bar
结构体的定义中,有一个隐含的 Sized
约束,像这样:
struct Bar<T: Sized> {
v: Rc<T>,
}
对象 dyn Foo
不能 是 Sized
因为 Foo
的每个可能实现可能有不同的大小,所以没有可以选择的一种尺寸。但是您正在尝试实例化 Bar<dyn Foo>
.
修复方法是选择退出 T
的 Sized
特征:
struct Bar<T: ?Sized> {
v: Rc<T>,
}
并且在实现的上下文中:
impl<T: ?Sized> Bar<T>
where
T: Foo
?Sized
其实不是约束,而是放宽了已有的Sized
约束,所以不需要了。
选择退出 Sized
的结果是 impl
块中 Bar
的方法中的 none 可以使用 T
,除了参考。