Alternative to equality constraints for associated types
I'm trying to write this in Rust:
trait Foo {
type T: PartialEq;
fn get_t(&self) -> Self::T;
}
struct Bar<F1: Foo, F2: Foo> {
f1: F1,
f2: F2,
}
impl<F1: Foo, F2: Foo> Bar<F1, F2> {
fn test_eq(&self) -> bool {
self.f1.get_t() == self.f2.get_t()
}
}
It refuses to compile, because F1::T
might be different from F2::T
, rendering the equality meaningless. I'd like to be able to resolve that by writing this:
impl<F1: Foo, F2: Foo> Bar<F1, F2>
where
F1::T = F2::T
{
fn test_eq(&self) -> bool {
self.f1.get_t() == self.f2.get_t()
}
}
But that tells me that equality constraints are not yet supported and refers me to this issue. Since it's been open since late 2014, I suspect it's not a feature that's arriving any time soon.
I can do this, and it'll compile:
struct Bar<T: PartialEq, F1: Foo<T=T>, F2: Foo<T=T>> {
f1: F1,
f2: F2,
}
impl<T: PartialEq, F1: Foo<T=T>, F2: Foo<T=T>> Bar<T, F1, F2>
{
fn test_eq(&self) -> bool {
self.f1.get_t() == self.f2.get_t()
}
}
But then I'm adding an additional generic parameter to the struct Bar
. If Foo
has multiple associated types that I want to constrain in this manner, then it'll get a bit messy. My question is:
- Is this really the only way I can enforce this constraint, by making
Bar
'more generic' with the addition of the additional type parameterT
? - Is this the most idiomatic way of solving this?
Edit:
I realize I simplified my example too much. Suppose I actually have a Bar
that has an associated Baz
that has an associated Foo
that has an associated T
. That's bit of a mouthful, so here is the example:
trait Foo {
type T: PartialEq;
fn get_t(&self) -> Self::T;
}
trait Baz {
type F: Foo;
fn get_inner_t(&self) -> <Self::F as Foo>::T;
}
struct Bar<B1: Baz, B2: Baz> {
b1: B1,
b2: B2,
}
impl<B1: Baz, B2: Baz> Bar<B1, B2>
{
fn test_eq(&self) -> bool {
self.b1.get_inner_t() == self.b2.get_inner_t()
}
}
Of course it still doesn't compile because the T
s from get_inner_t
can differ. I do genuinely want to allow that the two Baz
s differ, and the Foo
s differ, but constrain their T
s to be the same.
I've tried to adapt the answer given, by writing
impl<B1: Baz, B2: Baz< <F as Foo>::T = B1::F::T >> Bar<B1, B2>
But that gives this compile error:
Compiling type_bindings v0.1.0 (/home/harry/coding/rust_sandbox/type_bindings)
error: expected one of `(`, `,`, `::`, `<`, or `>`, found `=`
--> src/main.rs:18:38
|
18 | impl<B1: Baz, B2: Baz< <F as Foo>::T = B1::F::T >> Bar<B1, B2>
| ^ expected one of `(`, `,`, `::`, `<`, or `>`
error: aborting due to previous error
error: could not compile `type_bindings`
To learn more, run the command again with --verbose.
If this multi-level extraction of associated types not permitted?
from Recent Questions - Stack Overflow https://ift.tt/2ZO4Yp6
https://ift.tt/eA8V8J
Comments
Post a Comment