Commit 5293bde
committed
[stdlib] Collection: simplify default _failEarlyRangeCheck implementations
Currently, the default implementations of the various `_failEarlyRangeCheck` forms contain several _precondition invocations, like this:
```
@inlinable
public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
_precondition(
bounds.lowerBound <= index,
"Out of bounds: index < startIndex")
_precondition(
index < bounds.upperBound,
"Out of bounds: index >= endIndex")
}
```
Each such precondition call generates a separate trap instruction, which seems like a waste — theoretically it would be helpful to know which condition was violated, but in practice, that information tends not to be surfaced anyway. Combining these will lead to a minuscule code size improvement.
(The separate messages do surface these in debug builds, but only if these generic defaults actually execute, which isn’t often. These are not public entry points, so concrete collection types tend ignore these and roll their own custom index validation instead. From what I’ve seen, custom code tends to combine the upper/lower checks into a single precondition check. These underscored requirements tend to be only called by the standard `Slice`; and it seems reasonable for that to follow suit.)
More interestingly, the range-in-range version of `_failEarlyRangeCheck` performs two times as many checks than are necessary:
```
@inlinable
public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
_precondition(
bounds.lowerBound <= range.lowerBound,
"Out of bounds: range begins before startIndex")
_precondition(
range.lowerBound <= bounds.upperBound,
"Out of bounds: range ends after endIndex")
_precondition(
bounds.lowerBound <= range.upperBound,
"Out of bounds: range ends before bounds.lowerBound")
_precondition(
range.upperBound <= bounds.upperBound,
"Out of bounds: range begins after bounds.upperBound")
}
```
It is safe to assume that `range.lowerBound <= range.upperBound`, so it’s enough to test that `bounds.lowerBound <= range.lowerBound && range.upperBound <= bounds.upperBound` — we don’t need to check each combination separately.1 parent ac70bf7 commit 5293bde
1 file changed
+6
-20
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
712 | 712 | | |
713 | 713 | | |
714 | 714 | | |
715 | | - | |
716 | | - | |
717 | | - | |
718 | | - | |
719 | | - | |
| 715 | + | |
| 716 | + | |
720 | 717 | | |
721 | 718 | | |
722 | 719 | | |
723 | 720 | | |
724 | 721 | | |
725 | 722 | | |
726 | | - | |
727 | | - | |
728 | | - | |
729 | | - | |
730 | | - | |
| 723 | + | |
| 724 | + | |
731 | 725 | | |
732 | 726 | | |
733 | 727 | | |
734 | 728 | | |
735 | 729 | | |
736 | 730 | | |
737 | | - | |
738 | | - | |
739 | | - | |
740 | | - | |
741 | | - | |
742 | | - | |
743 | | - | |
744 | | - | |
745 | | - | |
| 731 | + | |
746 | 732 | | |
747 | | - | |
| 733 | + | |
748 | 734 | | |
749 | 735 | | |
750 | 736 | | |
| |||
0 commit comments