@@ -2001,6 +2001,37 @@ namespace {
2001
2001
using super = ContextDescriptorBuilderBase;
2002
2002
2003
2003
OpaqueTypeDecl *O;
2004
+
2005
+ // / Whether the given requirement is a conformance requirement that
2006
+ // / requires a witness table in the opaque type descriptor.
2007
+ // /
2008
+ // / When it does, returns the protocol.
2009
+ ProtocolDecl *requiresWitnessTable (const Requirement &req) const {
2010
+ // We only care about conformance requirements.
2011
+ if (req.getKind () != RequirementKind::Conformance)
2012
+ return nullptr ;
2013
+
2014
+ // The protocol must require a witness table.
2015
+ auto proto = req.getProtocolDecl ();
2016
+ if (!Lowering::TypeConverter::protocolRequiresWitnessTable (proto))
2017
+ return nullptr ;
2018
+
2019
+ // The type itself must be anchored on one of the generic parameters of
2020
+ // the opaque type (not an outer context).
2021
+ Type subject = req.getFirstType ();
2022
+ while (auto depMember = subject->getAs <DependentMemberType>()) {
2023
+ subject = depMember->getBase ();
2024
+ }
2025
+
2026
+ if (auto genericParam = subject->getAs <GenericTypeParamType>()) {
2027
+ unsigned opaqueDepth = O->getOpaqueGenericParams ().front ()->getDepth ();
2028
+ if (genericParam->getDepth () == opaqueDepth)
2029
+ return proto;
2030
+ }
2031
+
2032
+ return nullptr ;
2033
+ }
2034
+
2004
2035
public:
2005
2036
2006
2037
OpaqueTypeDescriptorBuilder (IRGenModule &IGM, OpaqueTypeDecl *O)
@@ -2015,29 +2046,28 @@ namespace {
2015
2046
2016
2047
void addUnderlyingTypeAndConformances () {
2017
2048
auto sig = O->getOpaqueInterfaceGenericSignature ();
2018
- auto underlyingType = Type (O->getUnderlyingInterfaceType ())
2019
- .subst (*O->getUnderlyingTypeSubstitutions ())
2020
- ->getCanonicalType (sig);
2021
-
2022
2049
auto contextSig = O->getGenericSignature ().getCanonicalSignature ();
2050
+ auto subs = *O->getUnderlyingTypeSubstitutions ();
2023
2051
2024
- B.addRelativeAddress (IGM.getTypeRef (underlyingType, contextSig,
2025
- MangledTypeRefRole::Metadata).first );
2026
-
2027
- auto opaqueType = O->getDeclaredInterfaceType ()
2028
- ->castTo <OpaqueTypeArchetypeType>();
2029
-
2030
- for (auto proto : opaqueType->getConformsTo ()) {
2031
- auto conformance = ProtocolConformanceRef (proto);
2032
- auto underlyingConformance = conformance
2033
- .subst (O->getUnderlyingInterfaceType (),
2034
- *O->getUnderlyingTypeSubstitutions ());
2035
-
2036
- // Skip protocols without Witness tables, e.g. @objc protocols.
2037
- if (!Lowering::TypeConverter::protocolRequiresWitnessTable (
2038
- underlyingConformance.getRequirement ()))
2052
+ // Add the underlying types for each generic parameter.
2053
+ for (auto genericParam : O->getOpaqueGenericParams ()) {
2054
+ auto underlyingType = Type (genericParam).subst (subs)->getCanonicalType (sig);
2055
+ B.addRelativeAddress (
2056
+ IGM.getTypeRef (underlyingType, contextSig,
2057
+ MangledTypeRefRole::Metadata).first );
2058
+ }
2059
+
2060
+ // Add witness tables for each of the conformance requirements.
2061
+ for (const auto &req : sig.getRequirements ()) {
2062
+ auto proto = requiresWitnessTable (req);
2063
+ if (!proto)
2039
2064
continue ;
2040
2065
2066
+ auto underlyingDependentType = req.getFirstType ()->getCanonicalType ();
2067
+ auto underlyingType = underlyingDependentType.subst (subs)
2068
+ ->getCanonicalType ();
2069
+ auto underlyingConformance =
2070
+ subs.lookupConformance (underlyingDependentType, proto);
2041
2071
auto witnessTableRef = IGM.emitWitnessTableRefString (
2042
2072
underlyingType, underlyingConformance,
2043
2073
contextSig,
@@ -2113,11 +2143,14 @@ namespace {
2113
2143
}
2114
2144
2115
2145
uint16_t getKindSpecificFlags () {
2116
- // Store the size of the type and conformances vector in the flags.
2117
- auto opaqueType = O->getDeclaredInterfaceType ()
2118
- ->castTo <OpaqueTypeArchetypeType>();
2119
-
2120
- return 1 + opaqueType->getConformsTo ().size ();
2146
+ // Store the number of types and witness tables in the flags.
2147
+ unsigned numWitnessTables = llvm::count_if (
2148
+ O->getOpaqueInterfaceGenericSignature ().getRequirements (),
2149
+ [&](const Requirement &req) {
2150
+ return requiresWitnessTable (req) != nullptr ;
2151
+ });
2152
+
2153
+ return O->getOpaqueGenericParams ().size () + numWitnessTables;
2121
2154
}
2122
2155
};
2123
2156
} // end anonymous namespace
0 commit comments