[stdlib] annotate uses of Range.init(_uncheckedBounds:)

This commit is contained in:
Guillaume Lessard
2025-03-05 18:52:11 -08:00
parent eed9c46116
commit dfb2e2f12e
14 changed files with 58 additions and 44 deletions

View File

@@ -90,7 +90,9 @@ public struct ClosedRange<Bound: Comparable> {
public init(uncheckedBounds bounds: (lower: Bound, upper: Bound)) {
_debugPrecondition(bounds.lower <= bounds.upper,
"ClosedRange requires lowerBound <= upperBound")
self.init(_uncheckedBounds: (lower: bounds.lower, upper: bounds.upper))
unsafe self.init(
_uncheckedBounds: (lower: bounds.lower, upper: bounds.upper)
)
}
}
@@ -110,7 +112,7 @@ extension ClosedRange: RangeExpression {
@inlinable // trivial-implementation
public func relative<C: Collection>(to collection: C) -> Range<Bound>
where C.Index == Bound {
return Range(
return unsafe Range(
_uncheckedBounds: (
lower: lowerBound,
upper: collection.index(after: self.upperBound)))
@@ -406,7 +408,7 @@ extension Comparable {
public static func ... (minimum: Self, maximum: Self) -> ClosedRange<Self> {
_precondition(
minimum <= maximum, "Range requires lowerBound <= upperBound")
return ClosedRange(_uncheckedBounds: (lower: minimum, upper: maximum))
return unsafe ClosedRange(_uncheckedBounds: (lower: minimum, upper: maximum))
}
}
@@ -497,7 +499,7 @@ extension ClosedRange {
limits.upperBound < self.upperBound ? limits.upperBound
: limits.lowerBound > self.upperBound ? limits.lowerBound
: self.upperBound
return ClosedRange(_uncheckedBounds: (lower: lower, upper: upper))
return unsafe ClosedRange(_uncheckedBounds: (lower: lower, upper: upper))
}
}
@@ -513,7 +515,9 @@ extension ClosedRange where Bound: Strideable, Bound.Stride: SignedInteger {
public init(_ other: Range<Bound>) {
_precondition(!other.isEmpty, "Can't form an empty closed range")
let upperBound = other.upperBound.advanced(by: -1)
self.init(_uncheckedBounds: (lower: other.lowerBound, upper: upperBound))
unsafe self.init(
_uncheckedBounds: (lower: other.lowerBound, upper: upperBound)
)
}
}
@@ -582,7 +586,7 @@ extension ClosedRange: Decodable where Bound: Decodable {
codingPath: decoder.codingPath,
debugDescription: "Cannot initialize \(ClosedRange.self) with a lowerBound (\(lowerBound)) greater than upperBound (\(upperBound))"))
}
self.init(_uncheckedBounds: (lower: lowerBound, upper: upperBound))
unsafe self.init(_uncheckedBounds: (lower: lowerBound, upper: upperBound))
}
}

View File

