Hello,
I have been working 2 weeks on cyclic references for a side project I am working on. So I have managed to have cyclic references and avoiding Mutex (I am on tokio) using Arc's nightly new_cyclic. Here is an mvp example:
#![feature(arc_new_cyclic)]
use std::sync::{Arc, Weak};
struct Builder {
manager: Arc<Manager>
}
struct Manager {
core: Arc<Core>,
}
struct Core {
manager: Weak<Manager>
}
impl Core {
pub fn say_hi(&self) {
println!("hi!");
}
}
fn main() {
let manager: Arc<Manager> = Builder {
manager: Arc::new_cyclic(|me| Manager {
core: Arc::new(Core {
manager: me.clone()
})
})
}.manager;
manager.core.say_hi();
}
rust playground link: Rust Playground
However, I want the "child" of the cyclic structure to adhere on a trait, so I moved over to that using dyn Trait:
#![feature(arc_new_cyclic)]
use std::sync::{Arc, Weak};
struct Builder {
manager: Arc<Manager>
}
struct Manager {
core: Arc<dyn CoreTrait>,
}
trait CoreTrait {
fn say_hi(&self);
}
struct Core {
manager: Weak<Manager>
}
impl Core {
fn say_hello(&self) {
println!("Say hello");
}
}
impl CoreTrait for Core {
fn say_hi(&self) {
println!("say hi!");
}
}
fn main() {
let manager: Arc<Manager> = Builder {
manager: Arc::new_cyclic(|me| Manager {
core: Arc::new(Core {
manager: me.clone()
})
})
}.manager;
manager.core.say_hi();
manager.core.say_hello();
}
rust playground link: Rust Playground
The problem now is that I completely lose the type information as you can see it doesn't compile. For me it's important to still keep the type and be able to access other parts of the type that is not defined in the trait.
I am trying to implement the same thing using generic types, but it's seems quite challenging. For starters, I have created an even more simple example here:
#![feature(arc_new_cyclic)]
use std::sync::{Arc, Weak};
struct Builder<T: CoreTrait> {
manager: Arc<Manager<T>>
}
struct Manager<T: CoreTrait> {
core: Arc<T>,
}
trait CoreTrait {
fn say_hi(&self);
}
struct Core<T: CoreTrait> {
manager: Weak<Manager<T>>
}
impl<T: CoreTrait> Core<T> where Core<T>: CoreTrait {
fn say_hello(&self) {
println!("Say hello");
}
}
impl<T: CoreTrait> CoreTrait for Core<T> where Core<T>: CoreTrait {
fn say_hi(&self) {
println!("say hi!");
}
}
fn main() {
let core: Core<dyn CoreTrait> = Core {
manager: Weak::new()
};
}
rust playground link: Rust Playground
While the types compile, main fails with an error saying the size for values of type dyn CoreTrait cannot be known at compilation time and some other things which don't help me to figure out what I need to change. Boxing things didn't make any difference.
I am a bit desperate, calling for help now, if anyone has any hint I would be more than grateful.