This is trivial to do for non-mut slices since they are covariant, but the invariance of &mut slices is making what looks like a simple operation a little hard.
Say, I have:
struct Foo<'a> {
bar: &'a mut [Bar],
}
impl<'a> Foo<'a> {
fn update_and_pop_front(&mut self, bar: Bar) {
if let [first, bars @ ..] = self.bars {
*first = bars;
// Cannot compile since we effectively have `&mut &mut [Bar]` and the lifetime
// of `bars` is tied to the outer `&` as well.
self.bars = bars;
} else {
panic!("Updating a non-existing element.");
}
}
}
(Edit: Sorry, I had selections instead of bars in various places. I neglected to rename all of them when making my min example. For those looking at some of the answers below, that's why some of them mention selection.)
Conceptually, though, self.bar is a pointer and size to mutable data, and I just want to move the pointer forward as long as the size is positive, which doesn't seem unsound. Any insights as to whether something like this can be done in safe rust?
Yes, I get that I could use an index as a workaround:
struct Foo<'a> {
bar: &'a mut [Bar],
index: usize,
}
and move index forward instead of shrinking the slice. But I was wondering whether the case above is possible.
This works:
struct Foo<'a> {
bar: &'a mut [Bar],
}
impl<'a> Foo<'a> {
fn update_and_pop_front(&mut self, replacement: Bar) {
let bar = mem::take(&mut self.bar);
let (head, tail) = bar.split_first_mut().expect("empty");
*head = replacement;
self.bar = tail;
}
}
If you want to do it yourself, you need to get the &mut [_] out from underneath &mut self temporarily.
fn update_and_pop_front(&mut self, bar: Bar) {
let slice = std::mem::take(&mut self.selections);
if let [first, selections @ ..] = slice {
*first = bar;
self.selections = selections;
} else {
panic!("Updating a non-existing element.");
}
}
See this walkthrough of a &mut slice iterator for more of a long-form explanation.
There is a caveat here if Bar (or any piece of it) implements Drop -- if that panics while dropping the original *first, you'll be leaving self.selections empty. So just to be safe, I would swap these lines.
That was what I meant in the footnote
.
Ah, that was too hidden for me to notice. 
Ha, thank you all so much! I totally forgot that &mut[] implements Default. I recall thinking, "well, if only I could swap it with a temporary value" but failed to consider that I actually can.
And thanks for the subtle note about drop panicking.
And thanks, cuviper for the split_off_first_mut reference. I didn't think to look for that name - I was looking for something like pop_front() instead.
Also: Sorry, I messed up my question by not renaming all the selections to bar when composing my minimal example for the question. I've edited my original question to use bar consistently everywhere.