Skip to content

Commit adf5d79

Browse files
committed
[stdlib] MemoryLayout: Add support for non-copyable type arguments
[stdlib] MemoryLayout: Update Swift version numbers [stdlib] MemoryLayout: Actually hide legacy ABI
1 parent 51c1543 commit adf5d79

File tree

2 files changed

+105
-6
lines changed

2 files changed

+105
-6
lines changed

stdlib/public/core/MemoryLayout.swift

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -40,7 +40,9 @@
4040
/// byteCount: count * MemoryLayout<Point>.stride,
4141
/// alignment: MemoryLayout<Point>.alignment)
4242
@frozen // namespace
43-
public enum MemoryLayout<T> {
43+
public enum MemoryLayout<T: ~Copyable> {}
44+
45+
extension MemoryLayout where T: ~Copyable {
4446
/// The contiguous memory footprint of `T`, in bytes.
4547
///
4648
/// A type's size does not include any dynamically allocated or out of line
@@ -50,6 +52,7 @@ public enum MemoryLayout<T> {
5052
/// When allocating memory for multiple instances of `T` using an unsafe
5153
/// pointer, use a multiple of the type's stride instead of its size.
5254
@_transparent
55+
@_alwaysEmitIntoClient
5356
public static var size: Int {
5457
return Int(Builtin.sizeof(T.self))
5558
}
@@ -62,6 +65,7 @@ public enum MemoryLayout<T> {
6265
/// trades runtime performance for space efficiency. This value is always
6366
/// positive.
6467
@_transparent
68+
@_alwaysEmitIntoClient
6569
public static var stride: Int {
6670
return Int(Builtin.strideof(T.self))
6771
}
@@ -71,6 +75,7 @@ public enum MemoryLayout<T> {
7175
/// Use the `alignment` property for a type when allocating memory using an
7276
/// unsafe pointer. This value is always positive.
7377
@_transparent
78+
@_alwaysEmitIntoClient
7479
public static var alignment: Int {
7580
return Int(Builtin.alignof(T.self))
7681
}
@@ -80,6 +85,29 @@ public enum MemoryLayout<T> {
8085
extension MemoryLayout : _BitwiseCopyable {}
8186

8287
extension MemoryLayout {
88+
// TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics
89+
@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2)
90+
@usableFromInline
91+
internal static var size: Int {
92+
return Int(Builtin.sizeof(T.self))
93+
}
94+
95+
// TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics
96+
@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2)
97+
@usableFromInline
98+
internal static var stride: Int {
99+
return Int(Builtin.strideof(T.self))
100+
}
101+
102+
// TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics
103+
@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2)
104+
@usableFromInline
105+
internal static var alignment: Int {
106+
return Int(Builtin.alignof(T.self))
107+
}
108+
}
109+
110+
extension MemoryLayout where T: ~Copyable {
83111
/// Returns the contiguous memory footprint of the given instance.
84112
///
85113
/// The result does not include any dynamically allocated or out of line
@@ -103,7 +131,8 @@ extension MemoryLayout {
103131
/// - Parameter value: A value representative of the type to describe.
104132
/// - Returns: The size, in bytes, of the given value's type.
105133
@_transparent
106-
public static func size(ofValue value: T) -> Int {
134+
@_alwaysEmitIntoClient
135+
public static func size(ofValue value: borrowing T) -> Int {
107136
return MemoryLayout.size
108137
}
109138

@@ -131,7 +160,8 @@ extension MemoryLayout {
131160
/// - Parameter value: A value representative of the type to describe.
132161
/// - Returns: The stride, in bytes, of the given value's type.
133162
@_transparent
134-
public static func stride(ofValue value: T) -> Int {
163+
@_alwaysEmitIntoClient
164+
public static func stride(ofValue value: borrowing T) -> Int {
135165
return MemoryLayout.stride
136166
}
137167

@@ -156,10 +186,36 @@ extension MemoryLayout {
156186
/// - Returns: The default memory alignment, in bytes, of the given value's
157187
/// type. This value is always positive.
158188
@_transparent
159-
public static func alignment(ofValue value: T) -> Int {
189+
@_alwaysEmitIntoClient
190+
public static func alignment(ofValue value: borrowing T) -> Int {
160191
return MemoryLayout.alignment
161192
}
193+
}
162194

195+
extension MemoryLayout {
196+
// TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics
197+
@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2)
198+
@usableFromInline
199+
internal static func size(ofValue value: borrowing T) -> Int {
200+
return MemoryLayout.size
201+
}
202+
203+
// TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics
204+
@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2)
205+
@usableFromInline
206+
internal static func stride(ofValue value: borrowing T) -> Int {
207+
return MemoryLayout.stride
208+
}
209+
210+
// TODO: Merge this back into the noncopyable variant once we have @_preInverseGenerics
211+
@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 2)
212+
@usableFromInline
213+
internal static func alignment(ofValue value: borrowing T) -> Int {
214+
return MemoryLayout.alignment
215+
}
216+
}
217+
218+
extension MemoryLayout {
163219
/// Returns the offset of an inline stored property within a type's in-memory
164220
/// representation.
165221
///
@@ -229,12 +285,15 @@ extension MemoryLayout {
229285
@_transparent
230286
@_unavailableInEmbedded
231287
public static func offset(of key: PartialKeyPath<T>) -> Int? {
288+
// FIXME(noncopyableGenerics): The new (implicit) `where T: Copyable`
289+
// extension constraint currently changes the mangling of this from a
290+
// standalone function to an extension method.
232291
return key._storedInlineOffset
233292
}
234293
}
235294

236295
// Not-yet-public alignment conveniences
237-
extension MemoryLayout {
296+
extension MemoryLayout where T: ~Copyable {
238297
internal static var _alignmentMask: Int { return alignment - 1 }
239298

240299
internal static func _roundingUpToAlignment(_ value: Int) -> Int {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-run-simple-swift(-enable-experimental-feature NoncopyableGenerics) | %FileCheck %s
3+
// REQUIRES: executable_test, noncopyable_generics
4+
5+
struct A: ~Copyable {
6+
let value: Int
7+
8+
init(_ value: Int) { self.value = value }
9+
}
10+
11+
let expectedSize = MemoryLayout<Int>.size
12+
let expectedStride = MemoryLayout<Int>.stride
13+
let expectedAlignment = MemoryLayout<Int>.alignment
14+
15+
16+
let actualSize1 = MemoryLayout<A>.size
17+
// CHECK: size: true
18+
print("size: \(actualSize1 == expectedSize)")
19+
20+
let actualStride1 = MemoryLayout<A>.stride
21+
// CHECK: stride: true
22+
print("stride: \(actualStride1 == expectedStride)")
23+
24+
let actualAlignment1 = MemoryLayout<A>.alignment
25+
// CHECK: alignment: true
26+
print("alignment: \(actualAlignment1 == expectedAlignment)")
27+
28+
let a = A(42)
29+
30+
let actualSize2 = MemoryLayout.size(ofValue: a)
31+
// CHECK: size(ofValue:): true
32+
print("size(ofValue:): \(actualSize2 == expectedSize)")
33+
34+
let actualStride2 = MemoryLayout.stride(ofValue: a)
35+
// CHECK: stride(ofValue:): true
36+
print("stride(ofValue:): \(actualStride2 == expectedStride)")
37+
38+
let actualAlignment2 = MemoryLayout.alignment(ofValue: a)
39+
// CHECK: alignment(ofValue:): true
40+
print("alignment(ofValue:): \(actualAlignment2 == expectedAlignment)")

0 commit comments

Comments
 (0)