Downcasting an Arc<T> into Arc<U> where trait T: U

Is this possible? I've tried doing Arc<T + U> but this comes up with errors about U not being an auto-trait. Doing arc_t as Arc<U> comes up with errors about it not being a trivial cast. Really, I just want to share the control block and refcounts between the instances. I can change pretty much everything at the T layer, but changing the Arc<U> boundary of that crate isn't so easy (but is possible).

As for the use case, U is used in the low-level machinery (and from another crate which uses Arc<U> due to Send being required and U being something that really should be shared between the components), but T adds methods that are used a bit higher up (at this level, we know there is information locally, but there is also now some additional I/O that needs to go on). And there are still multiple implementations of T, so an enum doesn't work here either. But, if there's just a better way of doing it, I could start down that road as well.

The U library: Utils / rust-ghostflow ยท GitLab (U is HostingService)
The T is added in this MR in a CLI layer on top of that: https://gitlab.kitware.com/utils/rust-ghostflow/merge_requests/206 (T is LocalService which is basically a HostingService with some added things used because we know there's a specific repository on-disk that is being worked on)

A coworker was able to figure it out:

use std::sync::Arc;

trait U {
    fn u(&self);
}

trait T: U {
    fn as_arc_u(self: Arc<Self>) -> Arc<dyn U>;
}

struct A;
impl U for A {
    fn u(&self) {
        println!("u")
    }
}
impl T for A {
    fn as_arc_u(self: Arc<Self>) -> Arc<dyn U> {
        self
    }
}

fn f(a: Arc<dyn T>) -> Arc<dyn U> {
    a.as_arc_u()
}

fn main() {
    let a: Arc<dyn T> = Arc::new(A);
    a.clone().as_arc_u().u();
    f(a).u();
}

I had seen references to the same thing when searching on here for a solution with Option<dyn U> instead of Arc<dyn U> and the obvious default implementation, but hadn't tried to do it without the Option.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.