Skip to content

[stdlib] Unchecked subscript on UnsafeBufferPointer #20767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions stdlib/public/core/FixedArray.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ extension _FixedArray${N} : RandomAccessCollection, MutableCollection {
let bufPtr = UnsafeBufferPointer(
start: rawPtr.baseAddress!.assumingMemoryBound(to: T.self),
count: count)
return bufPtr[i]
return bufPtr[_unchecked: i]
}
return res
}
@inline(__always)
set {
_internalInvariant(i >= 0 && i < count)
self.withUnsafeMutableBufferPointer { buffer in
buffer[i] = newValue
buffer[_unchecked: i] = newValue
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/NormalizedCodeUnitIterator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ extension UnsafeBufferPointer where Element == UInt8 {
return true
}

assert(!_isContinuation(self[index]))
assert(!_isContinuation(self[_unchecked: index]))

let cu = _decodeScalar(self, startingAt: index).0
return cu._hasNormalizationBoundaryBefore
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/SmallBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ extension _SmallBuffer {
let rawPtr = $0.baseAddress._unsafelyUnwrappedUnchecked
let bufPtr = UnsafeBufferPointer(
start: rawPtr.assumingMemoryBound(to: T.self), count: capacity)
return bufPtr[i]
return bufPtr[_unchecked: i]
}
}
set {
Expand All @@ -61,7 +61,7 @@ extension _SmallBuffer {
let rawPtr = $0.baseAddress._unsafelyUnwrappedUnchecked
let bufPtr = UnsafeMutableBufferPointer(
start: rawPtr.assumingMemoryBound(to: T.self), count: capacity)
bufPtr[i] = newValue
bufPtr[_unchecked: i] = newValue
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/StringComparison.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,11 @@ internal func _stringCompare(

// Back up to nearest scalar boundary and check if normal and end of segment.
// If so, we have our answer.
while _isContinuation(left[idx]) && idx > 0 { idx &-= 1 }
while _isContinuation(left[_unchecked: idx]) && idx > 0 { idx &-= 1 }

// TODO: Refactor this into a function, handle these boundary condition as
// early returns...
if !_isContinuation(right[idx]) {
if !_isContinuation(right[_unchecked: idx]) {
let (leftScalar, leftLen) = _decodeScalar(left, startingAt: idx)
let (rightScalar, rightLen) = _decodeScalar(right, startingAt: idx)
_internalInvariant(leftScalar != rightScalar)
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/StringUTF16View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ extension String.UTF16View {
}

while true {
let len = _utf8ScalarLength(utf8[readIdx])
let len = _utf8ScalarLength(utf8[_unchecked: readIdx])
let utf16Len = len == 4 ? 2 : 1
utf16I &+= utf16Len

Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/StringUTF8View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ extension String.UTF8View: BidirectionalCollection {
@inline(__always) get {
String(_guts)._boundsCheck(i)
if _fastPath(_guts.isFastUTF8) {
return _guts.withFastUTF8 { utf8 in utf8[i.encodedOffset] }
return _guts.withFastUTF8 { utf8 in utf8[_unchecked: i.encodedOffset] }
}

return _foreignSubscript(position: i)
Expand Down
18 changes: 12 additions & 6 deletions stdlib/public/core/UnicodeHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,20 @@ internal func _decodeUTF8(
internal func _decodeScalar(
_ utf8: UnsafeBufferPointer<UInt8>, startingAt i: Int
) -> (Unicode.Scalar, scalarLength: Int) {
let cu0 = utf8[i]
let cu0 = utf8[_unchecked: i]
let len = _utf8ScalarLength(cu0)
switch len {
case 1: return (_decodeUTF8(cu0), len)
case 2: return (_decodeUTF8(cu0, utf8[i &+ 1]), len)
case 3: return (_decodeUTF8(cu0, utf8[i &+ 1], utf8[i &+ 2]), len)
case 2: return (_decodeUTF8(cu0, utf8[_unchecked: i &+ 1]), len)
case 3: return (_decodeUTF8(
cu0, utf8[_unchecked: i &+ 1], utf8[_unchecked: i &+ 2]), len)
case 4:
return (_decodeUTF8(cu0, utf8[i &+ 1], utf8[i &+ 2], utf8[i &+ 3]), len)
return (_decodeUTF8(
cu0,
utf8[_unchecked: i &+ 1],
utf8[_unchecked: i &+ 2],
utf8[_unchecked: i &+ 3]),
len)
default: Builtin.unreachable()
}
}
Expand Down Expand Up @@ -123,7 +129,7 @@ internal func _utf8ScalarLength(
_ utf8: UnsafeBufferPointer<UInt8>, endingAt i: Int
) -> Int {
var len = 1
while _isContinuation(utf8[i &- len]) {
while _isContinuation(utf8[_unchecked: i &- len]) {
len += 1
}
_internalInvariant(len == _utf8ScalarLength(utf8[i &- len]))
Expand Down Expand Up @@ -187,7 +193,7 @@ extension _StringGuts {

return self.withFastUTF8 { utf8 in
var i = idx.encodedOffset
while _slowPath(_isContinuation(utf8[i])) {
while _slowPath(_isContinuation(utf8[_unchecked: i])) {
i -= 1
_internalInvariant(
i >= 0, "Malformed contents: starts with continuation byte")
Expand Down
17 changes: 17 additions & 0 deletions stdlib/public/core/UnsafeBufferPointer.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,23 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
%end
}

// Skip all debug and runtime checks
@inlinable // unsafe-performance
internal subscript(_unchecked i: Int) -> Element {
get {
_internalInvariant(i >= 0)
_internalInvariant(i < endIndex)
return _position._unsafelyUnwrappedUnchecked[i]
}
%if Mutable:
nonmutating _modify {
_internalInvariant(i >= 0)
_internalInvariant(i < endIndex)
yield &_position._unsafelyUnwrappedUnchecked[i]
}
%end
}

/// Accesses a contiguous subrange of the buffer's elements.
///
/// The accessed slice uses the same indices for the same elements as the
Expand Down