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
@@ -1530,11 +1530,16 @@ DEFINE_EMPTY_CAN_TYPE_WRAPPER(NominalOrBoundGenericNominalType, AnyGenericType)
15301530
15311531// / InverseType represents the "inverse" of a ProtocolType as a constraint.
15321532// / An inverse represents the _absence_ of an implicit constraint to the given
1533- // / protocol. It is not a real type.
1533+ // / protocol.
1534+ // /
1535+ // / Otherwise, an inverse is not a real type! It's an annotation for other types
1536+ // / to signal whether an implicit requirement on that type should be omitted.
1537+ // / Because that annotation is expressed in the surface language as if it _were_
1538+ // / a type (that is, as a type constraint) we still model it as a Type through
1539+ // / typechecking.
15341540class InverseType final : public TypeBase {
15351541 Type protocol;
15361542
1537- // The Error type is always canonical.
15381543 InverseType (Type type,
15391544 const ASTContext *canonicalContext,
15401545 RecursiveTypeProperties properties)
@@ -1548,10 +1553,14 @@ class InverseType final : public TypeBase {
15481553 static Type get (Type protocolType);
15491554
15501555
1556+ // / Obtain the underlying \c ProtocolType that was inverted.
15511557 Type getInvertedProtocol () const {
15521558 return protocol;
15531559 }
15541560
1561+ // / Get known kind of inverse this type represents.
1562+ InvertibleProtocolKind getInverseKind () const ;
1563+
15551564 // Implement isa/cast/dyncast/etc.
15561565 static bool classof (const TypeBase *T) {
15571566 return T->getKind () == TypeKind::Inverse;
@@ -5766,13 +5775,37 @@ class ProtocolCompositionType final : public TypeBase,
57665775 public llvm::FoldingSetNode,
57675776 private llvm::TrailingObjects<ProtocolCompositionType, Type> {
57685777 friend TrailingObjects;
5778+
5779+ // TODO: this could probably be folded into the existing Bits field
5780+ // or we could just store the InverseType's in the Members array.
5781+ InvertibleProtocolSet Inverses;
57695782
57705783public:
57715784 // / Retrieve an instance of a protocol composition type with the
5772- // / given set of members.
5785+ // / given set of members. A "hidden member" is an implicit constraint that
5786+ // / is present for all protocol compositions.
5787+ // /
5788+ // / \param Members the regular members of this composition.
5789+ // / \param Inverses the set of inverses that are a member of the composition,
5790+ // / i.e., if \c IP is in this set, then \c ~IP is a member of
5791+ // / this composition.
5792+ // / \param HasExplicitAnyObject indicates whether this composition should be
5793+ // / treated as if \c AnyObject was a member.
5794+ static Type get (const ASTContext &C, ArrayRef<Type> Members,
5795+ InvertibleProtocolSet Inverses,
5796+ bool HasExplicitAnyObject);
5797+
5798+ // / Retrieve an instance of a protocol composition type with the
5799+ // / given set of members. Assumes no inverses are present in \c Members.
57735800 static Type get (const ASTContext &C, ArrayRef<Type> Members,
57745801 bool HasExplicitAnyObject);
57755802
5803+ // / Constructs a protocol composition corresponding to the `Any` type.
5804+ static Type theAnyType (const ASTContext &C);
5805+
5806+ // / Constructs a protocol composition corresponding to the `AnyObject` type.
5807+ static Type theAnyObjectType (const ASTContext &C);
5808+
57765809 // / Canonical protocol composition types are minimized only to a certain
57775810 // / degree to preserve ABI compatibility. This routine enables performing
57785811 // / slower, but stricter minimization at need (e.g. redeclaration checking).
@@ -5795,11 +5828,14 @@ class ProtocolCompositionType final : public TypeBase,
57955828 return {getTrailingObjects<Type>(), Bits.ProtocolCompositionType .Count };
57965829 }
57975830
5831+ InvertibleProtocolSet getInverses () const { return Inverses; }
5832+
57985833 void Profile (llvm::FoldingSetNodeID &ID) {
5799- Profile (ID, getMembers (), hasExplicitAnyObject ());
5834+ Profile (ID, getMembers (), getInverses (), hasExplicitAnyObject ());
58005835 }
58015836 static void Profile (llvm::FoldingSetNodeID &ID,
58025837 ArrayRef<Type> Members,
5838+ InvertibleProtocolSet Inverses,
58035839 bool HasExplicitAnyObject);
58045840
58055841 // / True if the composition requires the concrete conforming type to
@@ -5820,12 +5856,15 @@ class ProtocolCompositionType final : public TypeBase,
58205856private:
58215857 static ProtocolCompositionType *build (const ASTContext &C,
58225858 ArrayRef<Type> Members,
5859+ InvertibleProtocolSet Inverses,
58235860 bool HasExplicitAnyObject);
58245861
58255862 ProtocolCompositionType (const ASTContext *ctx, ArrayRef<Type> members,
5863+ InvertibleProtocolSet inverses,
58265864 bool hasExplicitAnyObject,
58275865 RecursiveTypeProperties properties)
5828- : TypeBase (TypeKind::ProtocolComposition, /* Context=*/ ctx, properties) {
5866+ : TypeBase (TypeKind::ProtocolComposition, /* Context=*/ ctx, properties),
5867+ Inverses (inverses) {
58295868 Bits.ProtocolCompositionType .HasExplicitAnyObject = hasExplicitAnyObject;
58305869 Bits.ProtocolCompositionType .Count = members.size ();
58315870 std::uninitialized_copy (members.begin (), members.end (),
@@ -7267,6 +7306,7 @@ inline bool CanType::isExistentialTypeImpl(CanType type) {
72677306 isa<ProtocolCompositionType>(type) ||
72687307 isa<ExistentialType>(type) ||
72697308 isa<ParameterizedProtocolType>(type);
7309+ // TODO(kavon): treat InverseType as an existential, etc?
72707310}
72717311
72727312inline bool CanType::isAnyExistentialTypeImpl (CanType type) {
0 commit comments