Re:Things you can’t do in Rust (and what to do instead)
by devit on Saturday May 15, 2021 @05:17PM
(#27169113)
Use a crate that provides safe functions implemented with unsafe code to do that, like https://docs.rs/splitmut/0.2.1/splitmut/
Re:Things you can’t do in Rust (and what to do instead)
by oconnor663 on Saturday May 15, 2021 @06:43PM
(#27169654)
Neat! I bet we could add a macro to that crate to make it work with any (static) number of references. A variant of this using a HashSet to check arbitrary collections of keys might be cool too.
Getting multiple mutable references into a single container is tricky in Rust, because you (usually) have to statically guarantee that they don't alias, and how to do that depends on what container you're using. The suggestion in the error message is correct here, and `split_at_mut` is one of our options. Using it would look like this:
However, other containers like HashMap don't have `split_at_mut`, and taking two mutable references into e.g. a `HashMap<i32, i32>` would require a different approach. Refactoring our code to hold i32 keys instead of references would be the best option in that case, though it might mean paying for extra lookups. If we couldn't do that, we might have to resort to `Rc<RefCell<i32>>` or trickery with iterators. (This comment is too long already, and I'll spare the gory details.)At a high level, Rust's attitude towards multiple-mutable-references situations is leaning in the direction of "don't do that". There are definitely ways to do it (assuming what you're doing is in fact sound, and you're not actually trying to break the aliasing rule), but many of those ways are advanced and/or not-zero-cost, and in extremis it can require unsafe code. Life in Rust is a lot easier when you refactor things to avoid needing to do this, for example with an entity-component-system sort of architecture.