Как получить & dyn T из коробки <dyn T> [дубликат]

Jan 11 2021

Я пытаюсь получить &dyn Tот a Box<dyn T>, как в следующем примере. Однако он не компилируется.

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)

Сообщение об ошибке

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`

Понятно, что получить a можно &Tиз файла Box<T>. Я не понимаю, почему вы не можете получить &dyn Tа Box<dyn T>.

Ответы

2 kmdreko Jan 11 2021 at 07:22

Чтобы получить &dyn Tот a Box<dyn T>, используйте &*:

let c: &dyn MyTrait = &*b;

*Используются для deref коробки в его содержание ( dyn MyTrait) , а затем &используются для получения его в качестве ссылки.


Это также «правильный» способ получить &Fooот a Box<Foo>. Причина , по которой &bработает с конкретными типами потому , что Derefсвойство позволяет &Box<T>быть принужден к &T:

Если T реализует Deref <Target = U>, а x является значением типа T, то:

  • Значения типа & T приводятся к значениям типа & U

Причина, по которой это не работает для объектов-признаков, заключается в том, что они &dyn MyTrait могут быть действительными, &Box<...>и принуждение не выполняется, даже если оно не выполняется.