普通实现Default的可能错误?

时间:2017-09-06 16:10:40

标签: rust traits

鉴于以下结构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 Playground。

1 个答案:

答案 0 :(得分:1)

这是一个已知问题,很难修复。 Issue #26925

简而言之,#[derive]使用了不正确的边界:它假定为了Default实现Foo<T>T必须是Default,而实际上Option<T>: Default就足够了。

修复它的问题在于,可以使用私有类型的struct成员,并且在具有私有成员的公共泛型结构上使用#[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块:

impl Default for PubType<T>
    where T: MyTrait
{ ... }

现在解决此问题的最佳方法可能是避免在这种情况下使用#[derive]并自己编写impl