mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 23:12:02 +00:00
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:
commit
9ed0bf9f2b
@ -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])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user