Skip to content

Implement Equivalent and Comparable for tuples#10

Closed
AnthonyMikh wants to merge 1 commit into
indexmap-rs:mainfrom
AnthonyMikh:tuple_impls
Closed

Implement Equivalent and Comparable for tuples#10
AnthonyMikh wants to merge 1 commit into
indexmap-rs:mainfrom
AnthonyMikh:tuple_impls

Conversation

@AnthonyMikh

Copy link
Copy Markdown

One of the reasons people reach out to hashbrown instead of HashMap from std is to be able to lookup in maps like HashMap<(String, String), Thing> using (&str, &str). However, in it's current form it requires some newtype boilerplate. This PR aims to fix it by providing impls which make tuples Equivalent and Comparable to other tuples if they are Equivalent/Comparable element-wise.

This will probably also need a corresponding PR to hashbrown repo as well for their fallback Equivalent definition.

Impls are included for tuples with arity up to 12 inclusive. The justification for this exact limit is prior art from std, which has the same limits.

I deliberately avoided defining recursive macro to lower the impact on compile times, but it can be changed (this crate is rarely compiled from scratch).

Includes impls up to arity 12, same as `Default` tuple imple in std
@cuviper

cuviper commented Feb 16, 2026

Copy link
Copy Markdown
Member

Did you try compiling this yourself? CI failed, and not just because of the ancient 1.6 -- stable fails too:

error[E0119]: conflicting implementations of trait `Equivalent<(_,)>` for type `(_,)`
   --> src/lib.rs:118:9
    |
 82 | / impl<Q: ?Sized, K: ?Sized> Equivalent<K> for Q
 83 | | where
 84 | |     Q: Eq,
 85 | |     K: Borrow<Q>,
    | |_________________- first implementation here
...
118 | /         impl<$($T1,)* $($T2,)*> Equivalent<($($T2,)*)> for ($($T1,)*)
119 | |         where
120 | |             $(
121 | |                 $T1: Eq,
122 | |                 $T2: Borrow<$T1>,
    | |_________________________________^ conflicting implementation for `(_,)`
...
157 |   tuple_impl!(A a);
    |   ---------------- in this macro invocation
    |
    = note: this error originates in the macro `tuple_impl` (in Nightly builds, run with -Z macro-backtrace for more info)

[etc]

In other words, the top-level blanket Equivalent<K> for Q conflicts with these, if only for the case where K and Q are the same tuple types.

This PR aims to fix it by providing impls which make tuples Equivalent and Comparable to other tuples if they are Equivalent/Comparable element-wise.

I would have expected where $($T1: Equivalent<$T2>,)* bounds for that, rather than the more restrictive Eq and Borrow again, but that still won't help the conflict above.

This will probably also need a corresponding PR to hashbrown repo as well for their fallback Equivalent definition.

Even if we found a way to make this work, I wouldn't bother with that, as folks could enable hashbrown/equivalent when they need the expanded implementations.

@AnthonyMikh

Copy link
Copy Markdown
Author

I can't see how to solve these overlapping impls without specialization. It's a dead end

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants