Skip to content

Commit 7d5fbdb

Browse files
committed
Move wrapper type into Test, make it an enum for ABIness, update documentation to tell devs not to use our typealias because it'll almost certainly break them in the future
1 parent 06d8aa0 commit 7d5fbdb

File tree

2 files changed

+40
-21
lines changed

2 files changed

+40
-21
lines changed

Documentation/ABI/TestContent.md

+14
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ struct SWTTestContentRecord {
6363
};
6464
```
6565

66+
Do not use the `__TestContentRecord` typealias defined in the testing library.
67+
This type exists to support the testing library's macros and may change in the
68+
future (e.g. to accomodate a generic argument or to make use of one of the
69+
reserved fields.)
70+
71+
Instead, define your own copy of this type where needed—you can copy the
72+
definition above _verbatim_. If your test record type's `context` field (as
73+
described below) is a pointer type, make sure to change its type in your version
74+
of `TestContentRecord` accordingly so that, on systems with pointer
75+
authentication enabled, the pointer is correctly resigned at load time.
76+
6677
### Record content
6778

6879
#### The kind field
@@ -79,6 +90,9 @@ record's kind is a 32-bit unsigned value. The following kinds are defined:
7990
<!-- When adding cases to this enumeration, be sure to also update the
8091
corresponding enumeration in TestContentGeneration.swift. -->
8192

93+
If a test content record's `kind` field equals `0x00000000`, the values of all
94+
other fields in that record are undefined.
95+
8296
#### The accessor field
8397

8498
The function `accessor` is a C function. When called, it initializes the memory

Sources/Testing/Test+Discovery.swift

+26-21
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,28 @@
1010

1111
private import _TestingInternals
1212

13-
/// A type that encapsulates test content records that produce instances of
14-
/// ``Test``.
15-
///
16-
/// This type is necessary because such test content records produce an indirect
17-
/// `async` accessor function rather than directly producing instances of
18-
/// ``Test``, but functions are non-nominal types and cannot directly conform to
19-
/// protocols.
20-
///
21-
/// - Note: This helper type must have the exact in-memory layout of the `async`
22-
/// accessor function. Do not add any additional stored properties. The layout
23-
/// of this type is _de facto_ [guaranteed](https://github.com/swiftlang/swift/blob/main/docs/ABI/TypeLayout.rst)
24-
/// by the Swift ABI.
25-
/* @frozen */ private struct _TestRecord: TestContent {
26-
static var testContentKind: UInt32 {
27-
0x74657374
28-
}
13+
extension Test {
14+
/// A type that encapsulates test content records that produce instances of
15+
/// ``Test``.
16+
///
17+
/// This type is necessary because such test content records produce an
18+
/// indirect `async` accessor function rather than directly producing
19+
/// instances of ``Test``, but functions are non-nominal types and cannot
20+
/// directly conform to protocols.
21+
///
22+
/// - Note: This helper type must have the exact in-memory layout of the
23+
/// `async` accessor function. Do not add any additional cases or associated
24+
/// values. The layout of this type is [guaranteed](https://github.com/swiftlang/swift/blob/main/docs/ABI/TypeLayout.rst#fragile-enum-layout)
25+
/// by the Swift ABI.
26+
/* @frozen */ private enum _Record: TestContent {
27+
static var testContentKind: UInt32 {
28+
0x74657374
29+
}
2930

30-
/// This instance's actual (asynchronous) accessor function.
31-
var asyncAccessor: @Sendable () async -> Test
32-
}
31+
/// The actual (asynchronous) accessor function.
32+
case generator(@Sendable () async -> Test)
33+
}
3334

34-
extension Test {
3535
/// All available ``Test`` instances in the process, according to the runtime.
3636
///
3737
/// The order of values in this sequence is unspecified.
@@ -58,7 +58,12 @@ extension Test {
5858
// Walk all test content and gather generator functions, then call them in
5959
// a task group and collate their results.
6060
if useNewMode {
61-
let generators = _TestRecord.allTestContentRecords().lazy.compactMap { $0.load()?.asyncAccessor }
61+
let generators = _Record.allTestContentRecords().lazy.compactMap { record in
62+
if case let .generator(generator) = record.load() {
63+
return generator
64+
}
65+
return nil // currently unreachable, but not provably so
66+
}
6267
await withTaskGroup(of: Self.self) { taskGroup in
6368
for generator in generators {
6469
taskGroup.addTask(operation: generator)

0 commit comments

Comments
 (0)