Skip to content

Commit 9ead7d0

Browse files
authored
[stdlib] relax stride check in UnsafePointer.withMemoryRebound (#41553)
* [stdlib] relax stride check - The stride check in `UnsafePointer.withMemoryRebound` makes less sense when rebinding memory for a single element. - This skips the stride-matching portion of the `_debugPrecondition` in `withMemoryRebound` when `count == 1`. * [test] UnsafePointer.withMemoryRebound with capacity 1
1 parent 66a8f91 commit 9ead7d0

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

stdlib/public/core/UnsafePointer.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -315,9 +315,10 @@ public struct UnsafePointer<Pointee>: _Pointer {
315315
) rethrows -> Result {
316316
_debugPrecondition(
317317
Int(bitPattern: .init(_rawValue)) & (MemoryLayout<T>.alignment-1) == 0 &&
318-
MemoryLayout<Pointee>.stride > MemoryLayout<T>.stride
319-
? MemoryLayout<Pointee>.stride % MemoryLayout<T>.stride == 0
320-
: MemoryLayout<T>.stride % MemoryLayout<Pointee>.stride == 0
318+
( count == 1 ||
319+
MemoryLayout<Pointee>.stride > MemoryLayout<T>.stride
320+
? MemoryLayout<Pointee>.stride % MemoryLayout<T>.stride == 0
321+
: MemoryLayout<T>.stride % MemoryLayout<Pointee>.stride == 0 )
321322
)
322323
let binding = Builtin.bindMemory(_rawValue, count._builtinWordValue, T.self)
323324
defer { Builtin.rebindMemory(_rawValue, binding) }
@@ -1001,9 +1002,10 @@ public struct UnsafeMutablePointer<Pointee>: _Pointer {
10011002
) rethrows -> Result {
10021003
_debugPrecondition(
10031004
Int(bitPattern: .init(_rawValue)) & (MemoryLayout<T>.alignment-1) == 0 &&
1004-
MemoryLayout<Pointee>.stride > MemoryLayout<T>.stride
1005-
? MemoryLayout<Pointee>.stride % MemoryLayout<T>.stride == 0
1006-
: MemoryLayout<T>.stride % MemoryLayout<Pointee>.stride == 0
1005+
( count == 1 ||
1006+
MemoryLayout<Pointee>.stride > MemoryLayout<T>.stride
1007+
? MemoryLayout<Pointee>.stride % MemoryLayout<T>.stride == 0
1008+
: MemoryLayout<T>.stride % MemoryLayout<Pointee>.stride == 0 )
10071009
)
10081010
let binding = Builtin.bindMemory(_rawValue, count._builtinWordValue, T.self)
10091011
defer { Builtin.rebindMemory(_rawValue, binding) }

test/stdlib/UnsafePointer.swift.gyb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,20 @@ ${SelfName}TestSuite.test("withMemoryReboundSE0333") {
498498
}
499499
}
500500

501+
${SelfName}TestSuite.test("withMemoryReboundSE0333.capacity1") {
502+
let mutablePtr = UnsafeMutablePointer<(Int,Bool,UInt8)>.allocate(capacity: 1)
503+
defer { mutablePtr.deallocate() }
504+
let ptr = ${SelfName}<(Int, Bool, UInt8)>(mutablePtr)
505+
// test rebinding to a shorter type with the same alignment
506+
ptr.withMemoryRebound(to: (Int, Bool).self, capacity: 1) {
507+
// Make sure the closure argument is a ${SelfName}
508+
let ptrT: ${SelfName}<(Int, Bool)> = $0
509+
// and that the element is (Int, Bool).
510+
let mutablePtrT = UnsafeMutablePointer(mutating: ptrT)
511+
expectType((Int, Bool).self, &mutablePtrT.pointee)
512+
}
513+
}
514+
501515
% end
502516

503517
runAllTests()

0 commit comments

Comments
 (0)