Weird compiler error surrounding Box::new

Hello,

When trying to compile the following code:

trait MyTrait{}
impl MyTrait for () {}

fn main() {
    // Emits error
    let a = Box::<dyn MyTrait>::new(());
    // Works:
    let a: Box<dyn MyTrait> = Box::new(());
}

The first row emits the following error:

error[E0599]: the function or associated item `new` exists for struct `Box<dyn MyTrait>`, but its trait bounds were not satisfied
    --> src/main.rs:6:33
     |
1    | trait MyTrait{}
     | ------------- doesn't satisfy `dyn MyTrait: Sized`
...
6    |     let a = Box::<dyn MyTrait>::new(());
     |                                 ^^^ function or associated item cannot be called on `Box<dyn MyTrait>` due to unsatisfied trait bounds
     |

Does this behavior make any sense? What am I missing?

I think this might be related to unsized coercion.

1 Like

If Box::<dyn MyTrait>::new(()) were valid, it would imply passing a value of type dyn MyTrait to Box::new(), which is not possible because the language does not support handling dynamically sized values directly. So, instead, a Box<()> has to be created, then coerced to Box<dyn MyTrait>.

7 Likes

When I create eg a simple string literal (let x: &str ="abc";) does the compiler here also trigger an unsized coercion? Maybe from an array?

Regards
keks

No. String literals already have type &'static str to begin with.

However, if you use byte string literals, like b"abc" in code like

let x: &[u8] = b"abc";

then you do have an unsized coercion, because b"abc" itself has type &'static [u8; 3], a reference to a fixed-size array. The code snippet above would use unsize-coercion to turn this “reference to an array” (&[u8; 3]) into a “reference to a slice” (&[u8]).

Byte-string literals in Rust serve to offer ASCII-encoded text directly as an array or slice of bytes, which can improve readability a lot in some use-cases.

The main reason why “ordinary” strings don’t work the same is likely as simple as the fact that there is no fixed-size string-type, comparable to arrays, in the standard library. (And that in turn is likely motivated by the fact that the memory-size of strings, i.e. number of bytes, for UTF-8 encoded strings can be a confusing or unhelpful measure in practice, so it’s useful not to hardcode these on the type level).

5 Likes

Very good explanation! Thanks! :+1: