Skip to content

Commit 6bd528d

Browse files
committed
Upgrade a few more _debugPreconditions to _boundsCheckPrecondition
1 parent faa3b1a commit 6bd528d

File tree

7 files changed

+46
-21
lines changed

7 files changed

+46
-21
lines changed

docs/StandardLibraryProgrammersManual.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,11 +415,15 @@ return
415415
This should be rarely used. It informs the SIL optimizer that any code dominated by it should be treated as the innermost loop of a performance critical section of code. It cranks optimizer heuristics to 11. Injudicious use of this will degrade performance and bloat binary size.
416416
417417
418-
#### <a name="precondition"></a>`_precondition`, `_debugPrecondition`, and `_internalInvariant`
418+
#### <a name="precondition"></a>`_precondition`, `_debugPrecondition`, `_boundsCheckPrecondition`, and `_internalInvariant`
419419
420-
These three functions are assertions that will trigger a run time trap if violated.
420+
These four functions are assertions that will trigger a run time trap if violated.
421421
422422
* `_precondition` executes in all build configurations. Use this for invariant enforcement in all user code build configurations
423+
* `_boundsCheckPrecondition` executes in **used code** is built in either a debug build, or when the upcoming feature `UnsafePointerBoundsSafety`
424+
has been enabled. Use this only for `_debugPreconditions` that have
425+
historically only been `_debugPrecondition`, but are being updated
426+
for Swift 6.
423427
* `_debugPrecondition` will execute when **user code** is built with assertions enabled. Use this for invariant enforcement that's useful while debugging, but might be prohibitively expensive when user code is configured without assertions.
424428
* `_internalInvariant` will execute when **standard library code** is built with assertions enabled. Use this for internal only invariant checks that useful for debugging the standard library itself.
425429

