I have the following code that tries to take a reference to a trait object from a boxed trait:
trait T {}
struct S {}
impl T for S {}
fn main() {
let struct_box: Box<S> = Box::new(S {});
let struct_ref: &S = &struct_box;
let trait_box: Box<T> = Box::new(S {});
let trait_ref: &T = &trait_box;
}
The compiler returns the following error:
error[E0277]: the trait bound `std::boxed::Box<T>: T` is not satisfied
--> src/main.rs:12:25
|
12 | let trait_ref: &T = &trait_box;
| ^^^^^^^^^^ the trait `T` is not implemented for `std::boxed::Box<T>`
|
= note: required for the cast to the object type `T`
How do I properly borrow &T
from Box<T>
?
Box<T>
implements the AsRef<T>
trait, which provides the method as_ref()
, so you can turn it into a reference that way:
let trait_ref: &T = trait_box.as_ref();
Normally, deref coercions mean that you don't usually need to write this out explicitly. If you pass a value of type Box<T>
to a function that takes &T
, the compiler will insert the conversion for you. If you want to call one of the methods on T
that takes &self
, the compiler will insert the conversion for you. However, deref coercion doesn't apply to a cast to a trait object type (the compiler will choose an unsizing coercion instead, which is what happens in your example).
Borrow the contents of the Box
, rather than the Box
itself:
let trait_ref: &T = &*trait_box;
The reason the line involving &S
works is because the only way for Rust to get from Box<S>
to &S
is via "deref coercion"; that is, it repeatedly dereferences the value until either the types match, or it can't dereference any further.
Coercing to a trait object, on the other hand, isn't done using dereferencing at all; it involves constructing a new pointer directly from the given one. If it can't do that, it fails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With