@@ -1671,8 +1671,10 @@ ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
16711671 if (auto nominal = type->getAnyNominal ()) {
16721672 ImplicitKnownProtocolConformanceRequest icvRequest{nominal, *kp};
16731673 if (getASTContext ().evaluator .hasActiveRequest (icvRequest) ||
1674- getASTContext ().evaluator .hasActiveRequest (request))
1674+ getASTContext ().evaluator .hasActiveRequest (request)) {
1675+ assert (!getInvertibleProtocolKind (*kp));
16751676 return ProtocolConformanceRef::forInvalid ();
1677+ }
16761678 }
16771679 }
16781680
@@ -1731,13 +1733,35 @@ static ProtocolConformanceRef getBuiltinTupleTypeConformance(
17311733 return ProtocolConformanceRef::forMissingOrInvalid (type, protocol);
17321734}
17331735
1736+ using EitherFunctionType =
1737+ llvm::PointerUnion<const SILFunctionType *, const FunctionType *>;
1738+
17341739// / Whether the given function type conforms to Sendable.
1735- static bool isSendableFunctionType (const FunctionType *functionType) {
1736- if (functionType->isSendable ())
1737- return true ;
1740+ static bool isSendableFunctionType (EitherFunctionType eitherFnTy) {
1741+ FunctionTypeRepresentation representation;
1742+
1743+ if (auto silFnTy = eitherFnTy.dyn_cast <const SILFunctionType *>()) {
1744+ if (silFnTy->isSendable ())
1745+ return true ;
1746+
1747+ // convert SILFunctionTypeRepresentation -> FunctionTypeRepresentation
1748+ auto converted = convertRepresentation (silFnTy->getRepresentation ());
1749+ if (!converted)
1750+ return false ;
1751+
1752+ representation = *converted;
1753+
1754+ } else {
1755+ auto functionType = eitherFnTy.get <const FunctionType *>();
1756+
1757+ if (functionType->isSendable ())
1758+ return true ;
1759+
1760+ representation = functionType->getExtInfo ().getRepresentation ();
1761+ }
17381762
17391763 // C and thin function types have no captures, so they are Sendable.
1740- switch (functionType-> getExtInfo (). getRepresentation () ) {
1764+ switch (representation ) {
17411765 case FunctionTypeRepresentation::Block:
17421766 case FunctionTypeRepresentation::Swift:
17431767 return false ;
@@ -1749,41 +1773,47 @@ static bool isSendableFunctionType(const FunctionType *functionType) {
17491773}
17501774
17511775// / Whether the given function type conforms to Escapable.
1752- static bool isEscapableFunctionType (const FunctionType *functionType) {
1753- if (functionType->isNoEscape ())
1754- return false ;
1776+ static bool isEscapableFunctionType (EitherFunctionType eitherFnTy) {
1777+ if (auto silFnTy = eitherFnTy.dyn_cast <const SILFunctionType *>()) {
1778+ return !silFnTy->isNoEscape ();
1779+ }
17551780
1756- // FIXME: do we need to also include autoclosures??
1781+ auto functionType = eitherFnTy. get < const FunctionType *>();
17571782
1758- return true ;
1783+ // TODO: what about autoclosures?
1784+ return !functionType->isNoEscape ();
17591785}
17601786
17611787// / Synthesize a builtin function type conformance to the given protocol, if
17621788// / appropriate.
17631789static ProtocolConformanceRef getBuiltinFunctionTypeConformance (
1764- Type type, const FunctionType * functionType, ProtocolDecl *protocol) {
1790+ Type type, EitherFunctionType functionType, ProtocolDecl *protocol) {
17651791 ASTContext &ctx = protocol->getASTContext ();
1766- // @Sendable function types are Sendable.
1767- if (protocol->isSpecificProtocol (KnownProtocolKind::Sendable) &&
1768- isSendableFunctionType (functionType)) {
1769- return ProtocolConformanceRef (
1770- ctx.getBuiltinConformance (type, protocol,
1771- BuiltinConformanceKind::Synthesized));
1772- }
17731792
1774- // Functions cannot permanently destroy a move-only var/let
1775- // that they capture, so it's safe to copy functions, like classes.
1776- if (protocol->isSpecificProtocol (KnownProtocolKind::Copyable)) {
1793+ auto synthesizeConformance = [&]() -> ProtocolConformanceRef {
17771794 return ProtocolConformanceRef (
17781795 ctx.getBuiltinConformance (type, protocol,
17791796 BuiltinConformanceKind::Synthesized));
1780- }
1797+ };
17811798
1782- if (protocol->isSpecificProtocol (KnownProtocolKind::Escapable) &&
1783- isEscapableFunctionType (functionType)) {
1784- return ProtocolConformanceRef (
1785- ctx.getBuiltinConformance (type, protocol,
1786- BuiltinConformanceKind::Synthesized));
1799+ if (auto kp = protocol->getKnownProtocolKind ()) {
1800+ switch (*kp) {
1801+ case KnownProtocolKind::Escapable:
1802+ if (isEscapableFunctionType (functionType))
1803+ return synthesizeConformance ();
1804+ break ;
1805+ case KnownProtocolKind::Sendable:
1806+ // @Sendable function types are Sendable.
1807+ if (isSendableFunctionType (functionType))
1808+ return synthesizeConformance ();
1809+ break ;
1810+ case KnownProtocolKind::Copyable:
1811+ // Functions cannot permanently destroy a move-only var/let
1812+ // that they capture, so it's safe to copy functions, like classes.
1813+ return synthesizeConformance ();
1814+ default :
1815+ break ;
1816+ }
17871817 }
17881818
17891819 return ProtocolConformanceRef::forMissingOrInvalid (type, protocol);
@@ -1959,6 +1989,11 @@ LookupConformanceInModuleRequest::evaluate(
19591989 return getBuiltinFunctionTypeConformance (type, functionType, protocol);
19601990 }
19611991
1992+ // SIL function types in the AST can conform to protocols
1993+ if (auto silFn = type->getAs <SILFunctionType>()) {
1994+ return getBuiltinFunctionTypeConformance (type, silFn, protocol);
1995+ }
1996+
19621997 // Metatypes can conform to protocols.
19631998 if (auto metatypeType = type->getAs <AnyMetatypeType>()) {
19641999 return getBuiltinMetaTypeTypeConformance (type, metatypeType, protocol);
@@ -1969,6 +2004,18 @@ LookupConformanceInModuleRequest::evaluate(
19692004 return getBuiltinBuiltinTypeConformance (type, builtinType, protocol);
19702005 }
19712006
2007+ #ifndef NDEBUG
2008+ // Ensure we haven't missed queries for the specialty SIL types
2009+ // in the AST in conformance to one of the invertible protocols.
2010+ if (auto kp = protocol->getKnownProtocolKind ())
2011+ if (getInvertibleProtocolKind (*kp))
2012+ assert (!(type->is <SILFunctionType,
2013+ SILBoxType,
2014+ SILMoveOnlyWrappedType,
2015+ SILPackType,
2016+ SILTokenType>()));
2017+ #endif
2018+
19722019 auto nominal = type->getAnyNominal ();
19732020
19742021 // If we don't have a nominal type, there are no conformances.
0 commit comments