2424#include " swift/AST/ExtInfo.h"
2525#include " swift/AST/GenericParamKey.h"
2626#include " swift/AST/Identifier.h"
27+ #include " swift/AST/KnownProtocols.h"
2728#include " swift/AST/Ownership.h"
2829#include " swift/AST/ProtocolConformanceRef.h"
2930#include " swift/AST/Requirement.h"
@@ -100,7 +101,6 @@ class ProtocolConformance;
100101enum PointerTypeKind : unsigned ;
101102struct ValueOwnershipKind ;
102103class ErrorExpr ;
103- enum class KnownProtocolKind : uint8_t ;
104104
105105typedef CanTypeWrapper<SILFunctionType> CanSILFunctionType;
106106
@@ -1534,6 +1534,48 @@ class NominalOrBoundGenericNominalType : public AnyGenericType {
15341534};
15351535DEFINE_EMPTY_CAN_TYPE_WRAPPER (NominalOrBoundGenericNominalType, AnyGenericType)
15361536
1537+ // / InverseType represents the "inverse" of a ProtocolType as a constraint.
1538+ // / An inverse represents the _absence_ of an implicit constraint to the given
1539+ // / protocol.
1540+ // /
1541+ // / Otherwise, an inverse is not a real type! It's an annotation for other types
1542+ // / to signal whether an implicit requirement on that type should be omitted.
1543+ // / Because that annotation is expressed in the surface language as if it _were_
1544+ // / a type (that is, as a type constraint) we still model it as a Type through
1545+ // / typechecking.
1546+ class InverseType final : public TypeBase {
1547+ Type protocol;
1548+
1549+ InverseType (Type type,
1550+ const ASTContext *canonicalContext,
1551+ RecursiveTypeProperties properties)
1552+ : TypeBase(TypeKind::Inverse, canonicalContext, properties),
1553+ protocol (type) {
1554+ assert (protocol->is <ProtocolType>());
1555+ }
1556+
1557+ public:
1558+ // / Produce an inverse constraint type for the given protocol type.
1559+ static Type get (Type protocolType);
1560+
1561+
1562+ // / Obtain the underlying \c ProtocolType that was inverted.
1563+ Type getInvertedProtocol () const {
1564+ return protocol;
1565+ }
1566+
1567+ // / Get known kind of inverse this type represents.
1568+ InvertibleProtocolKind getInverseKind () const ;
1569+
1570+ // Implement isa/cast/dyncast/etc.
1571+ static bool classof (const TypeBase *T) {
1572+ return T->getKind () == TypeKind::Inverse;
1573+ }
1574+ };
1575+ BEGIN_CAN_TYPE_WRAPPER (InverseType, Type)
1576+ PROXY_CAN_TYPE_SIMPLE_GETTER(getInvertedProtocol)
1577+ END_CAN_TYPE_WRAPPER(InverseType, Type)
1578+
15371579// / ErrorType - Represents the type of an erroneously constructed declaration,
15381580// / expression, or type. When creating ErrorTypes, an associated error
15391581// / diagnostic should always be emitted. That way when later stages of
@@ -5739,13 +5781,37 @@ class ProtocolCompositionType final : public TypeBase,
57395781 public llvm::FoldingSetNode,
57405782 private llvm::TrailingObjects<ProtocolCompositionType, Type> {
57415783 friend TrailingObjects;
5784+
5785+ // TODO(kavon): this could probably be folded into the existing Bits field
5786+ // or we could just store the InverseType's in the Members array.
5787+ InvertibleProtocolSet Inverses;
57425788
57435789public:
57445790 // / Retrieve an instance of a protocol composition type with the
5745- // / given set of members.
5791+ // / given set of members. A "hidden member" is an implicit constraint that
5792+ // / is present for all protocol compositions.
5793+ // /
5794+ // / \param Members the regular members of this composition.
5795+ // / \param Inverses the set of inverses that are a member of the composition,
5796+ // / i.e., if \c IP is in this set, then \c ~IP is a member of
5797+ // / this composition.
5798+ // / \param HasExplicitAnyObject indicates whether this composition should be
5799+ // / treated as if \c AnyObject was a member.
57465800 static Type get (const ASTContext &C, ArrayRef<Type> Members,
5801+ InvertibleProtocolSet Inverses,
57475802 bool HasExplicitAnyObject);
57485803
5804+ // / Retrieve an instance of a protocol composition type with the
5805+ // / given set of members. Assumes no inverses are present in \c Members.
5806+ static Type get (const ASTContext &C, ArrayRef<Type> Members,
5807+ bool HasExplicitAnyObject);
5808+
5809+ // / Constructs a protocol composition corresponding to the `Any` type.
5810+ static Type theAnyType (const ASTContext &C);
5811+
5812+ // / Constructs a protocol composition corresponding to the `AnyObject` type.
5813+ static Type theAnyObjectType (const ASTContext &C);
5814+
57495815 // / Canonical protocol composition types are minimized only to a certain
57505816 // / degree to preserve ABI compatibility. This routine enables performing
57515817 // / slower, but stricter minimization at need (e.g. redeclaration checking).
@@ -5768,11 +5834,14 @@ class ProtocolCompositionType final : public TypeBase,
57685834 return {getTrailingObjects<Type>(), Bits.ProtocolCompositionType .Count };
57695835 }
57705836
5837+ InvertibleProtocolSet getInverses () const { return Inverses; }
5838+
57715839 void Profile (llvm::FoldingSetNodeID &ID) {
5772- Profile (ID, getMembers (), hasExplicitAnyObject ());
5840+ Profile (ID, getMembers (), getInverses (), hasExplicitAnyObject ());
57735841 }
57745842 static void Profile (llvm::FoldingSetNodeID &ID,
57755843 ArrayRef<Type> Members,
5844+ InvertibleProtocolSet Inverses,
57765845 bool HasExplicitAnyObject);
57775846
57785847 // / True if the composition requires the concrete conforming type to
@@ -5793,12 +5862,15 @@ class ProtocolCompositionType final : public TypeBase,
57935862private:
57945863 static ProtocolCompositionType *build (const ASTContext &C,
57955864 ArrayRef<Type> Members,
5865+ InvertibleProtocolSet Inverses,
57965866 bool HasExplicitAnyObject);
57975867
57985868 ProtocolCompositionType (const ASTContext *ctx, ArrayRef<Type> members,
5869+ InvertibleProtocolSet inverses,
57995870 bool hasExplicitAnyObject,
58005871 RecursiveTypeProperties properties)
5801- : TypeBase (TypeKind::ProtocolComposition, /* Context=*/ ctx, properties) {
5872+ : TypeBase (TypeKind::ProtocolComposition, /* Context=*/ ctx, properties),
5873+ Inverses (inverses) {
58025874 Bits.ProtocolCompositionType .HasExplicitAnyObject = hasExplicitAnyObject;
58035875 Bits.ProtocolCompositionType .Count = members.size ();
58045876 std::uninitialized_copy (members.begin (), members.end (),
@@ -7223,7 +7295,8 @@ inline bool TypeBase::isConstraintType() const {
72237295inline bool CanType::isConstraintTypeImpl (CanType type) {
72247296 return (isa<ProtocolType>(type) ||
72257297 isa<ProtocolCompositionType>(type) ||
7226- isa<ParameterizedProtocolType>(type));
7298+ isa<ParameterizedProtocolType>(type) ||
7299+ isa<InverseType>(type));
72277300}
72287301
72297302inline bool TypeBase::isExistentialType () {
@@ -7239,6 +7312,7 @@ inline bool CanType::isExistentialTypeImpl(CanType type) {
72397312 isa<ProtocolCompositionType>(type) ||
72407313 isa<ExistentialType>(type) ||
72417314 isa<ParameterizedProtocolType>(type);
7315+ // TODO(kavon): treat InverseType as an existential, etc?
72427316}
72437317
72447318inline bool CanType::isAnyExistentialTypeImpl (CanType type) {
0 commit comments