stdlib/public/core/Character.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ extension Character :
174174
public init(_ s: String) {
175175
_precondition(!s.isEmpty,
176176
"Can't form a Character from an empty String")
177-
_debugPrecondition(s.index(after: s.startIndex) == s.endIndex,
177+
_boundsCheckPrecondition(s.index(after: s.startIndex) == s.endIndex,
178178
"Can't form a Character from a String containing more than one extended grapheme cluster")
179179

180180
if _fastPath(s._guts._object.isPreferredRepresentation) {

stdlib/public/core/EmptyCollection.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@ extension EmptyCollection: RandomAccessCollection, MutableCollection {
110110
@inlinable // trivial-implementation
111111
public subscript(bounds: Range<Index>) -> SubSequence {
112112
get {
113-
_debugPrecondition(bounds.lowerBound == 0 && bounds.upperBound == 0,
113+
_boundsCheckPrecondition(bounds.lowerBound == 0 && bounds.upperBound == 0,
114114
"Index out of range")
115115
return self
116116
}
117117
set {
118-
_debugPrecondition(bounds.lowerBound == 0 && bounds.upperBound == 0,
118+
_boundsCheckPrecondition(bounds.lowerBound == 0 && bounds.upperBound == 0,
119119
"Index out of range")
120120
}
121121
}
@@ -128,39 +128,39 @@ extension EmptyCollection: RandomAccessCollection, MutableCollection {
128128

129129
@inlinable // trivial-implementation
130130
public func index(_ i: Index, offsetBy n: Int) -> Index {
131-
_debugPrecondition(i == startIndex && n == 0, "Index out of range")
131+
_boundsCheckPrecondition(i == startIndex && n == 0, "Index out of range")
132132
return i
133133
}
134134

135135
@inlinable // trivial-implementation
136136
public func index(
137137
_ i: Index, offsetBy n: Int, limitedBy limit: Index
138138
) -> Index? {
139-
_debugPrecondition(i == startIndex && limit == startIndex,
139+
_boundsCheckPrecondition(i == startIndex && limit == startIndex,
140140
"Index out of range")
141141
return n == 0 ? i : nil
142142
}
143143

144144
/// The distance between two indexes (always zero).
145145
@inlinable // trivial-implementation
146146
public func distance(from start: Index, to end: Index) -> Int {
147-
_debugPrecondition(start == 0, "From must be startIndex (or endIndex)")
148-
_debugPrecondition(end == 0, "To must be endIndex (or startIndex)")
147+
_boundsCheckPrecondition(start == 0, "From must be startIndex (or endIndex)")
148+
_boundsCheckPrecondition(end == 0, "To must be endIndex (or startIndex)")
149149
return 0
150150
}
151151

152152
@inlinable // trivial-implementation
153153
public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
154-
_debugPrecondition(index == 0, "out of bounds")
155-
_debugPrecondition(bounds == indices, "invalid bounds for an empty collection")
154+
_boundsCheckPrecondition(index == 0, "out of bounds")
155+
_boundsCheckPrecondition(bounds == indices, "invalid bounds for an empty collection")
156156
}
157157

158158
@inlinable // trivial-implementation
159159
public func _failEarlyRangeCheck(
160160
_ range: Range<Index>, bounds: Range<Index>
161161
) {
162-
_debugPrecondition(range == indices, "invalid range for an empty collection")
163-
_debugPrecondition(bounds == indices, "invalid bounds for an empty collection")
162+
_boundsCheckPrecondition(range == indices, "invalid range for an empty collection")
163+
_boundsCheckPrecondition(bounds == indices, "invalid bounds for an empty collection")
164164
}
165165
}
166166

stdlib/public/core/MutableCollection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ public func swap<T>(_ a: inout T, _ b: inout T) {
539539
let p1 = Builtin.addressof(&a)
540540
let p2 = Builtin.addressof(&b)
541541
#endif
542-
_debugPrecondition(
542+
_boundsCheckPrecondition(
543543
p1 != p2,
544544
"swapping a location with itself is not supported")
545545

stdlib/public/core/Range.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,7 @@ where Bound: Strideable, Bound.Stride: SignedInteger
301301
/// index.
302302
@inlinable
303303
public subscript(position: Index) -> Element {
304-
// FIXME: swift-3-indexing-model: tests for the range check.
305-
_debugPrecondition(self.contains(position), "Index out of range")
304+
_boundsCheckPrecondition(self.contains(position), "Index out of range")
306305
return position
307306
}
308307
}

stdlib/public/core/UnsafeBufferPointer.swift.gyb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ public struct Unsafe${Mutable}BufferPointer<Element>
6767
public init(
6868
@_nonEphemeral start: Unsafe${Mutable}Pointer<Element>?, count: Int
6969
) {
70-
_debugPrecondition(
70+
_boundsCheckPrecondition(
7171
count >= 0, "Unsafe${Mutable}BufferPointer with negative count")
72-
_debugPrecondition(
72+
_boundsCheckPrecondition(
7373
count == 0 || start != nil,
7474
"Unsafe${Mutable}BufferPointer has a nil start and nonzero count")
7575
self.init(_uncheckedStart: start, count: _assumeNonNegative(count))
@@ -499,7 +499,7 @@ extension Unsafe${Mutable}BufferPointer {
499499
) rethrows -> R? {
500500
let (oldBase, oldCount) = (self.baseAddress, self.count)
501501
defer {
502-
_debugPrecondition((oldBase, oldCount) == (self.baseAddress, self.count),
502+
_boundsCheckPrecondition((oldBase, oldCount) == (self.baseAddress, self.count),
503503
"UnsafeMutableBufferPointer.withContiguousMutableStorageIfAvailable: replacing the buffer is not allowed")
504504
}
505505
return try body(&self)
@@ -1140,7 +1140,7 @@ extension Unsafe${Mutable}BufferPointer {
11401140
return try body(.init(start: nil, count: 0))
11411141
}
11421142

1143-
_debugPrecondition(
1143+
_boundsCheckPrecondition(
11441144
Int(bitPattern: .init(base)) & (MemoryLayout<T>.alignment-1) == 0,
11451145
"baseAddress must be a properly aligned pointer for types Element and T"
11461146
)
@@ -1150,7 +1150,7 @@ extension Unsafe${Mutable}BufferPointer {
11501150
newCount = count
11511151
} else {
11521152
newCount = count * MemoryLayout<Element>.stride / MemoryLayout<T>.stride
1153-
_debugPrecondition(
1153+
_boundsCheckPrecondition(
11541154
MemoryLayout<T>.stride > MemoryLayout<Element>.stride
11551155
? MemoryLayout<T>.stride % MemoryLayout<Element>.stride == 0
11561156
: MemoryLayout<Element>.stride % MemoryLayout<T>.stride == 0,

test/stdlib/BoundsCheckTraps.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,26 @@ BoundsCheckTraps.test("UnsafeRawBufferPointer")
5252
_blackHole(array)
5353
}
5454

55+
BoundsCheckTraps.test("EmptyCollection")
56+
.skip(.custom(
57+
{ _isFastAssertConfiguration() || _isReleaseAssertConfiguration() },
58+
reason: "this trap is not guaranteed to happen"))
59+
.code {
60+
expectCrashLater()
61+
var empty = EmptyCollection<Int>()
62+
print(empty[0])
63+
_blackHole(empty)
64+
}
65+
66+
BoundsCheckTraps.test("Character")
67+
.skip(.custom(
68+
{ _isFastAssertConfiguration() || _isReleaseAssertConfiguration() },
69+
reason: "this trap is not guaranteed to happen"))
70+
.code {
71+
expectCrashLater()
72+
let twoChars = "ab"
73+
let char = Character(twoChars)
74+
_blackHole(char)
75+
}
76+
5577
runAllTests()

0 commit comments

Comments
 (0)