1
// traits describing aspects of functionality needed elsewhere
trait A {}
trait B {}

// provider of functionality is always expected to support both
trait AB {}
impl<T: A + B> AB for T {}

struct Provider0 {}
impl A for Provider0 {}
impl B for Provider0 {}

// provider is picked dynamically at runtime
fn new_ab(i: u8) -> Box<dyn AB> {
    match i {
        0 => Box::new(Provider0 {}),
        _ => unimplemented!(),
    }
}

use std::sync::Arc;
fn use_a(a: Arc<dyn A>) {}
fn use_b(b: Arc<dyn B>) {}

fn run() {
    let x = new_ab(0);
    let x: Arc<dyn AB> = Arc::from(x);
    use_a(x.clone());
    use_b(x);
}
error[E0308]: mismatched types
  --> src/lib.rs:28:11
   |
28 |     use_a(x.clone());
   |           ^^^^^^^^^ expected trait `A`, found trait `AB`
   |
   = note: expected struct `std::sync::Arc<(dyn A + 'static)>`
              found struct `std::sync::Arc<dyn AB>`

error[E0308]: mismatched types
  --> src/lib.rs:29:11
   |
29 |     use_b(x);
   |           ^ expected trait `B`, found trait `AB`
   |
   = note: expected struct `std::sync::Arc<(dyn B + 'static)>`
              found struct `std::sync::Arc<dyn AB>`

The functionality provided by the traits is identical in behavior, however the context is completely disjoint so making consumers accept Arc<dyn AB> would be wrong and adding a dependency that doesn't really exist (and having to resolve naming conflicts as the names of the methods are the same in both traits.)

Is there a way to return a trait object implementing multiple traits and pass that object as parameter to function expecting the individual trait objects wrapped in Arc?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Tommi Komulainen
  • 2,830
  • 1
  • 19
  • 16
  • 1
    Maybe I don't understand something, but what happens if you have `Provider1` which implements `AB` and not `A`? – Alexey Romanov Mar 11 '20 at 08:20
  • As in, trait AB can also be implemented for types which don't implement A or B – Nihar Karve Mar 11 '20 at 09:02
  • See also [Why can't I cast a Box with an extended trait to a Box with the base trait?](https://stackoverflow.com/q/49543778/155423); [Cast sub-trait pointer to super-trait pointer](https://stackoverflow.com/q/43958048/155423); [Downcast traits inside Rc for AST manipulation](https://stackoverflow.com/q/40024093/155423) – Shepmaster Mar 11 '20 at 13:58
  • See also: [Clone and Cast Rc pointer](https://stackoverflow.com/q/55927766/155423) – Shepmaster Mar 11 '20 at 14:04
  • [The duplicates applied to your situation](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f9ff54eed953d3d646237d8c6cdb9d5f). – Shepmaster Mar 11 '20 at 14:22

0 Answers0