I have the following 2 traits: Org, Capability.
#![feature(specialization)]
trait Org {}
struct OrgV1 {}
impl Org for OrgV1 {...}
struct OrgV2 {}
impl Org for OrgV2 {...}
trait Capability {}
struct CapV1 {}
impl Capability for CapV1 {...}
struct CapV2 {}
impl Capability for CapV2 {...}
// Capability has a generic associated .ensure method that is able to handle
// any combination of the concrete types of Org and Capability.
// It is implemented with rust's specialization feature: https://rust-lang.github.io/rfcs/1210-impl-specialization.html
trait CapabilityService<O: Org> where Self: Capability {
fn ensure(self, org_config: Arc<O>) -> Result<bool>
}
impl<O: Org, C: Capability> CapabilityService<O> for C {
default fn ensure(self, org_config: Arc<O>) -> Result<bool> {
... // not so important logic
return Ok(true)
}
}
fn main() {
...
// assume I have the following 2 variables I got in runtime by serde's deserealization:
// org_trait: instance Org trait object
// capability_trait: instance Capability trait object
// Given that there is .ensure that can handle any combination of the concrete repo and org
// is there a way in rust to downcast to a generic concrete type, aka:
let concrete_org = org_trait.as_any().downcast_ref::<T: Org>().unwrap()
let concrete_capability = capability_trait.as_any().downcast_ref::<T: Capability>().unwrap()
// where concrete_org and concrete_capability are some concrete types of Org,
// and Capability respectively.
let result = concrete_capability.ensure(concrete_org)
}
I am aware that I could do something like this:
{
if let Some(org) = org_trait.as_any().downcast_ref::<OrgV1>() {
if Some(cap) = cap_trait.as_any().downcast_ref::<CapV1>() {
cap.ensure(org)
}
...
} else Some(org) = org_trait.as_any().downcast_ref::<OrgV2>() {
...
}
...
}
But it seems like a nightmare to handle once there are more Org/Cap implementations(in my actual case, I have 3 traits that ensure works on, which I didn't include to make the picture a bit clear)
Is it possible to downcast trait to a generic concrete type, given the constraints(since we know that .ensure would be able to be called no matter what the concrete types are)? I would like to avoid writing my own long chain of nested if let Some
s if possible