1

Why is an explicit type needed in order to make this compile? I'd expect the compiler to understand that Box<STest> is equal to Box<(dyn TTest + 'static)> in the first test case since STest implements the TTest trait. What makes the compiler able to implicitly cast it to a BoxedTTest in the second case, while it doesn't do so in the first case?

I'm compiling it with rustc --edition 2018 mwe.rs on rustc 1.40.0 (stable), but the same error happens with --edition 2015 and on rustc 1.42.0-nightly.

trait TTest {}

struct STest {}
impl TTest for STest {}

type BoxedTTest = Box<dyn TTest>;

fn foo(_test: &BoxedTTest) {}

pub fn main() {
    // expected trait TTest, found struct `STest`
    let test1 = Box::new(STest {});
    foo(&test1);

    // OK
    let test2: BoxedTTest = Box::new(STest {});
    foo(&test2);
}

The full error is as follows:

error[E0308]: mismatched types
  --> mwe.rs:13:9
   |
13 |     foo(&test1);
   |         ^^^^^^ expected trait TTest, found struct `STest`
   |
   = note: expected type `&std::boxed::Box<(dyn TTest + 'static)>`
              found type `&std::boxed::Box<STest>`
Charlie
  • 978
  • 1
  • 7
  • 27
  • https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=83390ca4dc754e1286eba188f457552b – Stargateur Dec 24 '19 at 21:39
  • @Stargateur It seems I kinda messed up the boundaries between data storage (since I want to store anything that implements a TTest in a Vector) and processing data. Let me try to refactor my code to take `dyn TTest` everywhere and only use the Box'ed version when interacting with Vec's. – Charlie Dec 24 '19 at 21:45

1 Answers1

0

In this case the answer is not to use Box like this. As suggested by Stargateur in the comments, the following is the way to go:

trait TTest {}

struct STest {}
impl TTest for STest {}

fn foo(_test: &dyn TTest) {}

pub fn main() {
    // OK
    let test1 = STest {};
    foo(&test1);
}

If you still need to use Box to store it in a vector for example, you should only use it where strictly needed:

fn add_test(test: Box<dyn TTest>) {
    let mut vec = vec!{};
    vec.push(test);
}
// ...
add_test(Box::new(test1));
Charlie
  • 978
  • 1
  • 7
  • 27
  • Note that in your case it could be better to avoid dynamic dispatch https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b997a8208655ead4e7314368519ae159 my comment was just "here who this should be code to compile" but if your type is know at compile type better to have a compile time dispatch – Stargateur Dec 24 '19 at 22:32