Skip to content

Commit 03d3113

Browse files
authored
Merge pull request #68376 from Azoy/packs-packs-packs-59
[5.9] [Runtime] Add a function to check type creation
2 parents 7d181c1 + 9b3ea4c commit 03d3113

File tree

3 files changed

+176
-0
lines changed

3 files changed

+176
-0
lines changed

include/swift/Runtime/Metadata.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,18 @@ SWIFT_RUNTIME_STDLIB_SPI
10071007
void _swift_registerConcurrencyStandardTypeDescriptors(
10081008
const ConcurrencyStandardTypeDescriptors *descriptors);
10091009

1010+
/// Check if the given generic arguments are valid inputs for the generic type
1011+
/// context and if so call the metadata access function and return the metadata.
1012+
///
1013+
/// Note: This expects the caller to heap allocate all pack pointers within the
1014+
/// generic arguments via 'swift_allocateMetadataPack'.
1015+
SWIFT_RUNTIME_STDLIB_SPI
1016+
SWIFT_CC(swift)
1017+
const Metadata *_swift_instantiateCheckedGenericMetadata(
1018+
const TypeContextDescriptor *context,
1019+
const void * const *genericArgs,
1020+
size_t genericArgsSize);
1021+
10101022
#pragma clang diagnostic pop
10111023

10121024
} // end namespace swift

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2825,6 +2825,41 @@ swift_getOpaqueTypeConformance(const void * const *arguments,
28252825
arguments, static_cast<const OpaqueTypeDescriptor *>(descriptor), index);
28262826
}
28272827

2828+
SWIFT_RUNTIME_STDLIB_SPI
2829+
SWIFT_CC(swift)
2830+
const Metadata *swift::_swift_instantiateCheckedGenericMetadata(
2831+
const TypeContextDescriptor *context,
2832+
const void * const *genericArgs,
2833+
size_t genericArgsSize) {
2834+
context = swift_auth_data_non_address(
2835+
context, SpecialPointerAuthDiscriminators::ContextDescriptor);
2836+
2837+
if (!context->isGeneric()) {
2838+
return nullptr;
2839+
}
2840+
2841+
DemanglerForRuntimeTypeResolution<StackAllocatedDemangler<2048>> demangler;
2842+
2843+
llvm::ArrayRef<MetadataOrPack> genericArgsRef(
2844+
reinterpret_cast<const MetadataOrPack *>(genericArgs), genericArgsSize);
2845+
llvm::SmallVector<unsigned, 8> genericParamCounts;
2846+
llvm::SmallVector<const void *, 8> allGenericArgs;
2847+
2848+
auto result = _gatherGenericParameters(context, genericArgsRef,
2849+
/* parent */ nullptr,
2850+
genericParamCounts, allGenericArgs,
2851+
demangler);
2852+
2853+
// _gatherGenericParameters returns llvm::None on success.
2854+
if (result.hasValue()) {
2855+
return nullptr;
2856+
}
2857+
2858+
auto accessFunction = context->getAccessFunction();
2859+
2860+
return accessFunction(MetadataState::Complete, allGenericArgs).Value;
2861+
}
2862+
28282863
#if SWIFT_OBJC_INTEROP
28292864

28302865
// Return the ObjC class for the given type name.

