Consider the following Rust code:
#[derive(Debug, Clone, Copy)]
struct Struct;
trait Trait {}
impl Trait for Struct {}
fn f() {
// Why does this coerce to the target type (Result<Box<dyn Trait>, ()>)
let rbdt: Result<Box<dyn Trait>, ()> = Ok(Box::new(Struct));
// And this coerces to the target type...
let a = Box::new(Struct);
let rbdt: Result<Box<dyn Trait>, ()> = Ok(a);
// But this does not:
let a = Ok(Box::new(Struct));
let rbdt: Result<Box<dyn Trait>, ()> = a; // Error: mismatched types
}
Why do the first two assignments to rbdt work correctly, coercing the value into the target type (Result<Box<dyn Trait>, ()>), but the 3rd one does not? It seems to me that in all three cases the type of the RHS of the assignment is Result<Box<Struct>, ()>, so it's perplexing that some forms work while other cause a mismatched types error.
What are the rules governing when types containing trait objects can be assigned to? Are these documented anywhere?
I think this is less about coercion, and more about inference.
In first two cases it can immediately be inferred that
TinResult<Box<T>>is something other thanStruct, while in the thirdBox<Struct>is already a concrete type which then conflicts withT = dyn Traitrequirement introduced by type annotation onrdbt.Additionally I want to note that it is generally not possible to coerce a value that already exists to a type of a different, especially larger, size, which
Box<Struct>andBox<dyn Trait>are due to the latter being a fat pointer.