Passing a bounded struct to a function crashes with 'doesn't have a size known at compile-time'

How do I pass a struct with trait bounds as argument to a function? Consider this code:

use std::io::Write;
use termion::raw::IntoRawMode;

struct Game<W: Write> {
  inner: termion::raw::RawTerminal<W>,
}

impl<W: Write> Game<W> {
  fn new(w: W) -> Self {
    Self {
        inner: w.into_raw_mode().unwrap(), // consider returning `Result` instead of unwrapping
     }
  }

  fn write(&mut self) {
    write!(self.inner, "test");
  }
}

fn write(g: Game<Write>) {
   g.write();
}

fn main() {

  let stdout = std::io::stdout();
  let stdout = stdout.lock();
  let mut game = Game::new(stdout);
  write(game);
}

I want to pass game to the function write(). But this raises the error:

error[E0277]: the size for values of type `(dyn std::io::Write + 'static)` cannot be known at compilation time
  --> src/main.rs:21:1
   |
21 | / fn write(g: Game<dyn Write>) {
22 | |     g.write();
23 | | }
   | |_^ doesn't have a size known at compile-time

I understand why this error happens, but I've no clue how to fix it.

I tried to change the signature of write() to:

 fn write(g: Game<dyn Write>) {
   g.write();
}

as well as to:

 fn write(g: Box<Game<Write>>) {
   g.write();
}

But without luck: the error kept the same. Can someone show me explain why Boxing Game doesn't work? I thought that by Boxing a variable you put the variable on the heap, where as the pointer to the Box is pushed on the stack. And that pointer is fixed size, so why the error?

Also, how do I fix this problem?

Always use generic function for trait-bounded functionality, unless it doesn't compiles.

fn write<W: Write>(g: Game<W>) {
    g.write();
}

The "it doesn't compile" case usually is to store dyn trait objects in collections. But frequent use of this pattern should be considered as a signal of bad structure.

Thanks a lot!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.