Hi, I am new to rust and I am trying to understand how the following snippet works:
let x: Box<&str> = Box::new("test");
let y: Box<dyn AsRef<str>> = x;
If I understand correctly, we get fat pointers in case of references. So for the following snippet:
let x: &str = "test";
let y: &dyn AsRef<str> = &x;
y is a fat pointer, which will have a pointer to x, and a pointer to vtable entry for as_ref. This is a concept in rust and the rust compiler handles it by appropriately creating a fat pointer for y.
But I don't get what happens in the case of Box. When I say let y: Box<dyn AsRef<str>> = x, I am assigning a box of 1 type to a variable which is a box of another type. Here y itself is not of a pointer type, it's a Box. The fat pointer will have to be inside the Box. But we are not asking rust to create a new Box type by calling Box::new or some other function that will convert x to a box of a fat pointer. The box is not directly a construct of a language like &, it's a Type defined by std. So how does rust know how to create a new box type which takes ownership of x, and uses a fat pointer. Is there a Trait or function that I am not aware of and is being called here implicitly?
TLDR: if I am writing an implementation, say MyBox, which is similar to Box, what would I have in MyBox, which will allow the above code to compile, and how would it work?
Thanks for the quick reply. Following your answer, I was able to find what I was looking for. So the coercion is done based on (currently unstable) trait CoerceUnsized. Conveniently the documentation also details how the new instance is created: The coercion will work by coercing the Bar<T> field into Bar<U> and filling in the rest of the fields from Foo<T> to create a Foo<U>
Yup, I got that part. I was just confused about the unsized coercion. Just like how Deref trait helps treat a type as a smart pointer, I was not sure which trait is used in this case. There is a lot of "magic" that goes on in rust which relies on traits under the hood (like IntoIter in for loops, and Defer for smart pointers). So I was expecting a Trait to be responsible for unsized coercion as well, but I was not aware of the CoerceUnsized trait (or even coerce word here which would have helped me look this up quickly). I wish there was a simpler way to figure this out other than just going over the docs or asking around. I did try MIR in https://play.rust-lang.org/, but that didn't help.