diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def index fc559006a17a3..cb1d6f3b1cccc 100644 --- a/include/swift/Demangling/DemangleNodes.def +++ b/include/swift/Demangling/DemangleNodes.def @@ -210,6 +210,7 @@ NODE(CurryThunk) NODE(DispatchThunk) NODE(MethodDescriptor) NODE(ProtocolRequirementsBaseDescriptor) +NODE(AssociatedConformanceDescriptor) NODE(AssociatedTypeDescriptor) NODE(ThrowsAnnotation) NODE(EmptyList) diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h index f6780b3011b60..e5d486f8aee9c 100644 --- a/include/swift/IRGen/Linking.h +++ b/include/swift/IRGen/Linking.h @@ -206,6 +206,13 @@ class LinkEntity { /// The pointer is an AssociatedTypeDecl*. AssociatedTypeDescriptor, + /// An descriptor for an associated conformance within a protocol, which + /// will alias the TargetProtocolRequirement descripting this + /// particular associated conformance. + /// The pointer is a ProtocolDecl*; the index of the associated conformance + /// is stored in the data. + AssociatedConformanceDescriptor, + /// A function which returns the default type metadata for the associated /// type of a protocol. The secondary pointer is a ProtocolDecl*. /// The index of the associated type declaration is stored in the data. @@ -342,6 +349,21 @@ class LinkEntity { Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)); } + void setForProtocolAndAssociatedConformance(Kind kind, + const ProtocolDecl *proto, + CanType associatedType, + ProtocolDecl *associatedProtocol){ + assert(isDeclKind(kind)); + Pointer = static_cast(const_cast(proto)); + SecondaryPointer = nullptr; + Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)) | + LINKENTITY_SET_FIELD(AssociatedConformanceIndex, + getAssociatedConformanceIndex( + proto, + associatedType, + associatedProtocol)); + } + void setForProtocolConformance(Kind kind, const ProtocolConformance *c) { assert(isProtocolConformanceKind(kind) && !isTypeKind(kind)); Pointer = nullptr; @@ -407,14 +429,12 @@ class LinkEntity { } // We store associated conformances using their index in the requirement - // list of the requirement signature of the conformance's protocol. - static unsigned getAssociatedConformanceIndex( - const ProtocolConformance *conformance, + // list of the requirement signature of the protocol. + static unsigned getAssociatedConformanceIndex(const ProtocolDecl *proto, CanType associatedType, ProtocolDecl *requirement) { unsigned index = 0; - for (const auto &reqt : - conformance->getProtocol()->getRequirementSignature()) { + for (const auto &reqt : proto->getRequirementSignature()) { if (reqt.getKind() == RequirementKind::Conformance && reqt.getFirstType()->getCanonicalType() == associatedType && reqt.getSecondType()->castTo()->getDecl() == @@ -426,15 +446,31 @@ class LinkEntity { llvm_unreachable("requirement not found in protocol"); } + // We store associated conformances using their index in the requirement + // list of the requirement signature of the conformance's protocol. + static unsigned getAssociatedConformanceIndex( + const ProtocolConformance *conformance, + CanType associatedType, + ProtocolDecl *requirement) { + return getAssociatedConformanceIndex(conformance->getProtocol(), + associatedType, requirement); + } + static std::pair - getAssociatedConformanceByIndex(const ProtocolConformance *conformance, + getAssociatedConformanceByIndex(const ProtocolDecl *proto, unsigned index) { - auto &reqt = conformance->getProtocol()->getRequirementSignature()[index]; + auto &reqt = proto->getRequirementSignature()[index]; assert(reqt.getKind() == RequirementKind::Conformance); return { reqt.getFirstType()->getCanonicalType(), reqt.getSecondType()->castTo()->getDecl() }; } + static std::pair + getAssociatedConformanceByIndex(const ProtocolConformance *conformance, + unsigned index) { + return getAssociatedConformanceByIndex(conformance->getProtocol(), index); + } + void setForType(Kind kind, CanType type) { assert(isTypeKind(kind)); Pointer = type.getPointer(); @@ -758,6 +794,18 @@ class LinkEntity { return entity; } + static LinkEntity + forAssociatedConformanceDescriptor(ProtocolDecl *proto, + CanType associatedType, + ProtocolDecl *associatedProtocol) { + LinkEntity entity; + entity.setForProtocolAndAssociatedConformance( + Kind::AssociatedConformanceDescriptor, + proto, associatedType, + associatedProtocol); + return entity; + } + static LinkEntity forAssociatedTypeMetadataAccessFunction(const ProtocolConformance *C, AssociatedType association) { @@ -872,9 +920,15 @@ class LinkEntity { } std::pair getAssociatedConformance() const { - assert(getKind() == Kind::AssociatedTypeWitnessTableAccessFunction); - return getAssociatedConformanceByIndex(getProtocolConformance(), + if (getKind() == Kind::AssociatedTypeWitnessTableAccessFunction) { + return getAssociatedConformanceByIndex(getProtocolConformance(), LINKENTITY_GET_FIELD(Data, AssociatedConformanceIndex)); + } + + assert(getKind() == Kind::AssociatedConformanceDescriptor); + return getAssociatedConformanceByIndex( + cast(getDecl()), + LINKENTITY_GET_FIELD(Data, AssociatedConformanceIndex)); } ProtocolDecl *getAssociatedProtocol() const { diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp index ce7959e12efdd..758ccd62bae98 100644 --- a/lib/Demangling/Demangler.cpp +++ b/lib/Demangling/Demangler.cpp @@ -1827,6 +1827,14 @@ NodePointer Demangler::demangleThunkOrSpecialization() { return createWithChild(Node::Kind::DefaultAssociatedTypeMetadataAccessor, popAssocTypeName()); + case 'n': { + NodePointer requirementTy = popProtocol(); + auto assocTypePath = popAssocTypePath(); + NodePointer protoTy = popNode(Node::Kind::Type); + return createWithChildren(Node::Kind::AssociatedConformanceDescriptor, + protoTy, assocTypePath, requirementTy); + } + case 'H': case 'h': { auto nodeKind = c == 'H' ? Node::Kind::KeyPathEqualsThunkHelper diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index 6d2e2627cd497..50e451bff0fdd 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -308,6 +308,7 @@ class NodePrinter { case Node::Kind::ProtocolListWithClass: case Node::Kind::Allocator: case Node::Kind::ArgumentTuple: + case Node::Kind::AssociatedConformanceDescriptor: case Node::Kind::AssociatedTypeDescriptor: case Node::Kind::AssociatedTypeMetadataAccessor: case Node::Kind::AssociatedTypeWitnessTableAccessor: @@ -1555,6 +1556,14 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) { Printer << "lazy cache variable for type metadata for "; print(Node->getChild(0)); return nullptr; + case Node::Kind::AssociatedConformanceDescriptor: + Printer << "associated conformance descriptor for "; + print(Node->getChild(0)); + Printer << "."; + print(Node->getChild(1)); + Printer << ": "; + print(Node->getChild(2)); + return nullptr; case Node::Kind::AssociatedTypeDescriptor: Printer << "associated type descriptor for "; print(Node->getChild(0)); diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp index c1d0b271ea4c5..2549d1a04bf72 100644 --- a/lib/Demangling/OldRemangler.cpp +++ b/lib/Demangling/OldRemangler.cpp @@ -884,6 +884,10 @@ void Remangler::mangleAssociatedTypeDescriptor(Node *node) { Out << ""; } +void Remangler::mangleAssociatedConformanceDescriptor(Node *node) { + Out << ""; +} + void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) { Out << "Wt"; mangleChildNodes(node); // protocol conformance, identifier diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp index 0568b6fa3981b..f7ffe88252d27 100644 --- a/lib/Demangling/Remangler.cpp +++ b/lib/Demangling/Remangler.cpp @@ -574,6 +574,11 @@ void Remangler::mangleAssociatedTypeDescriptor(Node *node) { Buffer << "Tl"; } +void Remangler::mangleAssociatedConformanceDescriptor(Node *node) { + mangleChildNodes(node); + Buffer << "Tn"; +} + void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) { mangleChildNodes(node); // protocol conformance, identifier Buffer << "Wt"; diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 171d3fcd8e9f9..d48d0294270db 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -3387,6 +3387,26 @@ llvm::GlobalValue *IRGenModule::defineAssociatedTypeDescriptor( return defineAlias(entity, definition); } +llvm::Constant *IRGenModule::getAddrOfAssociatedConformanceDescriptor( + AssociatedConformance conformance) { + auto entity = LinkEntity::forAssociatedConformanceDescriptor( + conformance.getSourceProtocol(), + conformance.getAssociation(), + conformance.getAssociatedRequirement()); + return getAddrOfLLVMVariable(entity, getPointerAlignment(), ConstantInit(), + ProtocolRequirementStructTy, DebugTypeInfo()); +} + +llvm::GlobalValue *IRGenModule::defineAssociatedConformanceDescriptor( + ProtocolDecl *proto, + CanType subject, + ProtocolDecl *requirement, + llvm::Constant *definition) { + auto entity = LinkEntity::forAssociatedConformanceDescriptor(proto, subject, + requirement); + return defineAlias(entity, definition); +} + llvm::Constant *IRGenModule::getAddrOfProtocolConformanceDescriptor( const NormalProtocolConformance *conformance, ConstantInit definition) { diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 4b11cae3e896f..f0198cfa31dfd 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -709,6 +709,16 @@ namespace { B.getAddrOfCurrentPosition(IGM.ProtocolRequirementStructTy)); } + if (entry.isAssociatedConformance()) { + // Define the associated conformance descriptor to point to the + // current position in the protocol descriptor. + IGM.defineAssociatedConformanceDescriptor( + Proto, + entry.getAssociatedConformancePath(), + entry.getAssociatedConformanceRequirement(), + B.getAddrOfCurrentPosition(IGM.ProtocolRequirementStructTy)); + } + auto reqt = B.beginStruct(IGM.ProtocolRequirementStructTy); auto info = getRequirementInfo(entry); diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index b1ddf67c8d577..0cf4f020ec378 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -2500,10 +2500,30 @@ static llvm::Value * emitAssociatedTypeWitnessTableRef(IRGenFunction &IGF, llvm::Value *parentMetadata, llvm::Value *wtable, - WitnessIndex index, + AssociatedConformance conformance, llvm::Value *associatedTypeMetadata) { - llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, wtable, - index.forProtocolWitnessTable()); + auto sourceProtocol = conformance.getSourceProtocol(); + llvm::Value *witness; + if (IGF.IGM.isResilient(sourceProtocol, ResilienceExpansion::Maximal)) { + // For resilient protocols, use the associated conformance descriptor to + // determine the index. + auto assocConformanceDescriptor = + IGF.IGM.getAddrOfAssociatedConformanceDescriptor(conformance); + + auto index = + computeResilientWitnessTableIndex(IGF, sourceProtocol, + assocConformanceDescriptor); + + witness = emitInvariantLoadOfOpaqueWitness(IGF, wtable, index); + } else { + // For non-resilient protocols, the index is a constant. + auto &pi = IGF.IGM.getProtocolInfo(sourceProtocol, + ProtocolInfoKind::RequirementSignature); + + auto index = pi.getAssociatedConformanceIndex(conformance); + witness = emitInvariantLoadOfOpaqueWitness(IGF, wtable, + index.forProtocolWitnessTable()); + } // Cast the witness to the appropriate function type. auto sig = IGF.IGM.getAssociatedTypeWitnessTableAccessFunctionSignature(); @@ -2663,14 +2683,17 @@ MetadataResponse MetadataPath::followComponent(IRGenFunction &IGF, if (!source) return MetadataResponse(); - WitnessIndex index(component.getPrimaryIndex(), /*prefix*/ false); auto sourceMetadata = IGF.emitTypeMetadataRef(sourceType); auto associatedMetadata = IGF.emitTypeMetadataRef(sourceKey.Type); auto sourceWTable = source.getMetadata(); + AssociatedConformance associatedConformanceRef(sourceProtocol, + association, + associatedRequirement); auto associatedWTable = emitAssociatedTypeWitnessTableRef(IGF, sourceMetadata, sourceWTable, - index, associatedMetadata); + associatedConformanceRef, + associatedMetadata); setProtocolWitnessTableName(IGF.IGM, associatedWTable, sourceKey.Type, associatedRequirement); @@ -3396,13 +3419,7 @@ Signature IRGenModule::getAssociatedTypeMetadataAccessFunctionSignature() { return Signature(fnType, attrs, SwiftCC); } -/// Compute the index into a witness table for a resilient protocol given -/// a reference to a descriptor of one of the requirements in that witness -/// table. -/// -/// Given an index into the witness table for a resilient protocol that -/// was compiuted -static llvm::Value *computeResilientWitnessTableIndex( +llvm::Value *irgen::computeResilientWitnessTableIndex( IRGenFunction &IGF, ProtocolDecl *proto, llvm::Constant *reqtDescriptor) { diff --git a/lib/IRGen/GenProto.h b/lib/IRGen/GenProto.h index 69dfee86c8acd..42ea4f712adef 100644 --- a/lib/IRGen/GenProto.h +++ b/lib/IRGen/GenProto.h @@ -70,6 +70,14 @@ namespace irgen { SILDeclRef member, ProtocolConformanceRef conformance); + /// Compute the index into a witness table for a resilient protocol given + /// a reference to a descriptor of one of the requirements in that witness + /// table. + llvm::Value *computeResilientWitnessTableIndex( + IRGenFunction &IGF, + ProtocolDecl *proto, + llvm::Constant *reqtDescriptor); + /// Given a type T and an associated type X of some protocol P to /// which T conforms, return the type metadata for T.X. /// diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h index a00005980ed1e..edd77135904cc 100644 --- a/lib/IRGen/IRGenMangler.h +++ b/lib/IRGen/IRGenMangler.h @@ -184,6 +184,19 @@ class IRGenMangler : public Mangle::ASTMangler { return finalize(); } + std::string mangleAssociatedConformanceDescriptor( + const ProtocolDecl *proto, + CanType subject, + const ProtocolDecl *requirement) { + beginMangling(); + appendAnyGenericType(proto); + bool isFirstAssociatedTypeIdentifier = true; + appendAssociatedTypePath(subject, isFirstAssociatedTypeIdentifier); + appendProtocolName(requirement); + appendOperator("Tn"); + return finalize(); + } + std::string mangleProtocolConformanceDescriptor( const ProtocolConformance *Conformance) { beginMangling(); @@ -413,13 +426,6 @@ class IRGenMangler : public Mangle::ASTMangler { std::string manglePartialApplyForwarder(StringRef FuncName); - std::string mangleForProtocolDescriptor(ProtocolType *Proto) { - beginMangling(); - appendProtocolName(Proto->getDecl(), /*allowStandardSubstitution=*/false); - appendOperator("P"); - return finalize(); - } - std::string mangleTypeForForeignMetadataUniquing(Type type) { return mangleTypeWithoutPrefix(type); } diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h index 90f506d1b8e9a..b9efb2e9ccb4f 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -1234,6 +1234,13 @@ private: \ llvm::GlobalValue *defineAssociatedTypeDescriptor( AssociatedTypeDecl *assocType, llvm::Constant *definition); + llvm::Constant *getAddrOfAssociatedConformanceDescriptor( + AssociatedConformance conformance); + llvm::GlobalValue *defineAssociatedConformanceDescriptor( + ProtocolDecl *proto, + CanType subject, + ProtocolDecl *requirement, + llvm::Constant *definition); llvm::Constant *getAddrOfProtocolDescriptor(ProtocolDecl *D, ConstantInit definition = ConstantInit()); diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp index b4f396cdbbe0e..6562b5093acac 100644 --- a/lib/IRGen/Linking.cpp +++ b/lib/IRGen/Linking.cpp @@ -179,6 +179,14 @@ std::string LinkEntity::mangleAsString() const { return mangler.mangleAssociatedTypeDescriptor( cast(getDecl())); + case Kind::AssociatedConformanceDescriptor: { + auto assocConformance = getAssociatedConformance(); + return mangler.mangleAssociatedConformanceDescriptor( + cast(getDecl()), + assocConformance.first, + assocConformance.second); + } + case Kind::ProtocolConformanceDescriptor: return mangler.mangleProtocolConformanceDescriptor( cast(getProtocolConformance())); @@ -449,6 +457,7 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const { return getSILLinkage(getDeclLinkage(getterDecl), forDefinition); } + case Kind::AssociatedConformanceDescriptor: case Kind::ObjCClass: case Kind::ObjCMetaclass: case Kind::SwiftMetaclassStub: @@ -586,6 +595,7 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const { // FIXME: Removing this triggers a linker bug return true; + case Kind::AssociatedConformanceDescriptor: case Kind::SwiftMetaclassStub: case Kind::ClassMetadataBaseOffset: case Kind::PropertyDescriptor: diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp index 6011b3c3fdf10..68e0d42ffd9d2 100644 --- a/lib/TBDGen/TBDGen.cpp +++ b/lib/TBDGen/TBDGen.cpp @@ -99,6 +99,15 @@ void TBDGenVisitor::addAssociatedTypeDescriptor(AssociatedTypeDecl *assocType) { addSymbol(entity); } +void TBDGenVisitor::addAssociatedConformanceDescriptor( + ProtocolDecl *proto, + CanType subject, + ProtocolDecl *requirement) { + auto entity = LinkEntity::forAssociatedConformanceDescriptor(proto, subject, + requirement); + addSymbol(entity); +} + void TBDGenVisitor::addConformances(DeclContext *DC) { for (auto conformance : DC->getLocalConformances()) { auto protocol = conformance->getProtocol(); @@ -409,6 +418,20 @@ void TBDGenVisitor::visitProtocolDecl(ProtocolDecl *PD) { if (protocolDescriptorHasRequirements(PD)) addProtocolRequirementsBaseDescriptor(PD); + for (const auto &req : PD->getRequirementSignature()) { + if (req.getKind() != RequirementKind::Conformance) + continue; + + // Skip inherited requirements. + if (req.getFirstType()->isEqual(PD->getProtocolSelfType())) + continue; + + addAssociatedConformanceDescriptor( + PD, + req.getFirstType()->getCanonicalType(), + req.getSecondType()->castTo()->getDecl()); + } + for (auto *member : PD->getMembers()) { if (PD->isResilient()) { if (auto *funcDecl = dyn_cast(member)) { diff --git a/lib/TBDGen/TBDGenVisitor.h b/lib/TBDGen/TBDGenVisitor.h index bf514913920a4..9db482ea1add8 100644 --- a/lib/TBDGen/TBDGenVisitor.h +++ b/lib/TBDGen/TBDGenVisitor.h @@ -66,6 +66,9 @@ class TBDGenVisitor : public ASTVisitor { void addProtocolRequirementsBaseDescriptor(ProtocolDecl *proto); void addAssociatedTypeDescriptor(AssociatedTypeDecl *assocType); + void addAssociatedConformanceDescriptor(ProtocolDecl *proto, + CanType subject, + ProtocolDecl *requirement); public: TBDGenVisitor(tapi::internal::InterfaceFile &symbols, diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt index 58fe55d8a7b58..35fe8a3acfb13 100644 --- a/test/Demangle/Inputs/manglings.txt +++ b/test/Demangle/Inputs/manglings.txt @@ -331,3 +331,4 @@ $S2t21QP22ProtocolTypeAliasThingayAA4BlahV5SomeQa_GSgD ---> t2.Blah.SomeQ as t2. A.h(A) -> ()inlined generic function <(A, A1)> of $S1T19protocol_resilience17ResilientProtocolPTl --> associated type descriptor for T $S18resilient_protocol21ResilientBaseProtocolTL --> protocol requirements base descriptor for resilient_protocol.ResilientBaseProtocol +$S1t1PP10AssocType2_AA1QTn --> associated conformance descriptor for t.P.AssocType2: t.Q diff --git a/test/IRGen/protocol_resilience_descriptors.swift b/test/IRGen/protocol_resilience_descriptors.swift index cc7ccc1dc8fc3..7dd512ee44c93 100644 --- a/test/IRGen/protocol_resilience_descriptors.swift +++ b/test/IRGen/protocol_resilience_descriptors.swift @@ -20,15 +20,16 @@ // Protocol requirements base descriptor // CHECK-DEFINITION: @"$S18resilient_protocol21ResilientBaseProtocolTL" ={{( dllexport)?}}{{( protected)?}} alias %swift.protocol_requirement, getelementptr (%swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds (<{ i32, i32, i32, i32, i32, i32, %swift.protocol_requirement }>, <{ i32, i32, i32, i32, i32, i32, %swift.protocol_requirement }>* @"$S18resilient_protocol21ResilientBaseProtocolMp", i32 0, i32 6), i32 -1) -// Associated type requirement aliases +// Associated type and conformance // CHECK-DEFINITION: @"$S1T18resilient_protocol24ProtocolWithRequirementsPTl" ={{( dllexport)?}}{{( protected)?}} alias +// CHECK-DEFINITION: @"$S18resilient_protocol29ProtocolWithAssocTypeDefaultsP2T2_AA014OtherResilientC0Tn" ={{( dllexport)?}}{{( protected)?}} alias // Default associated type witnesses // CHECK-DEFINITION-LABEL: define internal swiftcc %swift.metadata_response @"$S2T118resilient_protocol29ProtocolWithAssocTypeDefaultsPTM" // CHECK-DEFINITION-LABEL: define internal swiftcc %swift.metadata_response @"$S2T218resilient_protocol29ProtocolWithAssocTypeDefaultsPTM" -// CHECK-DEFINITION: getelementptr inbounds i8*, i8** [[WTABLE:%.*]], i32 1 +// CHECK-DEFINITION: getelementptr inbounds i8*, i8** [[WTABLE:%.*]], i32 2 // CHECK-DEFINITION: call{{.*}}S18resilient_protocol7WrapperVMa import resilient_protocol @@ -74,3 +75,12 @@ public func assocTypeMetadata(_: PWR.Type) -> PWR // CHECK-USAGE: load i8*, i8** [[WITNESS_ADDR]], align {{(4|8)}} return PWR.T.self } + +func useOtherResilientProtocol(_: T.Type) { } + +// CHECK-USAGE: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$S31protocol_resilience_descriptors23extractAssocConformanceyyx010resilient_A0012ProtocolWithE12TypeDefaultsRzlF" +public func extractAssocConformance(_: T) { + // CHECK-USAGE: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** %T.ProtocolWithAssocTypeDefaults, [[INT]] udiv ([[INT]] sub ([[INT]] ptrtoint (%swift.protocol_requirement* @"$S2T218resilient_protocol29ProtocolWithAssocTypeDefaultsPTl" to [[INT]]), [[INT]] ptrtoint (%swift.protocol_requirement* @"$S18resilient_protocol29ProtocolWithAssocTypeDefaultsTL" to [[INT]])), [[INT]] 8) + // CHECK-USAGE: load i8*, i8** [[WITNESS_ADDR]] + useOtherResilientProtocol(T.T2.self) +} diff --git a/test/Inputs/resilient_protocol.swift b/test/Inputs/resilient_protocol.swift index 4e1a1e8b7f389..e6dfcb8dd7688 100644 --- a/test/Inputs/resilient_protocol.swift +++ b/test/Inputs/resilient_protocol.swift @@ -28,9 +28,9 @@ public protocol ProtocolWithRequirements { func second() } -public struct Wrapper { } +public struct Wrapper: OtherResilientProtocol { } public protocol ProtocolWithAssocTypeDefaults { associatedtype T1 = Self - associatedtype T2 = Wrapper + associatedtype T2: OtherResilientProtocol = Wrapper }