Skip to content

Commit 3ddec4f

Browse files
committed
Wrap _checkGenericRequirements instead for _instantiateCheckedGenericMetadata
1 parent 9050690 commit 3ddec4f

File tree

4 files changed

+137
-23
lines changed

4 files changed

+137
-23
lines changed

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2846,17 +2846,29 @@ const Metadata *swift::_swift_instantiateCheckedGenericMetadata(
28462846
return nullptr;
28472847
}
28482848

2849-
DemanglerForRuntimeTypeResolution<StackAllocatedDemangler<2048>> demangler;
2849+
llvm::SmallVector<const void *, 8> extraArguments;
28502850

2851-
llvm::ArrayRef<MetadataOrPack> genericArgsRef(
2852-
reinterpret_cast<const MetadataOrPack *>(genericArgs), genericArgsSize);
2853-
llvm::SmallVector<unsigned, 8> genericParamCounts;
2854-
llvm::SmallVector<const void *, 8> allGenericArgs;
2851+
for (size_t i = 0; i != genericArgsSize; i += 1) {
2852+
extraArguments.push_back(genericArgs[i]);
2853+
}
28552854

2856-
auto result = _gatherGenericParameters(context, genericArgsRef,
2857-
/* parent */ nullptr,
2858-
genericParamCounts, allGenericArgs,
2859-
demangler);
2855+
// Check whether the generic requirements are satisfied, collecting
2856+
// any extra arguments we need for the instantiation function.
2857+
//
2858+
// Note: The extra arguemnts provided are not complete and do not include
2859+
// witness tables. This is fine for _checkGenericRequirements because it does
2860+
// not look for any of those.
2861+
SubstGenericParametersFromMetadata substitutions(context, extraArguments.data());
2862+
2863+
auto result = _checkGenericRequirements(
2864+
context->getGenericContext()->getGenericRequirements(), extraArguments,
2865+
[&substitutions](unsigned depth, unsigned index) {
2866+
return substitutions.getMetadata(depth, index).Ptr;
2867+
},
2868+
[](const Metadata *type, unsigned index) {
2869+
// In fact, just don't offer any witness tables if asked for one.
2870+
return nullptr;
2871+
}, /* allowsUnresolvedSubject */ true);
28602872

28612873
// _gatherGenericParameters returns llvm::None on success.
28622874
if (result.hasValue()) {
@@ -2865,7 +2877,7 @@ const Metadata *swift::_swift_instantiateCheckedGenericMetadata(
28652877

28662878
auto accessFunction = context->getAccessFunction();
28672879

2868-
return accessFunction(MetadataState::Complete, allGenericArgs).Value;
2880+
return accessFunction(MetadataState::Complete, extraArguments).Value;
28692881
}
28702882

28712883
#if SWIFT_OBJC_INTEROP

stdlib/public/runtime/Private.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,8 @@ class TypeInfo {
523523
llvm::ArrayRef<GenericRequirementDescriptor> requirements,
524524
llvm::SmallVectorImpl<const void *> &extraArguments,
525525
SubstGenericParameterFn substGenericParam,
526-
SubstDependentWitnessTableFn substWitnessTable);
526+
SubstDependentWitnessTableFn substWitnessTable,
527+
bool allowsUnresolvedSubject = false);
527528

