3

I'm trying to understand why map triggers a compilation error where a match expression doesn't.

I have:

use std::boxed::Box;
use std::io::Error;

trait MyTrait {
    fn foo(&self);
}

struct MyStruct { }

impl MyTrait for MyStruct {
    fn foo(&self) { }
}

I'd like to write a function that transforms an instance of MyStruct to an instance of Box<MyTrait>.

This compiles:

fn bar() -> Result<Box<MyTrait>, Error> {
    let x = Ok(MyStruct {});
    match x {
        Ok(y) => Ok(Box::new(y)),
        Err(err) => Err(err),
    }
} 

While this:

fn bar() -> Result<Box<MyTrait>, Error> {
    let x = Ok(MyStruct {});
    x.map(|y| Box::new(y))
} 

Gives an error:

error[E0308]: mismatched types
  --> src\main.rs:16:2
   |
14 | fn bar() -> Result<Box<MyTrait>, Error> {
   |             --------------------------- expected `std::result::Result<std::boxed::Box<MyTrait + 'static>, std::io::Error>` because of return type
15 |    let x = Ok(MyStruct {});
16 |    x.map(|y| Box::new(y))
   |  ^^^^^^^^^^^^^^^^^^^^^^ expected trait MyTrait, found struct `MyStruct`
   |
   = note: expected type `std::result::Result<std::boxed::Box<MyTrait + 'static>, std::io::Error>`
              found type `std::result::Result<std::boxed::Box<MyStruct>, _>`

What's the difference between the two bar() implementations?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Shmoopy
  • 5,334
  • 4
  • 36
  • 72
  • 1
    *`use std::boxed::Box;`* — you do not need to import `Box`. It's part of the prelude (like `Result`). – Shepmaster Aug 05 '18 at 16:32
  • I believe your question is answered by the answers of [How can I box the contents of an iterator of a type that implements a trait?](https://stackoverflow.com/q/48180008/155423) and/or [Trait mismatch for function argument](https://stackoverflow.com/q/48218224/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Aug 05 '18 at 16:36

0 Answers0