@@ -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
@@ -1170,18 +1175,21 @@ class TypeRefBuilder {
11701175 /* useOpaqueTypeSymbolicReferences */ true );
11711176
11721177 // If the substituted type is an opaque type, also gather info
1173- // about which protocols it is required to conform to
1174- std::vector<std::string> OpaqueTypeConformanceRequirements;
1175- gatherConformanceRequirementsIfOpaque<ObjCInteropKind, PointerSize>(
1176- substitutedDemangleTree, OpaqueTypeConformanceRequirements);
1178+ // about which protocols it is required to conform to and the corresponding
1179+ // same-type requirements
1180+ std::vector<std::string> opaqueTypeConformanceRequirements;
1181+ std::vector<TypeAliasInfo> sameTypeRequirements;
1182+ gatherOpaqueTypeRequirements<ObjCInteropKind, PointerSize>(
1183+ substitutedDemangleTree, opaqueTypeConformanceRequirements,
1184+ sameTypeRequirements);
11771185
11781186 auto substitutedTypeName = nodeToString (substitutedDemangleTree);
11791187 std::stringstream OS;
11801188 dumpTypeRef (substitutedTypeRef, OS);
1181- associatedTypes.emplace_back (
1182- AssociatedType {typealiasTypeName, mangledSubstitutedTypeName,
1183- substitutedTypeName, OS.str (),
1184- OpaqueTypeConformanceRequirements });
1189+ associatedTypes.emplace_back (AssociatedType{
1190+ TypeAliasInfo {typealiasTypeName, mangledSubstitutedTypeName,
1191+ substitutedTypeName, OS.str ()} ,
1192+ opaqueTypeConformanceRequirements, sameTypeRequirements });
11851193 }
11861194 result.AssociatedTypeInfos .emplace_back (AssociatedTypeInfo{
11871195 mangledTypeName, typeName, protocolName, associatedTypes});
@@ -1193,9 +1201,10 @@ class TypeRefBuilder {
11931201
11941202 template <template <typename Runtime> class ObjCInteropKind ,
11951203 unsigned PointerSize>
1196- void gatherConformanceRequirementsIfOpaque (
1204+ void gatherOpaqueTypeRequirements (
11971205 Demangle::Node *substitutedTypeDemangleTree,
1198- std::vector<std::string> &OpaqueTypeConformanceRequirements) {
1206+ std::vector<std::string> &opaqueTypeConformanceRequirements,
1207+ std::vector<TypeAliasInfo> &sameTypeRequirements) {
11991208 // With unresolved opaque symbolic references, the demangle tree we
12001209 // extract the opaque type descriptor's address from is of the form:
12011210 // kind=Type
@@ -1209,9 +1218,10 @@ class TypeRefBuilder {
12091218 auto opaqueTypeChildDemangleTree = childDemangleTree->getFirstChild ();
12101219 if (opaqueTypeChildDemangleTree->getKind () ==
12111220 Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
1212- OpaqueTypeConformanceRequirements =
1213- collectOpaqueTypeConformanceNames<ObjCInteropKind, PointerSize>(
1214- opaqueTypeChildDemangleTree->getIndex ());
1221+ extractOpaqueTypeProtocolRequirements<ObjCInteropKind, PointerSize>(
1222+ opaqueTypeChildDemangleTree->getIndex (),
1223+ opaqueTypeConformanceRequirements,
1224+ sameTypeRequirements);
12151225 }
12161226 }
12171227 }
@@ -1628,41 +1638,71 @@ class TypeRefBuilder {
16281638 stream << " - " << info.FullyQualifiedName << " : "
16291639 << info.ProtocolFullyQualifiedName << " \n " ;
16301640 for (const auto &typeAlias : info.AssociatedTypes ) {
1631- stream << " typealias " << typeAlias.TypeAliasName << " = "
1632- << typeAlias.SubstitutedTypeFullyQualifiedName << " \n " ;
1633- stream << typeAlias.SubstitutedTypeDiagnosticPrintName ;
1641+ stream << " typealias " << typeAlias.SubstitutionInfo . TypeAliasName << " = "
1642+ << typeAlias.SubstitutionInfo . SubstitutedTypeFullyQualifiedName << " \n " ;
1643+ stream << typeAlias.SubstitutionInfo . SubstitutedTypeDiagnosticPrintName ;
16341644 if (!typeAlias.OpaqueTypeProtocolConformanceRequirements .empty ()) {
1635- stream << " opaque type conformance requirements: \n " ;
1645+ stream << " -------------------------\n " ;
1646+ stream << " conformance requirements: \n " ;
16361647 for (const auto &protocolName :
16371648 typeAlias.OpaqueTypeProtocolConformanceRequirements ) {
16381649 stream << protocolName << " \n " ;
16391650 }
16401651 }
1652+ if (!typeAlias.OpaqueTypeSameTypeRequirements .empty ()) {
1653+ stream << " -----------------------\n " ;
1654+ stream << " same-type requirements: \n " ;
1655+ for (const auto &sameTypeRequirementInfo :
1656+ typeAlias.OpaqueTypeSameTypeRequirements ) {
1657+ stream << sameTypeRequirementInfo.TypeAliasName << " = "
1658+ << sameTypeRequirementInfo.SubstitutedTypeMangledName << " ("
1659+ << sameTypeRequirementInfo.SubstitutedTypeFullyQualifiedName
1660+ << " )\n " ;
1661+ }
1662+ }
16411663 }
16421664 stream << " \n " ;
16431665 }
16441666 }
16451667
16461668 template <template <typename Runtime> class ObjCInteropKind ,
16471669 unsigned PointerSize>
1648- std::vector<std::string>
1649- collectOpaqueTypeConformanceNames (uintptr_t opaqueTypeDescriptorAddress) {
1650- std::vector<std::string> result;
1670+ void extractOpaqueTypeProtocolRequirements (
1671+ uintptr_t opaqueTypeDescriptorAddress,
1672+ std::vector<std::string> &protocolRequirements,
1673+ std::vector<TypeAliasInfo> &sameTypeRequirements) {
16511674 auto opaqueTypeDescriptorBytes = OpaqueByteReader (
16521675 remote::RemoteAddress (opaqueTypeDescriptorAddress),
16531676 sizeof (ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>));
16541677 if (!opaqueTypeDescriptorBytes.get ()) {
1655- return result ;
1678+ return ;
16561679 }
16571680 const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>
16581681 *opaqueTypeDescriptor =
16591682 (const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize> *)
16601683 opaqueTypeDescriptorBytes.get ();
16611684
16621685 if (!opaqueTypeDescriptor) {
1663- return result ;
1686+ return ;
16641687 }
16651688
1689+ // Given that at a given offset from the opaque type descriptor base there
1690+ // is an offset to a TypeRef string, read it.
1691+ auto readRequirementTypeRefAddress =
1692+ [&](uintptr_t offsetFromOpaqueDescBase,
1693+ uintptr_t requirementAddress) -> uint32_t {
1694+ std::string typeRefString = " " ;
1695+ auto fieldOffsetOffset = requirementAddress + offsetFromOpaqueDescBase -
1696+ (uintptr_t )opaqueTypeDescriptor;
1697+ auto fieldOffsetAddress = opaqueTypeDescriptorAddress + fieldOffsetOffset;
1698+ auto fieldOffsetBytes = OpaqueByteReader (
1699+ remote::RemoteAddress (fieldOffsetAddress), sizeof (uint32_t ));
1700+ auto fieldOffset = (const int32_t *)fieldOffsetBytes.get ();
1701+ auto fieldAddress = detail::applyRelativeOffset (
1702+ (const char *)fieldOffsetAddress, *fieldOffset);
1703+ return fieldAddress;
1704+ };
1705+
16661706 for (const auto &req : opaqueTypeDescriptor->getGenericRequirements ()) {
16671707 if (req.getKind () == GenericRequirementKind::Protocol) {
16681708 // Compute the address of the protocol descriptor offset as:
@@ -1688,10 +1728,32 @@ class TypeRefBuilder {
16881728 auto conformanceRequirementProtocolName =
16891729 nameReader.readFullyQualifiedProtocolName (
16901730 protocolDescriptorAddress);
1691- result.push_back (*conformanceRequirementProtocolName);
1731+ protocolRequirements.push_back (*conformanceRequirementProtocolName);
1732+ }
1733+ if (req.getKind () == GenericRequirementKind::SameType) {
1734+ // Read Param Name
1735+ auto paramAddress = readRequirementTypeRefAddress (req.getParamOffset (),
1736+ (uintptr_t )(&req));
1737+ std::string demangledParamName =
1738+ nodeToString (demangleTypeRef (readTypeRef (paramAddress)));
1739+
1740+ // Read the substituted Type Name
1741+ auto typeAddress = readRequirementTypeRefAddress (
1742+ req.getSameTypeNameOffset (), (uintptr_t )(&req));
1743+ auto typeTypeRef = readTypeRef (typeAddress);
1744+ std::string demangledTypeName =
1745+ nodeToString (demangleTypeRef (typeTypeRef));
1746+ std::string mangledTypeName;
1747+ auto typeMangling = Demangle::mangleNode (demangleTypeRef (typeTypeRef));
1748+ if (!typeMangling.isSuccess ())
1749+ mangledTypeName = " " ;
1750+ else
1751+ mangledTypeName = typeMangling.result ();
1752+ sameTypeRequirements.push_back (TypeAliasInfo{
1753+ demangledParamName, mangledTypeName, demangledTypeName, " " });
16921754 }
16931755 }
1694- return result ;
1756+ return ;
16951757 }
16961758
16971759 // /
@@ -1759,8 +1821,10 @@ class TypeRefBuilder {
17591821 (const char *)contextDescriptorFieldAddress,
17601822 *contextDescriptorOffset);
17611823
1762- // Instead of a type descriptor this may just be a reference to an external, check that first
1763- if (auto symbol = OpaqueDynamicSymbolResolver (remote::RemoteAddress (contextTypeDescriptorAddress))) {
1824+ // Instead of a type descriptor this may just be a reference to an
1825+ // external, check that first
1826+ if (auto symbol = OpaqueDynamicSymbolResolver (
1827+ remote::RemoteAddress (contextTypeDescriptorAddress))) {
17641828 if (!symbol->isResolved ()) {
17651829 Demangle::Context Ctx;
17661830 auto demangledRoot =
0 commit comments