1

I can create a Write trait object that points to a (heap-stored) File object as such:

let a : Box<dyn Write> = Box::new(File::open("/dev/null").unwrap());  // Compiles fine.

Using the turbofish notation, however, produces an error (Rust 1.56.1):

let a : Box<dyn Write> = Box::<dyn Write>::new(File::open("/dev/null").unwrap());  // Fails to compile.

The error being:

error[E0599]: the function or associated item `new` exists for struct `Box<dyn std::io::Write>`, but its trait bounds were not satisfied
    --> src/main.rs:37:48
     |
37   |     let a : Box<dyn Write> = Box::<dyn Write>::new(File::open("/dev/null").unwrap());  // Fails to compile.
     |                                                ^^^ function or associated item cannot be called on `Box<dyn std::io::Write>` due to unsatisfied trait bounds
     |
    ::: /home/[REDACTED]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/mod.rs:1368:1
     |
1368 | pub trait Write {
     | --------------- doesn't satisfy `dyn std::io::Write: Sized`
     |
     = note: the following trait bounds were not satisfied:
             `dyn std::io::Write: Sized`

I've been poking at the problem for the better part of a day. Either I'm missing something fundamental, or the special language treatment of Box is at play here (but I don't see how).

Nubarke
  • 2,020
  • 2
  • 13
  • 12

1 Answers1

4

Your code is actually quite deceptive.

let a: Box<dyn Write> = Box::new(File::open("/dev/null").unwrap());

doesn't actually create a Box<dyn Write> like you think. It first creates a Box<File>, then the Box<File> is cast into a Box<dyn Write>. If you turbofish with File, then it works:

let a: Box<dyn Write> = Box::<File>::new(File::open("/dev/null").unwrap());

So, if you want to be explicit about the type, use an as cast instead of turbofish:

// a is Box<dyn Write>
let a = Box::new(File::open("/dev/null").unwrap()) as Box<dyn Write>;
Aplet123
  • 33,825
  • 1
  • 29
  • 55
  • Thank you for your prompt response. I've re-read the relevant paragraph in "Programming Rust" and indeed, it explicitly mentions the conversion: "Likewise, Rust will happily convert a Box to a Box , a value that owns a writer in the heap." I'll do some tests with this in mind; meanwhile, solid +1. – Nubarke Nov 27 '21 at 00:33