indexmap icon indicating copy to clipboard operation
indexmap copied to clipboard

Implement get_many_mut

Open NiklasJonsson opened this issue 3 years ago • 5 comments

std::collections::HashMap is adding get_many_mut in https://github.com/rust-lang/rust/issues/97601 and I'm working on replacing some uses of that hash map with this one where some of the code uses get_many_mut (currently only a single location in rustc) so I would appreciate it if indexmap::IndexMap could provide the same interface.

This code uses a decent amount of unsafe compared to the rest of the file and I saw the comment in lib.rs on having almost all unsafe code in raw.rs but I couldn't figure out how to move parts of my implementation there as it is mostly dealing with initializing the array. I tried to use array::map to avoid all unsafe but couldn't quite get it to work with the lifetimes and the lambda.

If you want this change, I'll also write some docs.

NiklasJonsson avatar Jul 14 '22 19:07 NiklasJonsson

I think ideally we would want two things for this, especially the first:

  1. Stabilizing HashMap::get_many_mut so we can be sure to match that API as much as possible.
  2. Stabilizing <[T]>::get_many_mut (still new in rust-lang/rust#83608) to deal with all the unsafe aspects. We might also want to wrap that into our own get_many_index_mut, just like we have get_index and get_index_mut for slice-like indexing.

I tried to use array::map to avoid all unsafe but couldn't quite get it to work with the lifetimes and the lambda.

I suspect part of this is because you should be using a raw pointer to offset/index each of the elements, otherwise you have the main &mut [T] aliasing each of the &mut T you pull out while you're working. And of course, using raw pointers will still need unsafe to form the final references.

cuviper avatar Jul 15 '22 00:07 cuviper

Stabilizing HashMap::get_many_mut so we can be sure to match that API as much as possible.

Yeah, this makes a lot of sense. Is it okay to just leave the PR open until then?

Stabilizing <[T]>::get_many_mut

Haven't seen this before but it would indeed fit pretty well. It seems to have been open for quite a while without resolution though. Also, if they opt for a result-based return value, that'd not match the hashmap api (as it is now) so we'd have to do conversions in the implementation.

I suspect part of this is because you should be using a raw pointer to offset/index each of the elements, otherwise you have the main &mut [T] aliasing each of the &mut T you pull out while you're working. And of course, using raw pointers will still need unsafe to form the final references.

Yeah, exactly, the lambda captures the whole array lifetime mutably and can't be invoked multiple times. I did not consider pointer arithmetic though, I'll experiment a bit and see how it looks. Probably similar to the <[T]>::get_many_mut examples 🙂

NiklasJonsson avatar Jul 15 '22 12:07 NiklasJonsson

Is it okay to just leave the PR open until then?

Yeah, that's fine. I should probably make a label for this...

cuviper avatar Jul 15 '22 16:07 cuviper

I think ideally we would want two things for this, especially the first: Stabilizing HashMap::get_many_mut so we can be sure to match that API as much as possible.

Can IndexMap add it under a nightly or unstable opt-in cargo feature? Then people will have to opt in to breaking changes, and you can document that changes to this API won't result in a new major version.

(Or if you don't feel strongly, you can just make a new major release if the HashMap API changes for some reason.)

jyn514 avatar Jul 16 '22 13:07 jyn514

I don't like using nightly/unstable features, in part because it's an extra maintenance burden, but also because the feature may be opted-in on your behalf, arbitrarily deep in your dependency tree.

I'd rather not set us up for needing a semver bump either. If this is something that folks really need, let's apply that pressure on std stabilization. :)

cuviper avatar Jul 19 '22 00:07 cuviper