E0782: trait objects must include the `dyn` keyword の原因と直し方
トレイトを直接型として使おうとすると、コンパイル時のサイズが確定できないためエラーになります。トレイトオブジェクトとして扱いたい場合は、dynキーワードを付けてBox<dyn Trait>や&dyn Traitのようにポインタ経由にする必要があります。
エラーメッセージの読み方
error[E0782]: trait objects must include the `dyn` keyword
E0782- エラーコード — `rustc --explain E0782` で詳しい説明が見られます
trait objects must include the `dyn` keyword- 詳細メッセージ — 何が問題だったか
このエラーが出る典型パターン
パターン1
1 trait Shape { 2 fn area(&self) -> f64; 3 } 4 struct Circle { r: f64 } 5 impl Shape for Circle { 6 fn area(&self) -> f64 { 3.14 * self.r * self.r } 7 } 8 fn main() { 9 let shapes: Vec<Box<Shape >> = vec![Box::new(Circle { r: 2.0 })]; ^ 10 println!("{}", shapes[0].area()); 11 }
error[E0782]: trait objects must include the `dyn` keyword
トレイトを型として直接書くとサイズが不定になります。トレイトオブジェクトとして使うにはdynを付けます。
直し方: Shape を dyn Shape にします。
広告
広告スロット(未設定)
パターン2
1 trait Animal { 2 fn speak(&self) -> String; 3 } 4 struct Dog; 5 impl Animal for Dog { 6 fn speak(&self) -> String { String::from("woof") } 7 } 8 fn main() { 9 let animals: Vec<Box<Animal >> = vec![Box::new(Dog)]; ^ 10 println!("{}", animals[0].speak()); 11 }
error[E0782]: trait objects must include the `dyn` keyword
dynキーワードは「これは実行時に決まる動的な型のトレイトオブジェクトだ」とコンパイラに伝える印です。
直し方: Animal を dyn Animal にします。
パターン3
1 trait Job { 2 fn run(&self) -> i32; 3 } 4 struct Task; 5 impl Job for Task { 6 fn run(&self) -> i32 { 1 } 7 } 8 fn main() { 9 let jobs: Vec<Box<Job >> = vec![Box::new(Task)]; ^ 10 println!("{}", jobs[0].run()); 11 }
error[E0782]: trait objects must include the `dyn` keyword
Rust 2021ではdynの省略は許されず、必ず明示する必要があります。
直し方: Job を dyn Job にします。
パターン4
1 trait Greeter { 2 fn hello(&self) -> String; 3 } 4 struct English; 5 impl Greeter for English { 6 fn hello(&self) -> String { String::from("hello") } 7 } 8 fn main() { 9 let greeters: Vec<Box<Greeter >> = vec![Box::new(English)]; ^ 10 println!("{}", greeters[0].hello()); 11 }
error[E0782]: trait objects must include the `dyn` keyword
Box<dyn Trait>にすることで、異なる具象型を同じVecにまとめて格納できます。
直し方: Greeter を dyn Greeter にします。
パターン5
1 trait Payment { 2 fn amount(&self) -> i32; 3 } 4 struct Cash; 5 impl Payment for Cash { 6 fn amount(&self) -> i32 { 500 } 7 } 8 fn main() { 9 let payments: Vec<Box<Payment >> = vec![Box::new(Cash)]; ^ 10 println!("{}", payments[0].amount()); 11 }
error[E0782]: trait objects must include the `dyn` keyword
トレイト名だけを型のように書くのはRustの初期バージョンの名残で、現在は非推奨としてエラーになります。
直し方: Payment を dyn Payment にします。
よくある誤解
「トレイトを実装した型なら、そのトレイト名自体をVecの要素の型として使えるはず」という思い込みは誤りです。トレイトはサイズが不定であるため、dynを付けたポインタ型(Box<dyn Trait>など)を介してのみ扱えます。
まとめ
E0782: trait objects must include the `dyn` keywordは上級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。