Come ottenere un & dyn T da una scatola <dyn T> [duplicato]
Sto cercando di ottenere un &dyn T
da a Box<dyn T>
, come nell'esempio seguente. Tuttavia, non riesce a compilare.
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)
Il messaggio di errore è
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`
È chiaro che puoi ottenere un &T
da a Box<T>
. Non capisco perché non puoi ottenere un &dyn T
da a Box<dyn T>
.
Risposte
Per ottenere un &dyn T
da a Box<dyn T>
, usa &*
:
let c: &dyn MyTrait = &*b;
La *
viene utilizzato per Deref la scatola nel suo contenuto ( dyn MyTrait
) e quindi &
viene utilizzato per ottenere come riferimento.
Questo è anche il modo "giusto" per ottenere un &Foo
da a Box<Foo>
. Il motivo per cui &b
funziona con i tipi concreti è perché il Dereftratto consente &Box<T>
di essere costretti a &T
:
Se T implementa Deref <Target = U> e x è un valore di tipo T, allora:
- I valori di tipo & T sono obbligati a valori di tipo & U
Il motivo per cui non funziona per gli oggetti tratto è che &dyn MyTrait
potrebbe essere valido &Box<...>
e la coercizione non viene tentata anche se fallisce.