528529
/// A helper function which avoids performing a store if the destination
529530
/// address already contains the source value. This is useful when

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,24 +1344,37 @@ static llvm::Optional<TypeLookupError>
13441344
checkGenericRequirement(const GenericRequirementDescriptor &req,
13451345
llvm::SmallVectorImpl<const void *> &extraArguments,
13461346
SubstGenericParameterFn substGenericParam,
1347-
SubstDependentWitnessTableFn substWitnessTable) {
1347+
SubstDependentWitnessTableFn substWitnessTable,
1348+
bool allowsUnresolvedSubject) {
13481349
assert(!req.getFlags().isPackRequirement());
13491350

13501351
// Make sure we understand the requirement we're dealing with.
13511352
if (!req.hasKnownKind())
13521353
return TypeLookupError("unknown kind");
13531354

1355+
const Metadata *subjectType = nullptr;
1356+
13541357
// Resolve the subject generic parameter.
13551358
auto result = swift_getTypeByMangledName(
13561359
MetadataState::Abstract, req.getParam(), extraArguments.data(),
13571360
substGenericParam, substWitnessTable);
1358-
if (result.getError())
1361+
1362+
if (!allowsUnresolvedSubject && result.isError()) {
13591363
return *result.getError();
1360-
const Metadata *subjectType = result.getType().getMetadata();
1364+
}
1365+
1366+
if (!result.isError()) {
1367+
subjectType = result.getType().getMetadata();
1368+
}
13611369

13621370
// Check the requirement.
13631371
switch (req.getKind()) {
13641372
case GenericRequirementKind::Protocol: {
1373+
// Protocol requirements _require_ a subject type.
1374+
if (result.isError()) {
1375+
return *result.getError();
1376+
}
1377+
13651378
const WitnessTable *witnessTable = nullptr;
13661379
if (!_conformsToProtocol(nullptr, subjectType, req.getProtocol(),
13671380
&witnessTable)) {
@@ -1382,16 +1395,37 @@ checkGenericRequirement(const GenericRequirementDescriptor &req,
13821395
}
13831396

13841397
case GenericRequirementKind::SameType: {
1398+
// Same type requirements don't require a valid subject.
1399+
1400+
const Metadata *sameType = nullptr;
1401+
13851402
// Demangle the second type under the given substitutions.
13861403
auto result = swift_getTypeByMangledName(
13871404
MetadataState::Abstract, req.getMangledTypeName(),
13881405
extraArguments.data(), substGenericParam, substWitnessTable);
1389-
if (result.getError())
1406+
1407+
if (!allowsUnresolvedSubject && result.isError()) {
13901408
return *result.getError();
1391-
auto otherType = result.getType().getMetadata();
1409+
}
1410+
1411+
if (!result.isError()) {
1412+
sameType = result.getType().getMetadata();
1413+
}
1414+
1415+
// If we don't have one of either the subject type or the same type and we
1416+
// have the other, then return this as a success. This assumes the given
1417+
// extra arguments have provided only the required key arguments in which
1418+
// case some same type constraints may concretize some generic arguments
1419+
// making them non-key.
1420+
//
1421+
// Note: We don't need to check for allowsUnresolvedSubject here because
1422+
// these can only be null in the case where we do allow it.
1423+
if ((!subjectType && sameType) || (subjectType && !sameType)) {
1424+
return llvm::None;
1425+
}
13921426

13931427
// Check that the types are equivalent.
1394-
if (subjectType != otherType) {
1428+
if (subjectType != sameType) {
13951429
return TYPE_LOOKUP_ERROR_FMT(
13961430
"subject type %.*s does not match %.*s", (int)req.getParam().size(),
13971431
req.getParam().data(), (int)req.getMangledTypeName().size(),
@@ -1402,10 +1436,20 @@ checkGenericRequirement(const GenericRequirementDescriptor &req,
14021436
}
14031437

14041438
case GenericRequirementKind::Layout: {
1439+
// Layout requirements _require_ a subject type.
1440+
if (result.isError()) {
1441+
return *result.getError();
1442+
}
1443+
14051444
return satisfiesLayoutConstraint(req, subjectType);
14061445
}
14071446

14081447
case GenericRequirementKind::BaseClass: {
1448+
// Base class requirements _require_ a subject type.
1449+
if (result.isError()) {
1450+
return *result.getError();
1451+
}
1452+
14091453
// Demangle the base type under the given substitutions.
14101454
auto result = swift_getTypeByMangledName(
14111455
MetadataState::Abstract, req.getMangledTypeName(),
@@ -1594,7 +1638,8 @@ llvm::Optional<TypeLookupError> swift::_checkGenericRequirements(
15941638
llvm::ArrayRef<GenericRequirementDescriptor> requirements,
15951639
llvm::SmallVectorImpl<const void *> &extraArguments,
15961640
SubstGenericParameterFn substGenericParam,
1597-
SubstDependentWitnessTableFn substWitnessTable) {
1641+
SubstDependentWitnessTableFn substWitnessTable,
1642+
bool allowsUnresolvedSubject) {
15981643
for (const auto &req : requirements) {
15991644
if (req.getFlags().isPackRequirement()) {
16001645
auto error = checkGenericPackRequirement(req, extraArguments,
@@ -1605,7 +1650,8 @@ llvm::Optional<TypeLookupError> swift::_checkGenericRequirements(
16051650
} else {
16061651
auto error = checkGenericRequirement(req, extraArguments,
16071652
substGenericParam,
1608-
substWitnessTable);
1653+
substWitnessTable,
1654+
allowsUnresolvedSubject);
16091655
if (error)
16101656
return error;
16111657
}

test/Runtime/check_create_type.swift

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func metaPointer(_ x: Any.Type) -> UnsafeRawPointer {
3030
unsafeBitCast(x, to: UnsafeRawPointer.self)
3131
}
3232

33-
testSuite.test("_swift_checkedCreateType non-variadic") {
33+
testSuite.test("_swift_instantiateCheckedGenericMetadata non-variadic") {
3434
let dictMeta = unsafeBitCast(
3535
[Int: Int].self as Any.Type,
3636
to: UnsafeRawPointer.self
@@ -53,7 +53,7 @@ testSuite.test("_swift_checkedCreateType non-variadic") {
5353
}
5454
}
5555

56-
testSuite.test("_swift_checkedCreateType variadic") {
56+
testSuite.test("_swift_instantiateCheckedGenericMetadata variadic") {
5757
let variMeta = unsafeBitCast(
5858
Variadic< >.self as Any.Type,
5959
to: UnsafeRawPointer.self
@@ -70,7 +70,9 @@ testSuite.test("_swift_checkedCreateType variadic") {
7070
UnsafeRawPointer(pack.baseAddress!),
7171
UInt(pack.count)
7272
)
73-
let genericArgs = [packPointer]
73+
74+
// The 3 is the shape of the pack
75+
let genericArgs = [UnsafeRawPointer(bitPattern: 3)!, packPointer]
7476

7577
genericArgs.withUnsafeBufferPointer { genericArgs in
7678
let newVari = _instantiateCheckedGenericMetadata(
@@ -84,7 +86,7 @@ testSuite.test("_swift_checkedCreateType variadic") {
8486
}
8587
}
8688

87-
testSuite.test("_swift_checkedCreateType variadic nested with requirements") {
89+
testSuite.test("_swift_instantiateCheckedGenericMetadata variadic nested with requirements") {
8890
let nestedMeta = unsafeBitCast(
8991
Variadic< >.Nested<()>.self as Any.Type,
9092
to: UnsafeRawPointer.self
@@ -101,6 +103,10 @@ testSuite.test("_swift_checkedCreateType variadic nested with requirements") {
101103
nestedPack.withUnsafeBufferPointer { nestedPack in
102104
variPack.withUnsafeBufferPointer { variPack in
103105
let nestedGenericArgs = [
106+
// First shape class
107+
UnsafeRawPointer(bitPattern: 3)!,
108+
// Second shape class
109+
UnsafeRawPointer(bitPattern: 3)!,
104110
allocateMetadataPack(
105111
UnsafeRawPointer(variPack.baseAddress!),
106112
UInt(variPack.count)
@@ -126,4 +132,53 @@ testSuite.test("_swift_checkedCreateType variadic nested with requirements") {
126132
}
127133
}
128134

135+
struct Generic<T> {}
136+
struct Generic2<T, U> {}
137+
138+
extension Generic where T == Int {
139+
struct Nested {}
140+
}
141+
142+
extension Generic2 where T == U? {
143+
struct Nested {}
144+
}
145+
146+
testSuite.test("_swift_instantiateCheckedGenericMetadata concrete generic types (same type conretized)") {
147+
let nestedMeta1 = metaPointer(Generic<Int>.Nested.self)
148+
let nestedDesc1 = nestedMeta1.load(
149+
fromByteOffset: MemoryLayout<Int>.size,
150+
as: UnsafeRawPointer.self
151+
)
152+
153+
let genericArgs1: [UnsafeRawPointer?] = []
154+
155+
genericArgs1.withUnsafeBufferPointer {
156+
let nested = _instantiateCheckedGenericMetadata(
157+
nestedDesc1,
158+
UnsafeRawPointer($0.baseAddress!),
159+
UInt($0.count)
160+
)
161+
162+
expectTrue(nested == Generic<Int>.Nested.self)
163+
}
164+
165+
let nestedMeta2 = metaPointer(Generic2<Int?, Int>.Nested.self)
166+
let nestedDesc2 = nestedMeta2.load(
167+
fromByteOffset: MemoryLayout<Int>.size,
168+
as: UnsafeRawPointer.self
169+
)
170+
171+
let genericArgs2 = [metaPointer(String.self)]
172+
173+
genericArgs2.withUnsafeBufferPointer {
174+
let nested = _instantiateCheckedGenericMetadata(
175+
nestedDesc2,
176+
UnsafeRawPointer($0.baseAddress!),
177+
UInt($0.count)
178+
)
179+
180+
expectTrue(nested == Generic2<String?, String>.Nested.self)
181+
}
182+
}
183+
129184
runAllTests()

0 commit comments

Comments
 (0)