Como obter um & dyn T de uma caixa <dyn T> [duplicar]
Estou tentando obter um &dyn T
de a Box<dyn T>
, como no exemplo a seguir. No entanto, ele não consegue compilar.
trait MyTrait {
}
struct Foo;
impl MyTrait for Foo {}
fn main() {
let b: Box<dyn MyTrait> = Box::new(Foo);
let c: &dyn MyTrait = &b;
}
(https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=69c72904fbceae5b55470a878a441b7d)
A mensagem de erro é
error[E0277]: the trait bound `Box<dyn MyTrait>: MyTrait` is not satisfied
--> src/main.rs:10:27
|
10 | let c: &dyn MyTrait = &b;
| ^^ the trait `MyTrait` is not implemented for `Box<dyn MyTrait>`
|
= note: required for the cast to the object type `dyn MyTrait`
É claro que você pode obter um &T
de a Box<T>
. Não entendo por que você não consegue obter um &dyn T
de a Box<dyn T>
.
Respostas
Para obter um &dyn T
de a Box<dyn T>
, use &*
:
let c: &dyn MyTrait = &*b;
O *
é usado para desreferenciar a caixa em seu conteúdo ( dyn MyTrait
) e, em seguida, &
é usado para obtê-lo como uma referência.
Essa também é a maneira "certa" de obter um &Foo
de a Box<Foo>
. A razão que &b
funciona com tipos concretos é porque o Dereftraço permite &Box<T>
ser coagido a &T
:
Se T implementa Deref <Target = U>, e x é um valor do tipo T, então:
- Valores do tipo & T são coagidos para valores do tipo & U
O motivo pelo qual isso não funciona para objetos de traço é que &dyn MyTrait
pode ser válido &Box<...>
e a coerção não é tentada mesmo se falhar.