HELP: Why does this code fail to compile?

trait Instance<B: Backend>: Sized {
    fn create() -> Self;
}

trait Backend: Sized {
    type Instance: Instance<Self>;
}

pub mod private {
    pub enum GfxBackend {}
    impl super::Backend for GfxBackend {
        type Instance = Instance;
    }

    pub struct Instance {}

    impl super::Instance<GfxBackend> for Instance {
        fn create() -> Self {
            Self {}
        }
    }
}

struct Engine<B: Backend> {
    instance: B::Instance,
}

impl Engine<private::GfxBackend> {
    pub fn new() -> Self {
        Self::with()
    }
}

impl<B: Backend> Engine<B> {
    pub fn with() -> Self {
        let instance = private::Instance::create();
        // COMPILER ERROR:
        // mismatched types
        // expected associated type `<B as gfx_hal::Backend>::Instance`
        // found struct `gfx_backend_metal::Instance`
        // consider constraining the associated type `<B as gfx_hal::Backend>::Instance` to `gfx_backend_metal::Instance` or calling a method that returns `<B as gfx_hal::Backend>::Instance`
        // for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.htmlrustc(E0308)
        Self { instance }
    }
}

fn main() {
    let engine = Engine::new();
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/main.rs:43:16
   |
43 |         Self { instance }
   |                ^^^^^^^^ expected associated type, found struct `private::Instance`
   |
   = note: expected associated type `<B as Backend>::Instance`
                       found struct `private::Instance`
   = help: consider constraining the associated type `<B as Backend>::Instance` to `private::Instance` or calling a method that returns `<B as Backend>::Instance`
   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

In this code, the signature of the function says that it can return an Engine<B> for any Backend type, but the body of the function can only create a private::Instance, which only works for the specific type GfxBackend:

impl<B: Backend> Engine<B> {
    pub fn with() -> Self {
        let instance = private::Instance::create();
        Self { instance }
    }
}

If you want it to work with the generic type B, then it should be:

impl<B: Backend> Engine<B> {
    pub fn with() -> Self {
        let instance = B::Instance::create();
        Self { instance }
    }
}
1 Like

thks !!! :slight_smile: