Как решить "цикл, обнаруженный при вычислении супертрейта"? - PullRequest
2 голосов
/ 06 апреля 2020

У меня есть черта Component со связанным типом Msg:

trait Component {
    type Msg;
    fn update(&self, msg: Self::Msg);
}

Я изменил ее для реализации клона:

trait Component: ComponentClone<Self::Msg> {
    type Msg;
    fn update(&self, msg: Self::Msg);
}

pub trait ComponentClone<T> {
    fn clone_box(&self) -> Box<dyn Component<Msg = T>>;
}

impl<T, M> ComponentClone<M> for T
where
    T: 'static + Component<M> + Clone,
{
    fn clone_box(&self) -> Box<dyn Component<M>> {
        Box::new(self.clone())
    }
}

impl<M: 'static> Clone for Box<dyn Component<M>> {
    fn clone(&self) -> Box<dyn Component<M>> {
        self.clone_box()
    }
}

детская площадка

Я получил ошибку:

error[E0391]: cycle detected when computing the supertraits of `Component`
 --> src/lib.rs:1:1
  |
1 | trait Component: ComponentClone<Self::Msg> {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: ...which again requires computing the supertraits of `Component`, completing the cycle
note: cycle used when collecting item types in top-level module
 --> src/lib.rs:1:1
  |
1 | trait Component: ComponentClone<Self::Msg> {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Если я пытаюсь использовать дженерики, все компилируется (но я получаю предупреждения):

trait Component<M>: ComponentClone<M> {
    fn update(&self, msg: M);
}

pub trait ComponentClone<T> {
    fn clone_box(&self) -> Box<dyn Component<T>>;
}

impl<T, M> ComponentClone<M> for T
where
    T: 'static + Component<M> + Clone,
{
    fn clone_box(&self) -> Box<dyn Component<M>> {
        Box::new(self.clone())
    }
}

impl<M: 'static> Clone for Box<dyn Component<M>> {
    fn clone(&self) -> Box<dyn Component<M>> {
        self.clone_box()
    }
}

Что не так? Как решить эту проблему?

1 Ответ

1 голос
/ 06 апреля 2020

Может быть, вы можете уйти, переместив Msg в собственную черту:

pub trait ComponentMsg {
    type Msg;
}

pub trait Component : ComponentClone + ComponentMsg {
    fn update(&self, msg: Self::Msg);
}

pub trait ComponentClone : ComponentMsg {
    fn clone_box(&self) -> Box<dyn Component<Msg=Self::Msg>>;
}

impl<T, M> ComponentClone for T
where
    T: 'static + Component<Msg=M> + Clone,
{
    fn clone_box(&self) -> Box<dyn Component<Msg=M>> {
        Box::new(self.clone())
    }
}

impl<M: 'static> Clone for Box<dyn Component<Msg=M>> {
    fn clone(&self) -> Box<dyn Component<Msg=M>> {
        self.clone_box()
    }
}
...