何とは言わない天然水飲みたさ

Rust-1.7.0でDefault::default()を使ったコードのコンパイルが通らない、処理系の不具合と思われる挙動

未解決。 応急処置済。

概要

Rust-1.7で以下のコードのコンパイルが通らない。

        use std::fmt::Debug;

#[derive(Debug, Default)]
struct Struct<T: Debug> {
    pub opt: Option<T>,
}

impl<T: Debug> Struct<T> {
    pub fn new() -> Self {
        Default::default() // bad
        //Struct { opt: Default::default(), } // ok
    }
}

pub fn main () {
    let s = Struct::<i32>::new();
    println!("s: {:?}", s);
}
      
コンパイルの通らないバージョン (Rust Playgroundへのリンク)
        <anon>:10:9: 10:25 error: the trait `core::default::Default` is not implemented for the type `T` [E0277]
<anon>:10         Default::default() // bad
                  ^~~~~~~~~~~~~~~~
<anon>:10:9: 10:25 help: see the detailed explanation for E0277
<anon>:10:9: 10:25 note: required by `core::default::Default::default`
      
Rust Playgroundで(Rust-1.7.0 stableで)コンパイルした場合のエラーメッセージ

おかしい。

ドキュメントによれば、Option<T>Default traitを実装していて、その際Tに対してT: Default等の制約はかかっていない。 (コメントアウトされているopt: Default::default()のコンパイルが通るのはそのためである)。

しかし、構造体のメンバ変数(の型)すべてがDefaultを実装しているにも関わらず、「TDefaultを実装していない」という理由でコンパイルは失敗する。

奇妙なのは、Struct<T>全体に対してのDefault::default()呼び出しが失敗するにも関わらず、#[derive(Debug, Default)]にはコンパイラが何の文句も言ってこないところだ。

やっぱりgithubでissueとか投げるべきなのかなぁ……

応急処置

コード例のとおり、Default::default()が失敗するのは構造体全体に対してのみであるため、各メンバ変数それぞれについてDefault::default()を呼び出すことで、意図した通りのオブジェクトを生成することは可能である。 メンバ変数が沢山あると大変だが、仕方がない……

追記 (2016-03-24 02:23)

すごい後輩氏が該当issueを見付けてくれた。 > #[derive] is too conservative with field trait bounds · Issue #26925 · rust-lang/rust すごい。 このissue、ここ4ヶ月ほど動きがないようだが、ひとまず動きを注視することにしてみようと思う。 (でも再燃させた方がよかったりするのかなぁ……)

追記2 (2017-06-01 17:52)

Rustのderiveはあまり頭がよくない - 簡潔なQ で問題が説明されている。