Comment obtenir un & dyn T à partir d'un Box <dyn T> [duplicate]
J'essaie d'obtenir un à &dyn T
partir de a Box<dyn T>
, comme dans l'exemple suivant. Cependant, la compilation échoue.
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)
Le message d'erreur est
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`
Il est clair que vous pouvez obtenir un &T
fichier Box<T>
. Je ne comprends pas pourquoi vous ne pouvez pas obtenir &dyn T
un Box<dyn T>
.
Réponses
Pour obtenir un à &dyn T
partir de a Box<dyn T>
, utilisez &*
:
let c: &dyn MyTrait = &*b;
Le *
est utilisé pour déréférencer la boîte dans son contenu ( dyn MyTrait
) puis &
est utilisé pour l'obtenir comme référence.
C'est aussi la "bonne" façon d'obtenir un fichier à &Foo
partir d'un fichier Box<Foo>
. La raison qui &b
fonctionne avec les types concrets est que le Dereftrait permet &Box<T>
d'être contraint à &T
:
Si T implémente Deref <Target = U>, et x est une valeur de type T, alors:
- Les valeurs de type & T sont forcées à des valeurs de type & U
La raison pour laquelle cela ne fonctionne pas pour les objets de trait est que cela &dyn MyTrait
pourrait être valide &Box<...>
et que la contrainte n'est pas tentée même si elle échoue.