@@ -294,7 +294,7 @@ extension InlineArray where Element: ~Copyable {
@_alwaysEmitIntoClient
@_transparent
public var indices: Range<Int> {
Range(_uncheckedBounds: (0, count))
unsafe Range(_uncheckedBounds: (0, count))
}
/// Returns the position immediately after the given index.

View File

@@ -179,7 +179,9 @@ public struct Range<Bound: Comparable> {
public init(uncheckedBounds bounds: (lower: Bound, upper: Bound)) {
_debugPrecondition(bounds.lower <= bounds.upper,
"Range requires lowerBound <= upperBound")
self.init(_uncheckedBounds: (lower: bounds.lower, upper: bounds.upper))
unsafe self.init(
_uncheckedBounds: (lower: bounds.lower, upper: bounds.upper)
)
}
/// Returns a Boolean value indicating whether the given element is contained
@@ -322,7 +324,9 @@ extension Range where Bound: Strideable, Bound.Stride: SignedInteger {
@inlinable // trivial-implementation
public init(_ other: ClosedRange<Bound>) {
let upperBound = other.upperBound.advanced(by: 1)
self.init(_uncheckedBounds: (lower: other.lowerBound, upper: upperBound))
unsafe self.init(
_uncheckedBounds: (lower: other.lowerBound, upper: upperBound)
)
}
}
@@ -373,7 +377,7 @@ extension Range {
limits.upperBound < self.upperBound ? limits.upperBound
: limits.lowerBound > self.upperBound ? limits.lowerBound
: self.upperBound
return Range(_uncheckedBounds: (lower: lower, upper: upper))
return unsafe Range(_uncheckedBounds: (lower: lower, upper: upper))
}
}
@@ -454,7 +458,7 @@ extension Range: Decodable where Bound: Decodable {
codingPath: decoder.codingPath,
debugDescription: "Cannot initialize \(Range.self) with a lowerBound (\(lowerBound)) greater than upperBound (\(upperBound))"))
}
self.init(_uncheckedBounds: (lower: lowerBound, upper: upperBound))
unsafe self.init(_uncheckedBounds: (lower: lowerBound, upper: upperBound))
}
}
@@ -755,7 +759,7 @@ extension Comparable {
public static func ..< (minimum: Self, maximum: Self) -> Range<Self> {
_precondition(minimum <= maximum,
"Range requires lowerBound <= upperBound")
return Range(_uncheckedBounds: (lower: minimum, upper: maximum))
return unsafe Range(_uncheckedBounds: (lower: minimum, upper: maximum))
}
/// Returns a partial range up to, but not including, its upper bound.
@@ -1124,7 +1128,7 @@ extension Range where Bound == String.Index {
_internalInvariant(
(lowerBound._canBeUTF8 && upperBound._canBeUTF8)
|| (lowerBound._canBeUTF16 && upperBound._canBeUTF16))
return Range<Int>(
return unsafe Range<Int>(
_uncheckedBounds: (lowerBound._encodedOffset, upperBound._encodedOffset))
}
}

View File

@@ -138,7 +138,7 @@ public struct Slice<Base: Collection> {
@_alwaysEmitIntoClient @inline(__always)
internal var _bounds: Range<Base.Index> {
Range(_uncheckedBounds: (_startIndex, _endIndex))
unsafe Range(_uncheckedBounds: (_startIndex, _endIndex))
}
}

View File

@@ -322,7 +322,7 @@ extension RawSpan {
/// - Complexity: O(1)
@_alwaysEmitIntoClient
public var byteOffsets: Range<Int> {
.init(_uncheckedBounds: (0, byteCount))
unsafe Range(_uncheckedBounds: (0, byteCount))
}
}
@@ -629,13 +629,13 @@ extension RawSpan {
public func byteOffsets(of other: borrowing Self) -> Range<Int>? {
if other._count > _count { return nil }
guard let spanStart = other._pointer, _count > 0 else {
return unsafe _pointer == other._pointer ? Range(_uncheckedBounds: (0, 0)) : nil
return unsafe _pointer == other._pointer ? 0..<0 : nil
}
let start = _start()
let spanEnd = unsafe spanStart + other._count
if unsafe spanStart < start || (start + _count) < spanEnd { return nil }
let lower = unsafe start.distance(to: spanStart)
return Range(_uncheckedBounds: (lower, lower &+ other._count))
return unsafe Range(_uncheckedBounds: (lower, lower &+ other._count))
}
}

View File

@@ -395,7 +395,7 @@ extension Span where Element: ~Copyable {
/// - Complexity: O(1)
@_alwaysEmitIntoClient
public var indices: Range<Index> {
Range(_uncheckedBounds: (0, _count))
unsafe Range(_uncheckedBounds: (0, _count))
}
}
@@ -679,7 +679,7 @@ extension Span where Element: ~Copyable {
public func indices(of other: borrowing Self) -> Range<Index>? {
if other._count > _count { return nil }
guard let spanStart = other._pointer, _count > 0 else {
return unsafe _pointer == other._pointer ? Range(_uncheckedBounds: (0, 0)) : nil
return unsafe _pointer == other._pointer ? 0..<0 : nil
}
let start = _start()
let stride = MemoryLayout<Element>.stride
@@ -688,7 +688,7 @@ extension Span where Element: ~Copyable {
let byteOffset = unsafe start.distance(to: spanStart)
let (lower, r) = byteOffset.quotientAndRemainder(dividingBy: stride)
guard r == 0 else { return nil }
return Range(_uncheckedBounds: (lower, lower &+ other._count))
return unsafe Range(_uncheckedBounds: (lower, lower &+ other._count))
}
}

View File

@@ -599,7 +599,7 @@ extension Unicode {
while i < buffer.endIndex {
let (next, n) = unsafe _decodeScalar(buffer, startingAt: i)
if hasBreak(before: next) {
return Range(_uncheckedBounds: (i, i &+ n))
return unsafe Range(_uncheckedBounds: (i, i &+ n))
}
i &+= n
}

View File

@@ -367,7 +367,7 @@ extension _StringGuts {
let j = result._guts.count
result.append(contentsOf: selfStr[bounds.upperBound...])
self = result._guts
return Range(_uncheckedBounds: (i, j))
return unsafe Range(_uncheckedBounds: (i, j))
}
// - Returns: The encoded offset range of the replaced contents in the result.
@@ -421,7 +421,7 @@ extension _StringGuts {
let j = result._guts.count
result.append(contentsOf: selfStr[bounds.upperBound...])
self = result._guts
return Range(_uncheckedBounds: (i, j))
return unsafe Range(_uncheckedBounds: (i, j))
}
// - Returns: The encoded offset range of the replaced contents in the result.
@@ -443,7 +443,7 @@ extension _StringGuts {
updateNativeStorage {
unsafe $0.replace(from: start, to: end, with: codeUnits)
}
return Range(_uncheckedBounds: (start, start + codeUnits.count))
return unsafe Range(_uncheckedBounds: (start, start + codeUnits.count))
}
// - Returns: The encoded offset range of the replaced contents in the result.
@@ -468,7 +468,7 @@ extension _StringGuts {
$0.replace(
from: start, to: end, with: codeUnits, replacementCount: replCount)
}
return Range(_uncheckedBounds: (start, start + replCount))
return unsafe Range(_uncheckedBounds: (start, start + replCount))
}
/// Run `body` to mutate the given `subrange` of this string within
@@ -540,9 +540,9 @@ extension _StringGuts {
let oldRange = subrange._encodedOffsetRange
let newRange = body(&self)
let oldBounds = Range(
let oldBounds = unsafe Range(
_uncheckedBounds: (startIndex._encodedOffset, endIndex._encodedOffset))
let newBounds = Range(_uncheckedBounds: (
let newBounds = unsafe Range(_uncheckedBounds: (
oldBounds.lowerBound,
oldBounds.upperBound &+ newRange.count &- oldRange.count))

View File

@@ -24,7 +24,7 @@ internal struct _StringGutsSlice {
@inline(__always)
internal init(_ guts: _StringGuts) {
self._guts = guts
self._offsetRange = Range(_uncheckedBounds: (0, guts.count))
self._offsetRange = unsafe Range(_uncheckedBounds: (0, guts.count))
}
@inline(__always)
@@ -74,7 +74,7 @@ internal struct _StringGutsSlice {
._scalarAligned
let higher = String.Index(_encodedOffset: _offsetRange.upperBound)
._scalarAligned
return Range(_uncheckedBounds: (lower, higher))
return unsafe Range(_uncheckedBounds: (lower, higher))
}
}

View File

@@ -80,7 +80,7 @@ extension _StringGuts {
_precondition(upper <= endIndex && lower <= upper,
"String index range is out of bounds")
return Range(_uncheckedBounds: (lower, upper))
return unsafe Range(_uncheckedBounds: (lower, upper))
}
@_alwaysEmitIntoClient
@@ -102,7 +102,7 @@ extension _StringGuts {
&& upper <= bounds.upperBound,
"Substring index range is out of bounds")
return Range(_uncheckedBounds: (lower, upper))
return unsafe Range(_uncheckedBounds: (lower, upper))
}
}
@@ -213,7 +213,7 @@ extension _StringGuts {
}
let r = validateSubscalarRange(range)
return Range(
return unsafe Range(
_uncheckedBounds: (scalarAlign(r.lowerBound), scalarAlign(r.upperBound)))
}
@@ -243,7 +243,7 @@ extension _StringGuts {
let r = validateSubscalarRange(range, in: bounds)
let upper = scalarAlign(r.upperBound)
let lower = scalarAlign(r.lowerBound)
return Range(_uncheckedBounds: (lower, upper))
return unsafe Range(_uncheckedBounds: (lower, upper))
}
}
@@ -356,7 +356,7 @@ extension _StringGuts {
_precondition(upper <= endIndex && lower <= upper,
"String index range is out of bounds")
return Range(_uncheckedBounds: (lower, upper))
return unsafe Range(_uncheckedBounds: (lower, upper))
}
/// A version of `validateScalarRange` that only traps if the main executable
@@ -377,7 +377,7 @@ extension _StringGuts {
}
let r = validateSubscalarRange_5_7(range)
return Range(
return unsafe Range(
_uncheckedBounds: (scalarAlign(r.lowerBound), scalarAlign(r.upperBound)))
}

View File

@@ -153,7 +153,9 @@ extension StringProtocol {
let end = endIndex
_internalInvariant(
start.transcodedOffset == 0 && end.transcodedOffset == 0)
return Range(_uncheckedBounds: (start._encodedOffset, end._encodedOffset))
return unsafe Range(
_uncheckedBounds: (start._encodedOffset, end._encodedOffset)
)
}
}

View File

@@ -218,7 +218,7 @@ extension String: RangeReplaceableCollection {
/// - Complexity: O(*n*), where *n* is the length of the string.
public mutating func insert(_ newElement: Character, at i: Index) {
let i = _guts.validateInclusiveScalarIndex(i)
let range = Range(_uncheckedBounds: (i, i))
let range = unsafe Range(_uncheckedBounds: (i, i))
_guts.replaceSubrange(range, with: newElement._str)
}
@@ -243,7 +243,7 @@ extension String: RangeReplaceableCollection {
contentsOf newElements: S, at i: Index
) where S.Element == Character {
let i = _guts.validateInclusiveScalarIndex(i)
let range = Range(_uncheckedBounds: (i, i))
let range = unsafe Range(_uncheckedBounds: (i, i))
_guts.replaceSubrange(range, with: newElements)
}

View File

@@ -54,7 +54,7 @@ extension _AbstractStringStorage {
_precondition(aRange.location + aRange.length <= Int(count),
"Range out of bounds")
let range = Range(
let range = unsafe Range(
_uncheckedBounds: (aRange.location, aRange.location+aRange.length))
let str = asString
unsafe str._copyUTF16CodeUnits(

View File

@@ -621,7 +621,9 @@ extension Substring: CustomDebugStringConvertible {
extension Substring: LosslessStringConvertible {
public init(_ content: String) {
let range = Range(_uncheckedBounds: (content.startIndex, content.endIndex))
let range = unsafe Range(
_uncheckedBounds: (content.startIndex, content.endIndex)
)
self.init(_unchecked: Slice(base: content, bounds: range))
}
}
@@ -767,7 +769,7 @@ extension Substring {
// scalar aligned.
let lower = content._wholeGuts.scalarAlign(content.startIndex)
let upper = content._wholeGuts.scalarAlign(content.endIndex)
let bounds = Range(_uncheckedBounds: (lower, upper))
let bounds = unsafe Range(_uncheckedBounds: (lower, upper))
self.init(_unchecked: content._wholeGuts, bounds: bounds)
}
}
@@ -922,7 +924,7 @@ extension Substring {
// scalar aligned.
let lower = content._wholeGuts.scalarAlign(content.startIndex)
let upper = content._wholeGuts.scalarAlign(content.endIndex)
let bounds = Range(_uncheckedBounds: (lower, upper))
let bounds = unsafe Range(_uncheckedBounds: (lower, upper))
self.init(_unchecked: content._wholeGuts, bounds: bounds)
}
}
@@ -965,7 +967,9 @@ extension Substring {
internal init(_ base: String.UnicodeScalarView, _bounds: Range<Index>) {
let start = base._guts.scalarAlign(_bounds.lowerBound)
let end = base._guts.scalarAlign(_bounds.upperBound)
_slice = Slice(base: base, bounds: Range(_uncheckedBounds: (start, end)))
_slice = Slice(
base: base, bounds: unsafe Range(_uncheckedBounds: (start, end))
)
}
}
}
@@ -1233,7 +1237,7 @@ extension String {
// we don't need to compare against the `endIndex` -- those aren't nearly as
// critical.
if r.lowerBound._encodedOffset == 0 {
r = Range(_uncheckedBounds:
r = unsafe Range(_uncheckedBounds:
(r.lowerBound._characterAligned, r.upperBound))
}