diff --git a/include/swift/SIL/AbstractionPattern.h b/include/swift/SIL/AbstractionPattern.h index 2fcfc2ed61259..00beef86a84a3 100644 --- a/include/swift/SIL/AbstractionPattern.h +++ b/include/swift/SIL/AbstractionPattern.h @@ -1516,6 +1516,10 @@ class AbstractionPattern { /// the abstraction pattern for its self type. AbstractionPattern getDynamicSelfSelfType() const; + /// Given that the value being abstracted is a protocol composition + /// type, return the abstraction pattern for one of its member types. + AbstractionPattern getProtocolCompositionMemberType(unsigned i) const; + /// Given that the value being abstracted is a parameterized protocol /// type, return the abstraction pattern for one of its argument types. AbstractionPattern getParameterizedProtocolArgType(unsigned i) const; diff --git a/lib/SIL/IR/AbstractionPattern.cpp b/lib/SIL/IR/AbstractionPattern.cpp index 4854b828df72f..24be977835d3e 100644 --- a/lib/SIL/IR/AbstractionPattern.cpp +++ b/lib/SIL/IR/AbstractionPattern.cpp @@ -1022,6 +1022,14 @@ AbstractionPattern AbstractionPattern::getDynamicSelfSelfType() const { cast(getType()).getSelfType()); } +AbstractionPattern +AbstractionPattern::getProtocolCompositionMemberType(unsigned argIndex) const { + assert(getKind() == Kind::Type); + return AbstractionPattern(getGenericSubstitutions(), + getGenericSignature(), + cast(getType()).getMembers()[argIndex]); +} + AbstractionPattern AbstractionPattern::getParameterizedProtocolArgType(unsigned argIndex) const { assert(getKind() == Kind::Type); @@ -2699,22 +2707,44 @@ class SubstFunctionTypePatternVisitor CanType visitParameterizedProtocolType(CanParameterizedProtocolType ppt, AbstractionPattern pattern) { // Recurse into the arguments of the parameterized protocol. - SmallVector substArgs; auto origPPT = pattern.getAs(); if (!origPPT) return ppt; + SmallVector substArgs; for (unsigned i = 0; i < ppt->getArgs().size(); ++i) { auto argTy = ppt.getArgs()[i]; auto origArgTy = pattern.getParameterizedProtocolArgType(i); - auto substEltTy = visit(argTy, origArgTy); - substArgs.push_back(substEltTy); + auto substArgTy = visit(argTy, origArgTy); + substArgs.push_back(substArgTy); } return CanType(ParameterizedProtocolType::get( TC.Context, ppt->getBaseType(), substArgs)); } + CanType visitProtocolCompositionType(CanProtocolCompositionType pct, + AbstractionPattern pattern) { + // Recurse into the arguments of the protocol composition. + auto origPCT = pattern.getAs(); + if (!origPCT) + return pct; + + SmallVector substMembers; + for (unsigned i = 0; i < pct->getMembers().size(); ++i) { + auto memberTy = CanType(pct->getMembers()[i]); + auto origMemberTy = pattern.getProtocolCompositionMemberType(i); + auto substMemberTy = visit(memberTy, origMemberTy); + substMembers.push_back(substMemberTy); + } + + return CanType(ProtocolCompositionType::get( + TC.Context, + substMembers, + pct->getInverses(), + pct->hasExplicitAnyObject())); + } + /// Visit a tuple pattern. Note that, because of vanishing tuples, /// we can't handle this case by matching a tuple type in the /// substituted type; we have to check for a tuple pattern in the diff --git a/test/SILGen/subst_function_type_existential.swift b/test/SILGen/subst_function_type_existential.swift new file mode 100644 index 0000000000000..b2685187a1690 --- /dev/null +++ b/test/SILGen/subst_function_type_existential.swift @@ -0,0 +1,20 @@ +// RUN: %target-swift-emit-silgen %s + +// https://github.com/swiftlang/swift/issues/62061 + +protocol P {} + +class C {} + +protocol Q { + associatedtype A +} + +func foo1(t: T) { + let _: (any P & C) -> T = { x in t } +} + +func foo2(t: T) { + let _: (any P & C<(T.A) -> ()>) -> T = { x in t } +} +