Skip to content

Commit 9ed0bf9

Browse files
committed
Auto merge of #99223 - saethlin:panicless-split-mut, r=Mark-Simulacrum
Rearrange slice::split_mut to remove bounds check Closes #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.
2 parents 8804161 + c937390 commit 9ed0bf9

File tree

1 file changed

+9
-10
lines changed

1 file changed

+9
-10
lines changed

Diff for: library/core/src/slice/iter.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -710,18 +710,17 @@ where
710710
return None;
711711
}
712712

713-
let idx_opt = {
714-
// work around borrowck limitations
715-
let pred = &mut self.pred;
716-
self.v.iter().position(|x| (*pred)(x))
717-
};
718-
match idx_opt {
713+
match self.v.iter().position(|x| (self.pred)(x)) {
719714
None => self.finish(),
720715
Some(idx) => {
721-
let tmp = mem::replace(&mut self.v, &mut []);
722-
let (head, tail) = tmp.split_at_mut(idx);
723-
self.v = &mut tail[1..];
724-
Some(head)
716+
let tmp = mem::take(&mut self.v);
717+
// idx is the index of the element we are splitting on. We want to set self to the
718+
// region after idx, and return the subslice before and not including idx.
719+
// So first we split after idx
720+
let (head, tail) = tmp.split_at_mut(idx + 1);
721+
self.v = tail;
722+
// Then return the subslice up to but not including the found element
723+
Some(&mut head[..idx])
725724
}
726725
}
727726
}

0 commit comments

Comments
 (0)