Skip to content

Commit 9cb3641

Browse files
authored
Remove checks in UR[M]BP.Iterator.next() (#62965)
Swift tends to emit unnecessary checks and traps when iterating unsafe raw buffer pointers. These traps are confirming that the position pointer isn't nil, but this check is redundant with the bounds check that is already present. We can safely remove it.
1 parent 700bcb4 commit 9cb3641

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

stdlib/public/core/UnsafeRawBufferPointer.swift.gyb

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,21 @@ extension UnsafeRawBufferPointer.Iterator: IteratorProtocol, Sequence {
148148
public mutating func next() -> UInt8? {
149149
if _position == _end { return nil }
150150

151-
let result = _position!.load(as: UInt8.self)
152-
_position! += 1
151+
// We can do an unchecked unwrap here by borrowing invariants from the pointer.
152+
// For a validly constructed buffer pointer, the only way _position can be nil is
153+
// if _end is also nil. We checked that case above. Thus, we can safely do an
154+
// unchecked unwrap here.
155+
//
156+
// Additionally, validly constructed buffer pointers also have an _end that is
157+
// strictly greater than or equal to _position, and so we do not need to do checked
158+
// arithmetic here as we cannot possibly overflow.
159+
//
160+
// We check these invariants in debug builds to defend against invalidly constructed
161+
// pointers.
162+
_debugPrecondition(_position! < _end!)
163+
let position = _position._unsafelyUnwrappedUnchecked
164+
let result = position.load(as: UInt8.self)
165+
_position = position + 1
153166
return result
154167
}
155168
}

0 commit comments

Comments
 (0)