Skip to content

Infering default generic arguments through traits #50107

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…

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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