Cómo obtener un & dyn T de un Box <dyn T> [duplicado]

Jan 11 2021

Estoy tratando de obtener un &dyn Tde a Box<dyn T>, como en el siguiente ejemplo. Sin embargo, no se compila.

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)

El mensaje de error es

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`

Está claro que puede obtener &Tun Box<T>. No entiendo por qué no puede obtener un &dyn Tde a Box<dyn T>.

Respuestas

2 kmdreko Jan 11 2021 at 07:22

Para obtener un &dyn Tde a Box<dyn T>, use &*:

let c: &dyn MyTrait = &*b;

Se *usa para eliminar el cuadro en su contenido ( dyn MyTrait) y luego &se usa para obtenerlo como referencia.


Esta es también la forma "correcta" de obtener &Fooun Box<Foo>. La razón por la que &bfunciona con tipos concretos es porque el Derefrasgo permite &Box<T>ser coaccionado para &T:

Si T implementa Deref <Target = U>, y x es un valor de tipo T, entonces:

  • Los valores de tipo & T se convierten en valores de tipo & U

La razón por la que no funciona para los objetos de rasgo es que &dyn MyTrait podría ser válido &Box<...>y la coerción no se intenta incluso si falla.