I have a generic enum:
enum E<T> {
NeverForTuple(T),
TisTupleVariant1(T),
TisTupleVariant2(T),
}
and I know from context that E<T>
instances will always be TisTupleVariant1
or TisTupleVariant1
, if T
is a two-element tuple (T
= (A, B)
). I am using a tuple here to avoid making E
generic over two types A
and B
.
Now I define two functions bar1
and bar2
, where bar1
takes any E<T>
instance as an argument, and bar2
only works on E<(A, B)>
instances.
// bar1 takes any E<T> instance
fn bar1<T>(_: E<T>) {}
// bar2 only takes E instances over two-element tuples
fn bar2<A, B>(_: E<(A, B)>) {}
Finally, I have a third function foo
that delegates to bar1
or bar2
depending on the variant:
fn foo<T>(e: E<T>) {
match e {
E::NeverForTuple(_) => bar1(e),
_ => bar2(e),
}
}
The compiler will complain:
error[E0308]: mismatched types
--> <source>:24:19
|
21 | fn foo<T>(e: E<T>){
| - this type parameter
...
24 | _ => bar2(e),
| ^ expected tuple, found type parameter `T`
|
= note: expected enum `E<(_, _)>`
found enum `E<T>`
Here is the playground link.
- Coming from C++, I would have assumed that
foo
would get monomorphized forT
=(A, B)
just by existence ofbar2
and the code would work. Why is this not true? - Is there a way to get my code to compile without the
specialization
ormin_specialization
features?
Finally, in order to avoid giving an xy-problem, here is a less contrived example of what I am trying to achieve. Uncommenting line 115 will give the same compiler error. I want to implement the fold pattern for generic expressions as an exercise and follow-up to Expression template implementation in Rust like in boost::yap.