I have a trait Component
with an associated type Msg
:
trait Component {
type Msg;
fn update(&self, msg: Self::Msg);
}
I modified it to implement a clone:
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()
}
}
I got an error:
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> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If I try to use generics, everything compiles (but I do get warnings):
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()
}
}
What's wrong? How to solve this problem?
While the code given contains other errorrs I'll focus on the question in particular situation.
When you have a trait bound which depends on an associated type in the trait being defined, provide a full path (aka UFCS) to the associated type:
trait Component: ComponentClone<<Self as Component>::Msg> {
// ^^^^^^^^^^^^^^^^^^^^^^^^ use a full path to Msg
type Msg;
fn update(&self, msg: Self::Msg);
}
pub trait ComponentClone<T> {
/* snip */
}
Related issue rust-lang/rust#62581 "Cycle computing supertraits" error could be more helpful #62581
Maybe you can get away by moving Msg
into an own trait:
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()
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.