Code Fix

上級

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を付けます。

直し方: Shapedyn 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キーワードは「これは実行時に決まる動的な型のトレイトオブジェクトだ」とコンパイラに伝える印です。

直し方: Animaldyn 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の省略は許されず、必ず明示する必要があります。

直し方: Jobdyn 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にまとめて格納できます。

直し方: Greeterdyn 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の初期バージョンの名残で、現在は非推奨としてエラーになります。

直し方: Paymentdyn Payment にします。

この問題を解いてみる →

よくある誤解

「トレイトを実装した型なら、そのトレイト名自体をVecの要素の型として使えるはず」という思い込みは誤りです。トレイトはサイズが不定であるため、dynを付けたポインタ型(Box<dyn Trait>など)を介してのみ扱えます。

まとめ

E0782: trait objects must include the `dyn` keywordは上級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)