默认的通用实现中可能存在错误?
Possible bug in generic implementation of Default?
给定以下结构 Foo<T>
派生 Default
:
#[derive(Default)]
struct Foo<T> {
bar: Option<T>,
}
为什么编译
fn create<T>() -> Foo<T> {
Foo {
bar: Option::default(),
}
}
但这不是吗?
fn create_alt<T>() -> Foo<T> {
Foo::default()
}
在我看来,它们都在做完全相同的事情——如果 T
实现了 Default
(这是编译器希望我指定的),那应该无关紧要,因为 Option<T>
实现 Default
。
Here 是 Rust 游乐场的 link 这个例子。
这是一个已知问题,很难修复。 Issue #26925
简而言之,#[derive]
使用了不正确的边界:它假设为了 Foo<T>
实现 Default
,T
必须是 Default
,当实际上 Option<T>: Default
就足够了。
修复它的问题是可能有私有类型的结构成员,并且在具有私有成员的 public 泛型结构上使用 #[derive]
可能会部分公开该私有接口。例如,
trait MyTrait {}
struct MyType<T> {}
impl<T> Default for MyType<T> where T: MyTrait {}
#[derive(Default)]
pub struct PubType<T> {
member: MyType<T>,
}
如果 #[derive(Default)]
做了正确的事情,你实际上有这个 impl
块用于公开私有特征的 public 类型:
impl Default for PubType<T>
where T: MyTrait
{ ... }
现在解决这个问题的最好方法可能是避免在这种情况下使用 #[derive]
并自己编写 impl
。
给定以下结构 Foo<T>
派生 Default
:
#[derive(Default)]
struct Foo<T> {
bar: Option<T>,
}
为什么编译
fn create<T>() -> Foo<T> {
Foo {
bar: Option::default(),
}
}
但这不是吗?
fn create_alt<T>() -> Foo<T> {
Foo::default()
}
在我看来,它们都在做完全相同的事情——如果 T
实现了 Default
(这是编译器希望我指定的),那应该无关紧要,因为 Option<T>
实现 Default
。
Here 是 Rust 游乐场的 link 这个例子。
这是一个已知问题,很难修复。 Issue #26925
简而言之,#[derive]
使用了不正确的边界:它假设为了 Foo<T>
实现 Default
,T
必须是 Default
,当实际上 Option<T>: Default
就足够了。
修复它的问题是可能有私有类型的结构成员,并且在具有私有成员的 public 泛型结构上使用 #[derive]
可能会部分公开该私有接口。例如,
trait MyTrait {}
struct MyType<T> {}
impl<T> Default for MyType<T> where T: MyTrait {}
#[derive(Default)]
pub struct PubType<T> {
member: MyType<T>,
}
如果 #[derive(Default)]
做了正确的事情,你实际上有这个 impl
块用于公开私有特征的 public 类型:
impl Default for PubType<T>
where T: MyTrait
{ ... }
现在解决这个问题的最好方法可能是避免在这种情况下使用 #[derive]
并自己编写 impl
。