Compiler error "conflicting type" with associated types

I got an "conflicting type" error which I don't understand. I also didn't succeed to create a minimal example, so the code below doesn't compile.

The conflicting types are between an associated type and an explicit type. I expect those types to be different, as the conv_12 and conv_21 functions also suggest (because they don't compile). If I swap the associated type with the explicit type I expect it to be, it compiles fine (but that isn't an option because the code is generated).

I have no clue anymore what to check next or how to make a minimal example. What should be my next steps in understand why I get this error message here?

extern crate glib;

struct Type1;
struct Type2;

struct InnerType1;
struct InnerType2;

impl ::glib::wrapper::Wrapper for Type1 { type GlibType = InnerType1; type GlibClassType = InnerType1; }
impl ::glib::wrapper::Wrapper for Type2 { type GlibType = InnerType2; type GlibClassType = InnerType2;  }

/*
//Failing aliases
type Alias1 = <gobject_gen_test::auto::Counter as ::glib::wrapper::Wrapper>::GlibType;
type Alias2 = imp::RustCounterFfi;

fn _conv12(i: Alias1) -> Alias2 { i } //Failes
fn _conv21(i: Alias2) -> Alias1 { i } //Failes
*/

// Compiling aliases
type Alias1 = <Type1 as ::glib::wrapper::Wrapper>::GlibType;
type Alias2 = InnerType2;

/*
error[E0119]: conflicting implementations of trait `glib::translate::ToGlibPtr<'_, *mut RustCounterMod::imp::RustCounterFfi>` for type `Type1`:
    --> src/main.rs:1004:1                                                                                                                  
     |                                                                                                                                      
997  | impl <'a> ::glib::translate::ToGlibPtr<'a, *mut Alias1> for Type1                                                                    
     | ----------------------------------------------------------------- first implementation here                                          
...                                                                                                                                         
1004 | impl <'a> ::glib::translate::ToGlibPtr<'a, *mut Alias2> for Type1                                                                    
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Type1`
*/
impl <'a> ::glib::translate::ToGlibPtr<'a, *mut Alias1> for Type1 //Line 997
{
    type Storage = ();

    fn to_glib_none(&'a self) -> ::glib::translate::Stash<'a, *mut Alias1, Self> { unimplemented!() }
}

impl <'a> ::glib::translate::ToGlibPtr<'a, *mut Alias2> for Type1 //Line 1004
{
    type Storage = ();

    fn to_glib_none(&'a self) -> ::glib::translate::Stash<'a, *mut Alias2, Self> { unimplemented!() }
}```
<gobject_gen_test::auto::Counter as ::glib::wrapper::Wrapper>::GlibType

So what is the type of GlibType there?

Thanks for your response.

I expect it to be of type ::gobject_gen_test::auto::ffi::CtestCounter. The following functions compile:

fn conva1(i: <gobject_gen_test::auto::Counter as ::glib::wrapper::Wrapper>::GlibType) -> ::gobject_gen_test::auto::ffi::CtestCounter {i} //Works
fn conva2(i: ::gobject_gen_test::auto::ffi::CtestCounter) -> <gobject_gen_test::auto::Counter as ::glib::wrapper::Wrapper>::GlibType {i} //Works

And what is CtestCounter? It looks like whatever this boils down to is equivalent to imp::RustCounterFfi - are these possibly type aliases to the same underlying type?

It'd be helpful if you can paste those types definitions, rather than using conversion functions as examples.

Thanks for your help.

I created a testcase project for this issue on [1]. main.rs is basically an macro-expanded version of a unittest. The gen subcrate is generated by gtk-rs/gir. These types are defined by the glib_wrapper!-macro.

I also thought about a type reference, but if it was a type reference, I expect the functions _conv12 and _conv21 to compile.

[1] https://github.com/mredlek/gnome-class-test

I manage to simplify the case and updated the project. The case contains an external crate (gobject-gen-test, aliased as gen) which is included in main.rs. The content of the crate also exists in gobject_gen_test.rs, inside the main crate. In line 2 and 3 it is possible to switch between using the external crate and using the local mod. If the crate it used, compiling will fail. If the module is used, compilation succeeds.

Why does compilation fail when the crate is used?

I manage to create a minimal example. I have the following trait (named foo):

pub struct FooAssoc;
pub struct Foo;

pub trait Trait
{
    type Assoc;
}

impl Trait for Foo
{
    type Assoc = FooAssoc;
}

If I use the crate in the following way it failes:

extern crate foo;
//mod foo;

use foo::Trait;

trait GenericTrait<Generic>
{
}

pub struct Bar {
}

impl GenericTrait<<foo::Foo as Trait>::Assoc> for Bar
{
}

impl GenericTrait<Bar> for Bar
{
}

fn main()
{
}

If the crate is imported as module, it compiles. When it is imported as exern crate, it fails with a compile error. If I use a concrete type instead of an associated type, it also compiles. It is correct that the associated types in external crates aren't expanded?

Nicely done distilling it down. Seems like the same bug as this issue.

You are correct. Now I know what the real problem, I know how to proceed. If I think about, it does make sense if changing an associated type shouldn't be a breaking change.

What I think really cost me a lot of time and effort here is that the error message could be more clear. The compiler knew it disallowed this because the associated type was from an external crate, and didn't tell me. At least I know now for next time! Thanks for your help.