Skip to content

Commit 5dd3572

Browse files
authored
Merge pull request swiftlang#14351 from DougGregor/demangle-to-metadata-class-constraints
2 parents edd1408 + ef1dfdf commit 5dd3572

File tree

4 files changed

+136
-24
lines changed

4 files changed

+136
-24
lines changed

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ depthIndexToFlatIndex(unsigned depth, unsigned index,
420420
if (depth >= paramCounts.size()) return None;
421421

422422
// Compute the flat index.
423-
unsigned flatIndex = index + depth == 0 ? 0 : paramCounts[depth - 1];
423+
unsigned flatIndex = index + (depth == 0 ? 0 : paramCounts[depth - 1]);
424424

425425
// Out-of-bounds index.
426426
if (flatIndex >= paramCounts[depth]) return None;
@@ -829,13 +829,9 @@ class DecodedMetadataBuilder {
829829

830830
}
831831

832-
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
833-
const Metadata * _Nullable
834-
swift_getTypeByMangledName(const char *typeNameStart, size_t typeNameLength,
835-
size_t numberOfLevels,
836-
size_t *parametersPerLevel,
837-
const Metadata * const *flatSubstitutions) {
838-
llvm::StringRef typeName(typeNameStart, typeNameLength);
832+
const Metadata *swift::_getTypeByMangledName(
833+
StringRef typeName,
834+
SubstGenericParameterFn substGenericParam) {
839835

840836
Demangler demangler;
841837
NodePointer node;
@@ -860,20 +856,7 @@ swift_getTypeByMangledName(const char *typeNameStart, size_t typeNameLength,
860856
if (!node) return nullptr;
861857
}
862858

863-
DecodedMetadataBuilder builder(demangler,
864-
[&](unsigned depth, unsigned index) -> const Metadata * {
865-
if (depth >= numberOfLevels)
866-
return nullptr;
867-
868-
if (index >= parametersPerLevel[depth])
869-
return nullptr;
870-
871-
unsigned flatIndex = index;
872-
for (unsigned i = 0; i < depth; ++i)
873-
flatIndex += parametersPerLevel[i];
874-
875-
return flatSubstitutions[flatIndex];
876-
},
859+
DecodedMetadataBuilder builder(demangler, substGenericParam,
877860
[](const Metadata *base, StringRef assocType,
878861
const ProtocolDescriptor *protocol) -> const Metadata * {
879862
// Look for a conformance of the base type to the protocol.
@@ -893,3 +876,26 @@ swift_getTypeByMangledName(const char *typeNameStart, size_t typeNameLength,
893876

894877
return Demangle::decodeMangledType(builder, node);
895878
}
879+
880+
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
881+
const Metadata * _Nullable
882+
swift_getTypeByMangledName(const char *typeNameStart, size_t typeNameLength,
883+
size_t numberOfLevels,
884+
size_t *parametersPerLevel,
885+
const Metadata * const *flatSubstitutions) {
886+
llvm::StringRef typeName(typeNameStart, typeNameLength);
887+
return _getTypeByMangledName(typeName,
888+
[&](unsigned depth, unsigned index) -> const Metadata * {
889+
if (depth >= numberOfLevels)
890+
return nullptr;
891+
892+
if (index >= parametersPerLevel[depth])
893+
return nullptr;
894+
895+
unsigned flatIndex = index;
896+
for (unsigned i = 0; i < depth; ++i)
897+
flatIndex += parametersPerLevel[i];
898+
899+
return flatSubstitutions[flatIndex];
900+
});
901+
}

stdlib/public/runtime/Private.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,14 @@ namespace swift {
183183
using SubstGenericParameterFn =
184184
llvm::function_ref<const Metadata *(unsigned depth, unsigned index)>;
185185

186+
/// Retrieve the type metadata described by the given type name.
187+
///
188+
/// \p substGenericParam Function that provides generic argument metadata
189+
/// given a particular generic parameter specified by depth/index.
190+
const Metadata *_getTypeByMangledName(
191+
StringRef typeName,
192+
SubstGenericParameterFn substGenericParam);
193+
186194
/// FIXME: Remove once this is in Metadata.h
187195
using GenericRequirementDescriptor =
188196
TargetGenericRequirementDescriptor<InProcess>;

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -763,10 +763,53 @@ bool swift::_checkGenericRequirements(
763763
continue;
764764
}
765765

766-
// FIXME: Handle all of the other cases.
767-
default:
766+
case GenericRequirementKind::SameType: {
767+
// Demangle the second type under the given substitutions.
768+
auto otherType =
769+
_getTypeByMangledName(req.getMangledTypeName(), substGenericParam);
770+
if (!otherType) return true;
771+
772+
assert(!req.getFlags().hasExtraArgument());
773+
774+
// Check that the types are equivalent.
775+
if (subjectType != otherType) return true;
776+
777+
continue;
778+
}
779+
780+
case GenericRequirementKind::Layout: {
781+
switch (req.getLayout()) {
782+
case GenericRequirementLayoutKind::Class:
783+
// Check whether the subject type is a class.
784+
if (!subjectType->isAnyClass()) return true;
785+
continue;
786+
}
787+
788+
// Unknown layout.
768789
return true;
769790
}
791+
792+
case GenericRequirementKind::BaseClass: {
793+
// Demangle the base type under the given substitutions.
794+
auto baseType =
795+
_getTypeByMangledName(req.getMangledTypeName(), substGenericParam);
796+
if (!baseType) return true;
797+
798+
// Check whether it's dynamically castable, which works as a superclass
799+
// check.
800+
if (!swift_dynamicCastMetatype(subjectType, baseType)) return true;
801+
802+
continue;
803+
}
804+
805+
case GenericRequirementKind::SameConformance: {
806+
// FIXME: Implement this check.
807+
continue;
808+
}
809+
}
810+
811+
// Unknown generic requirement kind.
812+
return true;
770813
}
771814

772815
// Success!

test/Runtime/demangleToMetadata.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,5 +278,60 @@ DemangleToMetadataTests.test("associated type conformance requirements") {
278278
expectNil(_typeByMangledName("4main3SG5VyAA12ConformsToP1cVG"))
279279
}
280280

281+
struct SG6<T: P4> where T.Assoc1 == T.Assoc2 { }
282+
struct SG7<T: P4> where T.Assoc1 == Int { }
283+
struct SG8<T: P4> where T.Assoc1 == [T.Assoc2] { }
284+
285+
struct ConformsToP4d : P4 {
286+
typealias Assoc1 = [ConformsToP2]
287+
typealias Assoc2 = ConformsToP2
288+
}
289+
290+
DemangleToMetadataTests.test("same-type requirements") {
291+
// Concrete type.
292+
expectEqual(SG7<S>.self,
293+
_typeByMangledName("4main3SG7VyAA1SVG")!)
294+
295+
// Other associated type.
296+
expectEqual(SG6<ConformsToP4b>.self,
297+
_typeByMangledName("4main3SG6VyAA13ConformsToP4bVG")!)
298+
expectEqual(SG6<ConformsToP4c>.self,
299+
_typeByMangledName("4main3SG6VyAA13ConformsToP4cVG")!)
300+
301+
// Structural type.
302+
expectEqual(SG8<ConformsToP4d>.self,
303+
_typeByMangledName("4main3SG8VyAA13ConformsToP4dVG")!)
304+
305+
// Failure cases: types don't match.
306+
expectNil(_typeByMangledName("4main3SG7VyAA13ConformsToP4aVG"))
307+
expectNil(_typeByMangledName("4main3SG6VyAA13ConformsToP4aVG"))
308+
expectNil(_typeByMangledName("4main3SG8VyAA13ConformsToP4cVG"))
309+
}
310+
311+
struct SG9<T: AnyObject> { }
312+
313+
DemangleToMetadataTests.test("AnyObject requirements") {
314+
expectEqual(SG9<C>.self,
315+
_typeByMangledName("4main3SG9VyAA1CCG")!)
316+
317+
// Failure cases: failed AnyObject constraint.
318+
expectNil(_typeByMangledName("4main3SG9VyAA1SVG"))
319+
}
320+
321+
struct SG10<T: C> { }
322+
323+
class C2 : C { }
324+
class C3 { }
325+
326+
DemangleToMetadataTests.test("superclass requirements") {
327+
expectEqual(SG10<C>.self,
328+
_typeByMangledName("4main4SG10VyAA1CCG")!)
329+
expectEqual(SG10<C2>.self,
330+
_typeByMangledName("4main4SG10VyAA2C2CG")!)
331+
332+
// Failure cases: not a subclass.
333+
expectNil(_typeByMangledName("4main4SG10VyAA2C3CG"))
334+
}
335+
281336
runAllTests()
282337

0 commit comments

Comments
 (0)