`Key` trait (`Borrow` replacement for collections)


#1

I want a Key trait.

The Key trait would be kind of a mirror of the Borrow trait, but it would live in std::collections::Key.

Since &'a T can also be represented in an hypothetical Borrowed type as Borrowed<'a, T>, that’s exactly what we do here. This allows huge amounts of flexibility.

Here’s an example Key :

https://play.rust-lang.org/?gist=09dcd65070498868a11e5d379d90e9a8&version=stable&mode=debug

This could also be #[derive]'d, e.g.

#[derive(Eq, PartialEq, Hash, Key=MyKey)]
struct MyStruct(String, u8);
#[derive(Eq, PartialEq, Hash)]
struct MyKey<'a>(&'a str, &'a u8); // need the & and only a single lifetime if we wanna use derive, I think

This would be extremely useful for some keys. Indeed, (String, u8) is not hypothetical.

(This is not to be confused with “raw entry API”. I don’t want “raw entry API” I just want HashMap.get to be better/more useful with custom key types. No, Cow<'a, str> doesn’t work, I tried it and you just can’t move the map around (e.g. return it from a function) at all.)


#2

I think a good first step would be instead to impl Borrow<(&T, &U, …)> for (T, U, …) in the standard library. (I just went to check if that is already done, but apparently it isn’t, which surprises me.)


#3

You can’t do that. Borrow turns T into &U, e.g. String into &str.

It needs to put out an &.

And you can’t have &(&str) for (String) or w/e

let s = (String::new(), 0u8);
let b: &(&str, &u8) = &(&s.0, &s.1);

This is what your borrow would have to do.


#4

Right, I somehow missed that.