Associated types do not work in multiple crates

⚓ Rust    📅 2025-09-21    👤 surdeus    👁️ 7      

surdeus

Warning

This post was published 40 days ago. The information described in this article may have changed.

I'm using stable rust 1.90 rustc 1.90.0 (1159e78c4 2025-09-14).

foo crate:

// foo/src/lib.rs
pub trait HasConfig: Sized {
    type Config;
}

pub struct A;

pub struct AConfig;

impl HasConfig for A {
    type Config = AConfig;
}

bar crate:

// bar/src/lib.rs
use foo::{A, HasConfig};

pub enum EConfig {
    A(<A as HasConfig>::Config),
}

impl From<<A as HasConfig>::Config> for EConfig {
    fn from(config: <A as HasConfig>::Config) -> Self {
        EConfig::A(config)
    }
}

rustc complains that:

error[E0119]: conflicting implementations of trait `std::convert::From<EConfig>` for type `EConfig`
 --> bar\src\lib.rs:7:1
  |
7 | impl From<<A as HasConfig>::Config> for EConfig {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: conflicting implementation in crate `core`:
          - impl<T> std::convert::From<T> for T;

Why does rustc think that <A as HasConfig>::Config is EConfig?

If I replace impl From<<A as HasConfig>::Config> for EConfig with impl From<AConfig> for EConfig, then rustc is happy.

If I put the code in the same foobar crate, rustc is happy again:

// foobar/src/lib.rs
pub trait HasConfig: Sized {
    type Config;
}

pub struct A;

pub struct AConfig;

impl HasConfig for A {
    type Config = AConfig;
}

pub enum EConfig {
    A(<A as HasConfig>::Config),
}

impl From<<A as HasConfig>::Config> for EConfig {
    fn from(config: <A as HasConfig>::Config) -> Self {
        EConfig::A(config)
    }
}

Does rustc check associated types differently if the trait / struct / impl is in another crate? Or is it a bug in the type system?

2 posts - 1 participant

Read full topic

🏷️ Rust_feed