omniswap: a crate to swap values between possibly-overlapping references
Motivating Example
You cannot simply use std::mem::swap to replace values within an array:
let mut a = ;
// You cannot prove their disjointness!
swap;
You get the following message:
error[E0499]: cannot borrow `a[_]` as mutable more than once at a time
--> src/main.rs:4:31
|
4 | std::mem::swap(&mut a[0], &mut a[2]);
| -------------- --------- ^^^^^^^^^ second mutable borrow occurs here
| | |
| | first mutable borrow occurs here
| first borrow later used by call
|
= help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
You can use the dedicated <[T]>::swap instead:
let mut a = ;
a.swap;
But how about two-dimensional arrays?
let mut a = ;
// You cannot prove their disjointness!
swap;
This is not as simple as the first one.
Solution
This crate solves the problem by providing a generic framework for sentinel-based swapping.
The idea is simple: it leaves a dummy value behind to safely move values around:
let mut a = ;
let tmp = replace;
let tmp = replace;
a = tmp;
# assert_eq!;
However, in Rust, the best sentinel value differs between types.
The macro swap! automatically chooses the best sentinel and
provides the same interface as std::mem::swap:
let mut a = ;
swap!;
# assert_eq!;
Usage
Simply use swap! where you want to use std::mem::swap:
let mut x = 42;
let mut y = 84;
swap!;
See swap! for detailed usages.
Other APIs
The crate provides the following variants:
rotate!-- swaps more than two values at once
The crate also exposes take! and Replace.
These are primitives used in swap! and rotate!.