Почему размерная черта необходима для функции строителя для генерации Rc <T>? - PullRequest
1 голос
/ 08 марта 2019

Этот код отлично работает ( детская площадка ):

use std::rc::Rc;

trait Foo {
    fn foo(&self);
}

struct Bar<T> {
    v: Rc<T>,
}

impl<T> Bar<T> where
T: Foo {
    fn new(rhs: Rc<T>) -> Bar<T> {
        Bar{v: rhs}
    }
}

struct Zzz {
}

impl Zzz {
    fn new() -> Zzz {
        Zzz{}
    }
}

impl Foo for Zzz {
    fn foo(&self) {
        println!("Zzz foo");
    }
}

fn make_foo() -> Rc<Foo> {
    Rc::new(Zzz{})
}

fn main() {
    let a = Bar::new(Rc::new(Zzz::new()));
    a.v.as_ref().foo()
}

, но если я создаю оболочку для генерации Rc, как показано ниже, компилятор жалуется на черту отсутствующего размера ( детская площадка )

fn make_foo() -> Rc<dyn Foo> {
    Rc::new(Zzz::new())
}

fn main() {
    let a = Bar::new(make_foo());
    a.v.as_ref().foo()
}

в обоих случаях, Bar :: новые полученные параметры с тем же типом Rc, почему компилятор ржавчины реагирует по-разному?

1 Ответ

2 голосов
/ 08 марта 2019

По умолчанию все переменные типа предполагаются равными Sized.Например, в определении структуры Bar существует неявное ограничение Sized, например:

struct Bar<T: Sized> {
    v: Rc<T>,
}

Объект dyn Foo не может быть Sizedпоскольку каждая возможная реализация Foo может иметь разный размер, поэтому не может быть выбран один размер.Но вы пытаетесь создать экземпляр Bar<dyn Foo>.

. Исправление заключается в отказе от черты Sized для T:

struct Bar<T: ?Sized> {
    v: Rc<T>,
}

А также в контекстереализации:

impl<T: ?Sized> Bar<T>
where 
    T: Foo 

?Sized на самом деле не ограничение, а ослабление существующего ограничения Sized, так что оно не требуется.

Последствие отказа от Sized в том, что ни один из Bar методов этого блока impl не может использовать T, кроме как по ссылке.

...