test/Runtime/check_create_type.swift

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking)
2+
// REQUIRES: executable_test
3+
4+
// UNSUPPORTED: CPU=arm64e
5+
// UNSUPPORTED: use_os_stdlib
6+
// UNSUPPORTED: back_deployment_runtime
7+
8+
import StdlibUnittest
9+
10+
let testSuite = TestSuite("CheckedCreateType")
11+
12+
struct Variadic<each T> {
13+
struct Nested<U, each V: Equatable> {}
14+
}
15+
16+
@_silgen_name("swift_allocateMetadataPack")
17+
func allocateMetadataPack(
18+
_ packPointer: UnsafeRawPointer,
19+
_ packCount: UInt
20+
) -> UnsafeRawPointer
21+
22+
@_silgen_name("_swift_instantiateCheckedGenericMetadata")
23+
func _instantiateCheckedGenericMetadata(
24+
_ descriptor: UnsafeRawPointer,
25+
_ genericArgs: UnsafeRawPointer,
26+
_ genericArgsSize: UInt
27+
) -> Any.Type?
28+
29+
func metaPointer(_ x: Any.Type) -> UnsafeRawPointer {
30+
unsafeBitCast(x, to: UnsafeRawPointer.self)
31+
}
32+
33+
testSuite.test("_swift_checkedCreateType non-variadic") {
34+
let dictMeta = unsafeBitCast(
35+
[Int: Int].self as Any.Type,
36+
to: UnsafeRawPointer.self
37+
)
38+
let dictDesc = dictMeta.load(
39+
fromByteOffset: MemoryLayout<Int>.size,
40+
as: UnsafeRawPointer.self
41+
)
42+
43+
let dictGenericArgs: [Any.Type] = [String.self, Double.self]
44+
45+
dictGenericArgs.withUnsafeBufferPointer {
46+
let newDict = _instantiateCheckedGenericMetadata(
47+
dictDesc,
48+
UnsafeRawPointer($0.baseAddress!),
49+
UInt($0.count)
50+
)
51+
52+
expectTrue(newDict == [String: Double].self)
53+
}
54+
}
55+
56+
testSuite.test("_swift_checkedCreateType variadic") {
57+
let variMeta = unsafeBitCast(
58+
Variadic< >.self as Any.Type,
59+
to: UnsafeRawPointer.self
60+
)
61+
let variDesc = variMeta.load(
62+
fromByteOffset: MemoryLayout<Int>.size,
63+
as: UnsafeRawPointer.self
64+
)
65+
66+
let variPack: [Any.Type] = [Int.self, Int8.self, UInt8.self]
67+
68+
variPack.withUnsafeBufferPointer { pack in
69+
let packPointer = allocateMetadataPack(
70+
UnsafeRawPointer(pack.baseAddress!),
71+
UInt(pack.count)
72+
)
73+
let genericArgs = [packPointer]
74+
75+
genericArgs.withUnsafeBufferPointer { genericArgs in
76+
let newVari = _instantiateCheckedGenericMetadata(
77+
variDesc,
78+
UnsafeRawPointer(genericArgs.baseAddress!),
79+
UInt(genericArgs.count)
80+
)
81+
82+
expectTrue(newVari == Variadic<Int, Int8, UInt8>.self)
83+
}
84+
}
85+
}
86+
87+
testSuite.test("_swift_checkedCreateType variadic nested with requirements") {
88+
let nestedMeta = unsafeBitCast(
89+
Variadic< >.Nested<()>.self as Any.Type,
90+
to: UnsafeRawPointer.self
91+
)
92+
let nestedDesc = nestedMeta.load(
93+
fromByteOffset: MemoryLayout<Int>.size,
94+
as: UnsafeRawPointer.self
95+
)
96+
97+
let variPack: [Any.Type] = [String.self, [Int].self, UInt64.self]
98+
99+
let nestedPack: [Any.Type] = [Int.self, Substring.self, Bool.self]
100+
101+
nestedPack.withUnsafeBufferPointer { nestedPack in
102+
variPack.withUnsafeBufferPointer { variPack in
103+
let nestedGenericArgs = [
104+
allocateMetadataPack(
105+
UnsafeRawPointer(variPack.baseAddress!),
106+
UInt(variPack.count)
107+
),
108+
metaPointer(Int16.self),
109+
allocateMetadataPack(
110+
UnsafeRawPointer(nestedPack.baseAddress!),
111+
UInt(nestedPack.count)
112+
)
113+
]
114+
115+
nestedGenericArgs.withUnsafeBufferPointer { nestedGenericArgs in
116+
117+
let newNested = _instantiateCheckedGenericMetadata(
118+
nestedDesc,
119+
UnsafeRawPointer(nestedGenericArgs.baseAddress!),
120+
UInt(nestedGenericArgs.count)
121+
)
122+
123+
expectTrue(newNested == Variadic<String, [Int], UInt64>.Nested<Int16, Int, Substring, Bool>.self)
124+
}
125+
}
126+
}
127+
}
128+
129+
runAllTests()

0 commit comments

Comments
 (0)