Inferring generic parameter by intersecting trait impls

Consider this minimal example:

struct A;
struct B;

trait Ch1<const N: u8> {}
trait Ch2<const N: u8> {}

impl Ch1<1> for A {}
impl Ch1<2> for A {}

impl Ch2<1> for B {}
impl Ch2<3> for B {}

fn foo<const N: u8>(_: impl Ch1<N>, _: impl Ch2<N>) {}

fn main() {
    foo::<1>(A, B);
    // foo(A, B); // does not compile
}

The only N for which both trait bounds hold is 1. In principle, the compiler could figure this out and infer N = 1.

Instead it fails with: error[E0283]: type annotations needed

Is there a fundamental reason Rust’s type/const parameter inference can’t do this kind of “intersection” reasoning in simple, finite, unambiguous cases?

Regardless of whether this is feasible, Rust’s existing use of “only one impl matches” reasoning creates trouble by making it a breaking change to introduce additional impls, and I don’t think we should have more of that kind of reasoning.

6 Likes

playground

I didn't see any error with this ? :thinking: so what is wrong ?

Can I have more detail impl for this ?

@giang299 Please comment in the line saying "does not compile".