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);
}
<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`
おかしい。
ドキュメントによれば、Option<T>
はDefault
traitを実装していて、その際T
に対してT: Default
等の制約はかかっていない。
(コメントアウトされているopt: Default::default()
のコンパイルが通るのはそのためである)。
しかし、構造体のメンバ変数(の型)すべてがDefault
を実装しているにも関わらず、「T
がDefault
を実装していない」という理由でコンパイルは失敗する。
奇妙なのは、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 で問題が説明されている。