ZNackasha
ZNackasha

Reputation: 1089

How do I cast Arc<RwLock<dyn Child>> to Arc<RwLock<dyn Base>>

I currently have some code like the following:

use std::sync::{Arc, RwLock};

// Define traits
trait Child: Base {
    fn method_a(&self);
}

trait Base {
    fn method_b(&self);
}

// Struct implementing both traits
struct MyStruct {
    something: i32,
};

impl Child for MyStruct {
    fn method_a(&self) {
        println!("Method A");
    }
}

impl Base for MyStruct {
    fn method_b(&self) {
        println!("Method B");
    }
}

fn do_some_processing(parent: &Arc<RwLock<dyn Child>>) -> Arc<RwLock<dyn Base>> {
    //How do i do this?
}

fn main() {
    let my_struct = Arc::new(RwLock::new(MyStruct));

    let base = do_some_processing(&my_struct);

}

I want to limit the functions used after do_some_processing has been called. That is the reason for the two traits.

Upvotes: 0

Views: 89

Answers (1)

Milan Jaric
Milan Jaric

Reputation: 5646

Upcasting coercion is not yet stable. So this could work in +nightly

#![feature(trait_upcasting)]
use std::sync::{Arc, RwLock};

// Define traits
trait Child: Base {
    fn method_a(&self);
}

trait Base {
    fn method_b(&self);
}

// Struct implementing both traits
struct MyStruct {
    something: i32,
}

impl Child for MyStruct {
    fn method_a(&self) {
        println!("Method A");
    }
}

impl Base for MyStruct {
    fn method_b(&self) {
        println!("Method B");
    }
}

fn do_some_processing(parent: &Arc<RwLock<dyn Child>>) -> Arc<RwLock<dyn Base>> {
    parent.clone()
}



fn main() {
    let my_struct: Arc<RwLock<dyn Child>> = Arc::new(RwLock::new(MyStruct { something: 42 }));

    let base = do_some_processing(&my_struct);

}

---OR---

If you want to stick to stable you will need some wrapper

use std::sync::{Arc, RwLock};

// Define traits
trait Child: Base {
    fn method_a(&self);
}

trait Base {
    fn method_b(&self);
}

// Struct implementing both traits
struct MyStruct {
    something: i32,
}

impl Child for MyStruct {
    fn method_a(&self) {
        println!("Method A");
    }
}

impl Base for MyStruct {
    fn method_b(&self) {
        println!("Method B");
    }
}

// Wrapper struct to manually upcast Child to Base
struct BaseWrapper {
    inner: Arc<RwLock<dyn Child>>,
}

impl Base for BaseWrapper {
    fn method_b(&self) {
        self.inner.read().unwrap().method_b();
    }
}

fn upcast(child: Arc<RwLock<dyn Child>>) -> Arc<RwLock<dyn Base>> {
    Arc::new(RwLock::new(BaseWrapper { inner: child }))
}

fn main() {
    let my_struct: Arc<RwLock<dyn Child>> = Arc::new(RwLock::new(MyStruct { something: 42 }));

    let base = upcast(my_struct);

    base.read().unwrap().method_b();
}

Upvotes: 1

Related Questions