Auto merge of #99223 - saethlin:panicless-split-mut, r=Mark-Simulacrum

Rearrange slice::split_mut to remove bounds check

Closes https://github.com/rust-lang/rust/issues/86313

Turns out that all we need to do here is reorder the bounds checks to convince LLVM that all the bounds checks can be removed. It seems like LLVM just fails to propagate the original length information past the first bounds check and into the second one. With this implementation it doesn't need to, each check can be proven inbounds based on the one immediately previous.

I've gradually convinced myself that this implementation is unambiguously better based on the above logic, but maybe this is still deserving of a codegen test?

Also the mentioned borrowck limitation no longer seems to exist.
This commit is contained in:
bors 2022-07-18 10:16:58 +00:00
commit 9ed0bf9f2b

View File

@ -710,18 +710,17 @@ where
return None;
}
let idx_opt = {
// work around borrowck limitations
let pred = &mut self.pred;
self.v.iter().position(|x| (*pred)(x))
};
match idx_opt {
match self.v.iter().position(|x| (self.pred)(x)) {
None => self.finish(),
Some(idx) => {
let tmp = mem::replace(&mut self.v, &mut []);
let (head, tail) = tmp.split_at_mut(idx);
self.v = &mut tail[1..];
Some(head)
let tmp = mem::take(&mut self.v);
// idx is the index of the element we are splitting on. We want to set self to the
// region after idx, and return the subslice before and not including idx.
// So first we split after idx
let (head, tail) = tmp.split_at_mut(idx + 1);
self.v = tail;
// Then return the subslice up to but not including the found element
Some(&mut head[..idx])
}
}
}