@@ -243,8 +243,8 @@ public struct UnsafePointer<Pointee>: _Pointer {
243
243
}
244
244
}
245
245
246
- /// Executes the given closure while temporarily binding the specified number
247
- /// of instances to the given type.
246
+ /// Executes the given closure while temporarily binding memory to
247
+ /// the specified number of instances of type `T` .
248
248
///
249
249
/// Use this method when you have a pointer to memory bound to one type and
250
250
/// you need to access that memory as instances of another type. Accessing
@@ -253,15 +253,23 @@ public struct UnsafePointer<Pointee>: _Pointer {
253
253
/// the same memory as an unrelated type without first rebinding the memory
254
254
/// is undefined.
255
255
///
256
- /// The region of memory starting at this pointer and covering `count`
257
- /// instances of the pointer's `Pointee` type must be initialized.
256
+ /// The region of memory that starts at this pointer and covers `count`
257
+ /// strides of `T` instances must be bound to `Pointee`.
258
+ /// Any instance of `T` within the re-bound region may be initialized or
259
+ /// uninitialized. Every instance of `Pointee` overlapping with a given
260
+ /// instance of `T` should have the same initialization state (i.e.
261
+ /// initialized or uninitialized.) Accessing a `T` whose underlying
262
+ /// `Pointee` storage is in a mixed initialization state shall be
263
+ /// undefined behaviour.
258
264
///
259
265
/// The following example temporarily rebinds the memory of a `UInt64`
260
266
/// pointer to `Int64`, then accesses a property on the signed integer.
261
267
///
262
268
/// let uint64Pointer: UnsafePointer<UInt64> = fetchValue()
263
- /// let isNegative = uint64Pointer.withMemoryRebound(to: Int64.self, capacity: 1) { ptr in
264
- /// return ptr.pointee < 0
269
+ /// let isNegative = uint64Pointer.withMemoryRebound(
270
+ /// to: Int64.self, capacity: 1
271
+ /// ) {
272
+ /// return $0.pointee < 0
265
273
/// }
266
274
///
267
275
/// Because this pointer's memory is no longer bound to its `Pointee` type
@@ -274,31 +282,60 @@ public struct UnsafePointer<Pointee>: _Pointer {
274
282
/// `Pointee` type.
275
283
///
276
284
/// - Note: Only use this method to rebind the pointer's memory to a type
277
- /// with the same size and stride as the currently bound `Pointee` type.
278
- /// To bind a region of memory to a type that is a different size, convert
279
- /// the pointer to a raw pointer and use the `bindMemory(to:capacity:)`
280
- /// method.
285
+ /// that is layout compatible with the `Pointee` type. The stride of the
286
+ /// temporary type (`T`) may be an integer multiple or a whole fraction
287
+ /// of `Pointee`'s stride, for example to point to one element of
288
+ /// an aggregate.
289
+ /// To bind a region of memory to a type that does not match these
290
+ /// requirements, convert the pointer to a raw pointer and use the
291
+ /// `bindMemory(to:)` method.
292
+ /// If `T` and `Pointee` have different alignments, this pointer
293
+ /// must be aligned with the larger of the two alignments.
281
294
///
282
295
/// - Parameters:
283
296
/// - type: The type to temporarily bind the memory referenced by this
284
- /// pointer. The type `T` must be the same size and be layout compatible
297
+ /// pointer. The type `T` must be layout compatible
285
298
/// with the pointer's `Pointee` type.
286
- /// - count: The number of instances of `Pointee` to bind to `type` .
287
- /// - body: A closure that takes a typed pointer to the
299
+ /// - count: The number of instances of `T` in the re-bound region .
300
+ /// - body: A closure that takes a typed pointer to the
288
301
/// same memory as this pointer, only bound to type `T`. The closure's
289
302
/// pointer argument is valid only for the duration of the closure's
290
303
/// execution. If `body` has a return value, that value is also used as
291
304
/// the return value for the `withMemoryRebound(to:capacity:_:)` method.
305
+ /// - pointer: The pointer temporarily bound to `T`.
292
306
/// - Returns: The return value, if any, of the `body` closure parameter.
293
307
@inlinable
294
- public func withMemoryRebound< T, Result> ( to type: T . Type , capacity count: Int ,
308
+ @_alwaysEmitIntoClient
309
+ // This custom silgen name is chosen to not interfere with the old ABI
310
+ @_silgen_name ( " _swift_se0333_UnsafePointer_withMemoryRebound " )
311
+ public func withMemoryRebound< T, Result> (
312
+ to type: T . Type ,
313
+ capacity count: Int ,
314
+ _ body: ( _ pointer: UnsafePointer < T > ) throws -> Result
315
+ ) rethrows -> Result {
316
+ _debugPrecondition (
317
+ 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
321
+ )
322
+ let binding = Builtin . bindMemory ( _rawValue, count. _builtinWordValue, T . self)
323
+ defer { Builtin . rebindMemory ( _rawValue, binding) }
324
+ return try body ( . init( _rawValue) )
325
+ }
326
+
327
+ // This unavailable implementation uses the expected mangled name
328
+ // of `withMemoryRebound`, and provides an entry point for any
329
+ // binary compiled against the stlib binary for Swift 5.6 and older.
330
+ @available ( * , unavailable)
331
+ @_silgen_name ( " $sSP17withMemoryRebound2to8capacity_qd_0_qd__m_Siqd_0_SPyqd__GKXEtKr0_lF " )
332
+ @usableFromInline
333
+ internal func _legacy_se0333_withMemoryRebound< T, Result> (
334
+ to type: T . Type ,
335
+ capacity count: Int ,
295
336
_ body: ( UnsafePointer < T > ) throws -> Result
296
337
) rethrows -> Result {
297
- Builtin . bindMemory ( _rawValue, count. _builtinWordValue, T . self)
298
- defer {
299
- Builtin . bindMemory ( _rawValue, count. _builtinWordValue, Pointee . self)
300
- }
301
- return try body ( UnsafePointer < T > ( _rawValue) )
338
+ return try withMemoryRebound ( to: T . self, capacity: count, body)
302
339
}
303
340
304
341
/// Accesses the pointee at the specified offset from this pointer.
@@ -894,8 +931,8 @@ public struct UnsafeMutablePointer<Pointee>: _Pointer {
894
931
return UnsafeMutableRawPointer ( self )
895
932
}
896
933
897
- /// Executes the given closure while temporarily binding the specified number
898
- /// of instances to the given type.
934
+ /// Executes the given closure while temporarily binding memory to
935
+ /// the specified number of instances of the given type.
899
936
///
900
937
/// Use this method when you have a pointer to memory bound to one type and
901
938
/// you need to access that memory as instances of another type. Accessing
@@ -904,15 +941,21 @@ public struct UnsafeMutablePointer<Pointee>: _Pointer {
904
941
/// the same memory as an unrelated type without first rebinding the memory
905
942
/// is undefined.
906
943
///
907
- /// The region of memory starting at this pointer and covering `count`
908
- /// instances of the pointer's `Pointee` type must be initialized.
944
+ /// The region of memory that starts at this pointer and covers `count`
945
+ /// strides of `T` instances must be bound to `Pointee`.
946
+ /// Any instance of `T` within the re-bound region may be initialized or
947
+ /// uninitialized. Every instance of `Pointee` overlapping with a given
948
+ /// instance of `T` should have the same initialization state (i.e.
949
+ /// initialized or uninitialized.) Accessing a `T` whose underlying
950
+ /// `Pointee` storage is in a mixed initialization state shall be
951
+ /// undefined behaviour.
909
952
///
910
953
/// The following example temporarily rebinds the memory of a `UInt64`
911
- /// pointer to `Int64`, then accesses a property on the signed integer.
954
+ /// pointer to `Int64`, then modifies the signed integer.
912
955
///
913
956
/// let uint64Pointer: UnsafeMutablePointer<UInt64> = fetchValue()
914
- /// let isNegative = uint64Pointer.withMemoryRebound(to: Int64.self, capacity: 1) { ptr in
915
- /// return ptr .pointee < 0
957
+ /// uint64Pointer.withMemoryRebound(to: Int64.self, capacity: 1) {
958
+ /// $0 .pointee.negate()
916
959
/// }
917
960
///
918
961
/// Because this pointer's memory is no longer bound to its `Pointee` type
@@ -925,31 +968,60 @@ public struct UnsafeMutablePointer<Pointee>: _Pointer {
925
968
/// `Pointee` type.
926
969
///
927
970
/// - Note: Only use this method to rebind the pointer's memory to a type
928
- /// with the same size and stride as the currently bound `Pointee` type.
929
- /// To bind a region of memory to a type that is a different size, convert
930
- /// the pointer to a raw pointer and use the `bindMemory(to:capacity:)`
931
- /// method.
971
+ /// that is layout compatible with the `Pointee` type. The stride of the
972
+ /// temporary type (`T`) may be an integer multiple or a whole fraction
973
+ /// of `Pointee`'s stride, for example to point to one element of
974
+ /// an aggregate.
975
+ /// To bind a region of memory to a type that does not match these
976
+ /// requirements, convert the pointer to a raw pointer and use the
977
+ /// `bindMemory(to:)` method.
978
+ /// If `T` and `Pointee` have different alignments, this pointer
979
+ /// must be aligned with the larger of the two alignments.
932
980
///
933
981
/// - Parameters:
934
982
/// - type: The type to temporarily bind the memory referenced by this
935
- /// pointer. The type `T` must be the same size and be layout compatible
983
+ /// pointer. The type `T` must be layout compatible
936
984
/// with the pointer's `Pointee` type.
937
- /// - count: The number of instances of `Pointee` to bind to `type` .
985
+ /// - count: The number of instances of `T` in the re-bound region .
938
986
/// - body: A closure that takes a mutable typed pointer to the
939
987
/// same memory as this pointer, only bound to type `T`. The closure's
940
988
/// pointer argument is valid only for the duration of the closure's
941
989
/// execution. If `body` has a return value, that value is also used as
942
990
/// the return value for the `withMemoryRebound(to:capacity:_:)` method.
991
+ /// - pointer: The pointer temporarily bound to `T`.
943
992
/// - Returns: The return value, if any, of the `body` closure parameter.
944
993
@inlinable
945
- public func withMemoryRebound< T, Result> ( to type: T . Type , capacity count: Int ,
994
+ @_alwaysEmitIntoClient
995
+ // This custom silgen name is chosen to not interfere with the old ABI
996
+ @_silgen_name ( " $_swift_se0333_UnsafeMutablePointer_withMemoryRebound " )
997
+ public func withMemoryRebound< T, Result> (
998
+ to type: T . Type ,
999
+ capacity count: Int ,
1000
+ _ body: ( _ pointer: UnsafeMutablePointer < T > ) throws -> Result
1001
+ ) rethrows -> Result {
1002
+ _debugPrecondition (
1003
+ 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
1007
+ )
1008
+ let binding = Builtin . bindMemory ( _rawValue, count. _builtinWordValue, T . self)
1009
+ defer { Builtin . rebindMemory ( _rawValue, binding) }
1010
+ return try body ( . init( _rawValue) )
1011
+ }
1012
+
1013
+ // This unavailable implementation uses the expected mangled name
1014
+ // of `withMemoryRebound`, and provides an entry point for any
1015
+ // binary compiled against the stlib binary for Swift 5.6 and older.
1016
+ @available ( * , unavailable)
1017
+ @_silgen_name ( " $sSp17withMemoryRebound2to8capacity_qd_0_qd__m_Siqd_0_Spyqd__GKXEtKr0_lF " )
1018
+ @usableFromInline
1019
+ internal func _legacy_se0333_withMemoryRebound< T, Result> (
1020
+ to type: T . Type ,
1021
+ capacity count: Int ,
946
1022
_ body: ( UnsafeMutablePointer < T > ) throws -> Result
947
1023
) rethrows -> Result {
948
- Builtin . bindMemory ( _rawValue, count. _builtinWordValue, T . self)
949
- defer {
950
- Builtin . bindMemory ( _rawValue, count. _builtinWordValue, Pointee . self)
951
- }
952
- return try body ( UnsafeMutablePointer < T > ( _rawValue) )
1024
+ return try withMemoryRebound ( to: T . self, capacity: count, body)
953
1025
}
954
1026
955
1027
/// Accesses the pointee at the specified offset from this pointer.
0 commit comments