In short, I want Index<&Q>
and Index<Idx>
for IndexMap
, but I can't find a way to constrain this to convince the compiler that they are distinct. Since &T
is fundamental, and we don't have negative impls, maybe it's just not possible.
For IndexMap<K, V, S>
, we currently have a few indexing methods, roughly:
impl<K, V, S> IndexMap<K, V, S> {
pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
where
Q: Hash + Equivalent<K>;
pub fn get_index(&self, index: usize) -> Option<(&K, &V)>;
}
impl<'a, K, V, Q: ?Sized, S> Index<&'a Q> for IndexMap<K, V, S>
where
Q: Hash + Equivalent<K>,
K: Hash + Eq,
S: BuildHasher,
{
type Output = V;
fn index(&self, key: &'a Q) -> &V;
}
I would like to add Index<usize>
too, and this seems OK:
impl<K, V, S> Index<usize> for IndexMap<K, V, S> {
type Output = V;
fn index(&self, index: usize) -> &V;
}
But going even further, I would like to make the index type generic, both in the API and how we store it in the data structure. For example, rustc
often uses u32
indexes for its data types that it asserts will never get too big for that.
So, add a parameter IndexMap<K, V, S, Idx>
and use that instead of usize
everywhere, e.g.:
trait AsIndex { ... }
impl<K, V, S, Idx: AsIndex> Index<Idx> for IndexMap<K, V, S, Idx> {
type Output = V;
fn index(&self, index: Idx) -> &V;
}
Now the compiler says this conflicts with Index<&Q>
, because Idx
could be a reference itself. Is there any way I can constrain these to make them definitely distinct?
Here's a simplified playground.