# Getting `dyn AB` from `dyn ABC` trait if both bounds `A + B`

Is there any reason for this code to be not compiled?

``````// Nightly
#![feature(trait_upcasting)]
#![allow(incomplete_features)]

trait A {
fn first(&self);
}

trait B {
fn second(&self);
}

trait C {
// IMAGINE HEAVY VERSION OF A OR DIFFERENT FUNCTIONAL
fn first(&self);
}

trait AB: A + B {}
impl<T: A + B> AB for T {}

trait BC: B + C {}
impl<T: B + C> BC for T {}

trait ABC: A + B + C {}
impl<T: A + B + C> ABC for T {}

// STRUCT + IMPL

struct ABCStruct {}

impl A for ABCStruct {
fn first(&self) {
println!("A FIRST")
}
}

impl B for ABCStruct {
fn second(&self) {
println!("B SECOND")
}
}

impl C for ABCStruct {
fn first(&self) {
println!("C FIRST")
}
}

// USERS

fn use_ab(ab: &dyn AB) {
ab.first()
}

fn use_bc(bc: &dyn BC) {
bc.first()
}

fn use_a(a: &dyn A) {
a.first()
}

fn ab_from_abc(abc: &dyn ABC) {
use_ab(abc as &dyn AB)
}

fn bc_from_abc(abc: &dyn ABC) {
use_bc(abc as &dyn BC)
}

fn a_from_abc(abc: &dyn ABC) {
use_a(abc as &dyn A)
}

fn main() {
let abc = ABCStruct {};
ab_from_abc(&abc as &dyn ABC);
bc_from_abc(&abc as &dyn ABC);
a_from_abc(&abc as &dyn ABC);
}
``````

There is the working version which I don't like (because of strange bounds):

If we forget about `AB + BC` additional bounds, then what reasons to not implement `AB` trait for `ABC`?

Most possible that I'm wrong but for know I think that: All traits with bound `ChildN` (N = 1, 2, ...) must be implmented for all traits `ParentN` (N = 1, 2, ...), as long as the set of `ChildN` basic traits is a subset of the set of `ParentN` basic trait.

I suppose that trait is basic when:

• It's have associated type or function (`A`, `B`, `C`, `Error`)
• It's have no bounds (Marker traits `Send`, `Sync` and possible user defined)

Notice that I don't ask to remove `AB`, I just wan't to auto implement (where is obviously possible)

I hope that you will point me on my misunderstanding or \ and appreciate by idea If you have other solution for this in current Rust I will really glad to see

I feel like this thread could get better and quicker responses (and could be a better fit in general) on users.rust-lang.org

Especially any good answer I could give would mostly (or rather exclusively) consist of explanations on how Rust works, and not consists of any discussions on how Rust design could/should be changed, but I donâ€™t feel like doing too in-depth explanations/explorations of â€śhow does Rust workâ€ť on the internals forum.

For nowâ€¦ in short: If you want a trait object `dyn AB`, there needs to be a vtable for it, and thereâ€™s nothing in `trait ABC: A + B + C` that could suggest to the compiler that a (pointer to a) `dyn AB` vtable should be included in a `dyn ABC` vtable, hence upcasting `&dyn ABC` to `&dyn AB` is not possible. You also cannot simply generate all possible vtables for all possible combinations of supertraits on mere speculation that there could be a need for it (that would quickly blow up to too many possible combinations).

4 Likes

I think this subject is suitable to irlo if it's proposing a new language feature. But this is already in nightly (in an incomplete state)

https://doc.rust-lang.org/beta/unstable-book/language-features/trait-upcasting.html

1 Like

It seems like it's not incomplete already. Check last checkbox

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