@@ -1671,8 +1671,10 @@ ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
1671
1671
if (auto nominal = type->getAnyNominal ()) {
1672
1672
ImplicitKnownProtocolConformanceRequest icvRequest{nominal, *kp};
1673
1673
if (getASTContext ().evaluator .hasActiveRequest (icvRequest) ||
1674
- getASTContext ().evaluator .hasActiveRequest (request))
1674
+ getASTContext ().evaluator .hasActiveRequest (request)) {
1675
+ assert (!getInvertibleProtocolKind (*kp));
1675
1676
return ProtocolConformanceRef::forInvalid ();
1677
+ }
1676
1678
}
1677
1679
}
1678
1680
@@ -1731,13 +1733,35 @@ static ProtocolConformanceRef getBuiltinTupleTypeConformance(
1731
1733
return ProtocolConformanceRef::forMissingOrInvalid (type, protocol);
1732
1734
}
1733
1735
1736
+ using EitherFunctionType =
1737
+ llvm::PointerUnion<const SILFunctionType *, const FunctionType *>;
1738
+
1734
1739
// / 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
+ }
1738
1762
1739
1763
// C and thin function types have no captures, so they are Sendable.
1740
- switch (functionType-> getExtInfo (). getRepresentation () ) {
1764
+ switch (representation ) {
1741
1765
case FunctionTypeRepresentation::Block:
1742
1766
case FunctionTypeRepresentation::Swift:
1743
1767
return false ;
@@ -1749,41 +1773,47 @@ static bool isSendableFunctionType(const FunctionType *functionType) {
1749
1773
}
1750
1774
1751
1775
// / 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
+ }
1755
1780
1756
- // FIXME: do we need to also include autoclosures??
1781
+ auto functionType = eitherFnTy. get < const FunctionType *>();
1757
1782
1758
- return true ;
1783
+ // TODO: what about autoclosures?
1784
+ return !functionType->isNoEscape ();
1759
1785
}
1760
1786
1761
1787
// / Synthesize a builtin function type conformance to the given protocol, if
1762
1788
// / appropriate.
1763
1789
static ProtocolConformanceRef getBuiltinFunctionTypeConformance (
1764
- Type type, const FunctionType * functionType, ProtocolDecl *protocol) {
1790
+ Type type, EitherFunctionType functionType, ProtocolDecl *protocol) {
1765
1791
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
- }
1773
1792
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 {
1777
1794
return ProtocolConformanceRef (
1778
1795
ctx.getBuiltinConformance (type, protocol,
1779
1796
BuiltinConformanceKind::Synthesized));
1780
- }
1797
+ };
1781
1798
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
+ }
1787
1817
}
1788
1818
1789
1819
return ProtocolConformanceRef::forMissingOrInvalid (type, protocol);
@@ -1959,6 +1989,11 @@ LookupConformanceInModuleRequest::evaluate(
1959
1989
return getBuiltinFunctionTypeConformance (type, functionType, protocol);
1960
1990
}
1961
1991
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
+
1962
1997
// Metatypes can conform to protocols.
1963
1998
if (auto metatypeType = type->getAs <AnyMetatypeType>()) {
1964
1999
return getBuiltinMetaTypeTypeConformance (type, metatypeType, protocol);
@@ -1969,6 +2004,18 @@ LookupConformanceInModuleRequest::evaluate(
1969
2004
return getBuiltinBuiltinTypeConformance (type, builtinType, protocol);
1970
2005
}
1971
2006
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
+
1972
2019
auto nominal = type->getAnyNominal ();
1973
2020
1974
2021
// If we don't have a nominal type, there are no conformances.
0 commit comments