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:
- 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…
I've recently come across an issue of type inference that can be summed up like this:
returns
(playground)
I would have thought rustc could be able to infer the type for
T3asFoo<u8, u16>, through this procedure:Many<'a, 'b, 't1, 't2, 't3>with't1 = Foo<u8, 'b1>and't2 = Foo<'a2, u16>whereclause says't1: Trait<'a, 'b>, and we only have't1: Trait<u8, 'b1>, so we can unify and get'a = u8and'b = 'b1whereclause also says't2: Trait<'a, 'b>, and we only have't2: Trait<'a2, u16>, so we can unify and get'a = 'a2and'b = u16Many<u8, u16, Foo<u8, u16>, Foo<u8, u16>, 't3>'t3gives't3 = Foo<u8, u16>, which is what I'm hoping forIn 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…