Closed
Description
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`
I would have thought rustc could be able to infer the type for T3
as Foo<u8, u16>
, through this procedure:
- the match arms return
Many<'a, 'b, 't1, 't2, 't3>
with't1 = Foo<u8, 'b1>
and't2 = Foo<'a2, u16>
- 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
- 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
- So currently we are at the match arms return
Many<u8, u16, Foo<u8, u16>, Foo<u8, u16>, 't3>
- 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…