@@ -312,12 +312,17 @@ struct ConformanceCollectionResult {
312312 std::vector<std::string> Errors;
313313};
314314
315- struct AssociatedType {
315+ struct TypeAliasInfo {
316316 std::string TypeAliasName;
317317 std::string SubstitutedTypeMangledName;
318318 std::string SubstitutedTypeFullyQualifiedName;
319319 std::string SubstitutedTypeDiagnosticPrintName;
320+ };
321+
322+ struct AssociatedType {
323+ TypeAliasInfo SubstitutionInfo;
320324 std::vector<std::string> OpaqueTypeProtocolConformanceRequirements;
325+ std::vector<TypeAliasInfo> OpaqueTypeSameTypeRequirements;
321326};
322327
323328// / Info about all of a given type's associated types, as read out from an Image
@@ -1078,18 +1083,21 @@ class TypeRefBuilder {
10781083 /* useOpaqueTypeSymbolicReferences */ true );
10791084
10801085 // If the substituted type is an opaque type, also gather info
1081- // about which protocols it is required to conform to
1082- std::vector<std::string> OpaqueTypeConformanceRequirements;
1083- gatherConformanceRequirementsIfOpaque<ObjCInteropKind, PointerSize>(
1084- substitutedDemangleTree, OpaqueTypeConformanceRequirements);
1086+ // about which protocols it is required to conform to and the corresponding
1087+ // same-type requirements
1088+ std::vector<std::string> opaqueTypeConformanceRequirements;
1089+ std::vector<TypeAliasInfo> sameTypeRequirements;
1090+ gatherOpaqueTypeRequirements<ObjCInteropKind, PointerSize>(
1091+ substitutedDemangleTree, opaqueTypeConformanceRequirements,
1092+ sameTypeRequirements);
10851093
10861094 auto substitutedTypeName = nodeToString (substitutedDemangleTree);
10871095 std::stringstream OS;
10881096 dumpTypeRef (substitutedTypeRef, OS);
1089- associatedTypes.emplace_back (
1090- AssociatedType {typealiasTypeName, mangledSubstitutedTypeName,
1091- substitutedTypeName, OS.str (),
1092- OpaqueTypeConformanceRequirements });
1097+ associatedTypes.emplace_back (AssociatedType{
1098+ TypeAliasInfo {typealiasTypeName, mangledSubstitutedTypeName,
1099+ substitutedTypeName, OS.str ()} ,
1100+ opaqueTypeConformanceRequirements, sameTypeRequirements });
10931101 }
10941102 result.AssociatedTypeInfos .emplace_back (AssociatedTypeInfo{
10951103 mangledTypeName, typeName, protocolName, associatedTypes});
@@ -1101,9 +1109,10 @@ class TypeRefBuilder {
11011109
11021110 template <template <typename Runtime> class ObjCInteropKind ,
11031111 unsigned PointerSize>
1104- void gatherConformanceRequirementsIfOpaque (
1112+ void gatherOpaqueTypeRequirements (
11051113 Demangle::Node *substitutedTypeDemangleTree,
1106- std::vector<std::string> &OpaqueTypeConformanceRequirements) {
1114+ std::vector<std::string> &opaqueTypeConformanceRequirements,
1115+ std::vector<TypeAliasInfo> &sameTypeRequirements) {
11071116 // With unresolved opaque symbolic references, the demangle tree we
11081117 // extract the opaque type descriptor's address from is of the form:
11091118 // kind=Type
@@ -1117,9 +1126,10 @@ class TypeRefBuilder {
11171126 auto opaqueTypeChildDemangleTree = childDemangleTree->getFirstChild ();
11181127 if (opaqueTypeChildDemangleTree->getKind () ==
11191128 Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
1120- OpaqueTypeConformanceRequirements =
1121- collectOpaqueTypeConformanceNames<ObjCInteropKind, PointerSize>(
1122- opaqueTypeChildDemangleTree->getIndex ());
1129+ extractOpaqueTypeProtocolRequirements<ObjCInteropKind, PointerSize>(
1130+ opaqueTypeChildDemangleTree->getIndex (),
1131+ opaqueTypeConformanceRequirements,
1132+ sameTypeRequirements);
11231133 }
11241134 }
11251135 }
@@ -1536,41 +1546,71 @@ class TypeRefBuilder {
15361546 stream << " - " << info.FullyQualifiedName << " : "
15371547 << info.ProtocolFullyQualifiedName << " \n " ;
15381548 for (const auto &typeAlias : info.AssociatedTypes ) {
1539- stream << " typealias " << typeAlias.TypeAliasName << " = "
1540- << typeAlias.SubstitutedTypeFullyQualifiedName << " \n " ;
1541- stream << typeAlias.SubstitutedTypeDiagnosticPrintName ;
1549+ stream << " typealias " << typeAlias.SubstitutionInfo . TypeAliasName << " = "
1550+ << typeAlias.SubstitutionInfo . SubstitutedTypeFullyQualifiedName << " \n " ;
1551+ stream << typeAlias.SubstitutionInfo . SubstitutedTypeDiagnosticPrintName ;
15421552 if (!typeAlias.OpaqueTypeProtocolConformanceRequirements .empty ()) {
1543- stream << " opaque type conformance requirements: \n " ;
1553+ stream << " -------------------------\n " ;
1554+ stream << " conformance requirements: \n " ;
15441555 for (const auto &protocolName :
15451556 typeAlias.OpaqueTypeProtocolConformanceRequirements ) {
15461557 stream << protocolName << " \n " ;
15471558 }
15481559 }
1560+ if (!typeAlias.OpaqueTypeSameTypeRequirements .empty ()) {
1561+ stream << " -----------------------\n " ;
1562+ stream << " same-type requirements: \n " ;
1563+ for (const auto &sameTypeRequirementInfo :
1564+ typeAlias.OpaqueTypeSameTypeRequirements ) {
1565+ stream << sameTypeRequirementInfo.TypeAliasName << " = "
1566+ << sameTypeRequirementInfo.SubstitutedTypeMangledName << " ("
1567+ << sameTypeRequirementInfo.SubstitutedTypeFullyQualifiedName
1568+ << " )\n " ;
1569+ }
1570+ }
15491571 }
15501572 stream << " \n " ;
15511573 }
15521574 }
15531575
15541576 template <template <typename Runtime> class ObjCInteropKind ,
15551577 unsigned PointerSize>
1556- std::vector<std::string>
1557- collectOpaqueTypeConformanceNames (uintptr_t opaqueTypeDescriptorAddress) {
1558- std::vector<std::string> result;
1578+ void extractOpaqueTypeProtocolRequirements (
1579+ uintptr_t opaqueTypeDescriptorAddress,
1580+ std::vector<std::string> &protocolRequirements,
1581+ std::vector<TypeAliasInfo> &sameTypeRequirements) {
15591582 auto opaqueTypeDescriptorBytes = OpaqueByteReader (
15601583 remote::RemoteAddress (opaqueTypeDescriptorAddress),
15611584 sizeof (ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>));
15621585 if (!opaqueTypeDescriptorBytes.get ()) {
1563- return result ;
1586+ return ;
15641587 }
15651588 const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>
15661589 *opaqueTypeDescriptor =
15671590 (const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize> *)
15681591 opaqueTypeDescriptorBytes.get ();
15691592
15701593 if (!opaqueTypeDescriptor) {
1571- return result ;
1594+ return ;
15721595 }
15731596
1597+ // Given that at a given offset from the opaque type descriptor base there
1598+ // is an offset to a TypeRef string, read it.
1599+ auto readRequirementTypeRefAddress =
1600+ [&](uintptr_t offsetFromOpaqueDescBase,
1601+ uintptr_t requirementAddress) -> uint32_t {
1602+ std::string typeRefString = " " ;
1603+ auto fieldOffsetOffset = requirementAddress + offsetFromOpaqueDescBase -
1604+ (uintptr_t )opaqueTypeDescriptor;
1605+ auto fieldOffsetAddress = opaqueTypeDescriptorAddress + fieldOffsetOffset;
1606+ auto fieldOffsetBytes = OpaqueByteReader (
1607+ remote::RemoteAddress (fieldOffsetAddress), sizeof (uint32_t ));
1608+ auto fieldOffset = (const int32_t *)fieldOffsetBytes.get ();
1609+ auto fieldAddress = detail::applyRelativeOffset (
1610+ (const char *)fieldOffsetAddress, *fieldOffset);
1611+ return fieldAddress;
1612+ };
1613+
15741614 for (const auto &req : opaqueTypeDescriptor->getGenericRequirements ()) {
15751615 if (req.getKind () == GenericRequirementKind::Protocol) {
15761616 // Compute the address of the protocol descriptor offset as:
@@ -1596,10 +1636,32 @@ class TypeRefBuilder {
15961636 auto conformanceRequirementProtocolName =
15971637 nameReader.readFullyQualifiedProtocolName (
15981638 protocolDescriptorAddress);
1599- result.push_back (*conformanceRequirementProtocolName);
1639+ protocolRequirements.push_back (*conformanceRequirementProtocolName);
1640+ }
1641+ if (req.getKind () == GenericRequirementKind::SameType) {
1642+ // Read Param Name
1643+ auto paramAddress = readRequirementTypeRefAddress (req.getParamOffset (),
1644+ (uintptr_t )(&req));
1645+ std::string demangledParamName =
1646+ nodeToString (demangleTypeRef (readTypeRef (paramAddress)));
1647+
1648+ // Read the substituted Type Name
1649+ auto typeAddress = readRequirementTypeRefAddress (
1650+ req.getSameTypeNameOffset (), (uintptr_t )(&req));
1651+ auto typeTypeRef = readTypeRef (typeAddress);
1652+ std::string demangledTypeName =
1653+ nodeToString (demangleTypeRef (typeTypeRef));
1654+ std::string mangledTypeName;
1655+ auto typeMangling = Demangle::mangleNode (demangleTypeRef (typeTypeRef));
1656+ if (!typeMangling.isSuccess ())
1657+ mangledTypeName = " " ;
1658+ else
1659+ mangledTypeName = typeMangling.result ();
1660+ sameTypeRequirements.push_back (TypeAliasInfo{
1661+ demangledParamName, mangledTypeName, demangledTypeName, " " });
16001662 }
16011663 }
1602- return result ;
1664+ return ;
16031665 }
16041666
16051667 // /
@@ -1667,8 +1729,10 @@ class TypeRefBuilder {
16671729 (const char *)contextDescriptorFieldAddress,
16681730 *contextDescriptorOffset);
16691731
1670- // Instead of a type descriptor this may just be a reference to an external, check that first
1671- if (auto symbol = OpaqueDynamicSymbolResolver (remote::RemoteAddress (contextTypeDescriptorAddress))) {
1732+ // Instead of a type descriptor this may just be a reference to an
1733+ // external, check that first
1734+ if (auto symbol = OpaqueDynamicSymbolResolver (
1735+ remote::RemoteAddress (contextTypeDescriptorAddress))) {
16721736 if (!symbol->isResolved ()) {
16731737 Demangle::Context Ctx;
16741738 auto demangledRoot =
0 commit comments