Skip to content

Infering default generic arguments through traits #50107

Closed
@Ekleog

Description

@Ekleog

I've recently come across an issue of type inference that can be summed up like this:

trait Trait {
    type A;
    type B;
}

enum Foo<A, B> { A(A), B(B) }
impl<A, B> Trait for Foo<A, B> { type A = A; type B = B; }

enum Many<A, B, T1 = Foo<A, B>, T2 = Foo<A, B>, T3 = Foo<A, B>>
where T1: Trait<A = A, B = B>,
      T2: Trait<A = A, B = B>,
      T3: Trait<A = A, B = B>,
{
    M1(T1), M2(T2), M3(T3)
}

fn main() {
    let x = match 3 {
        1 => Many::M1(Foo::A(3u8)),
        _ => Many::M2(Foo::B(3u16)),
    };
}

returns

error[E0282]: type annotations needed
  --> src/main.rs:19:14
   |
18 |     let x = match 3 {
   |         - consider giving `x` a type
19 |         1 => Many::M1(Foo::A(3u8)),
   |              ^^^^^^^^ cannot infer type for `T3`

(playground)

I would have thought rustc could be able to infer the type for T3 as Foo<u8, u16>, through this procedure:

  1. the match arms return Many<'a, 'b, 't1, 't2, 't3> with 't1 = Foo<u8, 'b1> and 't2 = Foo<'a2, u16>
  2. The where clause says 't1: Trait<'a, 'b>, and we only have 't1: Trait<u8, 'b1>, so we can unify and get 'a = u8 and 'b = 'b1
  3. The where clause also says 't2: Trait<'a, 'b>, and we only have 't2: Trait<'a2, u16>, so we can unify and get 'a = 'a2 and 'b = u16
  4. So currently we are at the match arms return Many<u8, u16, Foo<u8, u16>, Foo<u8, u16>, 't3>
  5. Applying the default for 't3 gives 't3 = Foo<u8, u16>, which is what I'm hoping for

In the meantime, would you happen to know of a way to do what I'm trying to do? Ideally it'd be a variadic enum, but not being able to figure out a way to do it I just decided to have a cap on the number of variants, and hit this bug. If this could not be a solution based on auto-generating a rust file for all possible numbers of variants it'd be even better, but…

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inferenceArea: Type inferenceC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions