Skip to content

Commit 66712ce

Browse files
committed
[Sema] introduce InverseType
This type will become the corresponding type that is resolved for an `InverseTypeRepr`. This kind of type is not expected to appear past type checking (currently, not even past requirement lowering!).
1 parent 7feb622 commit 66712ce

File tree

14 files changed

+123
-1
lines changed

14 files changed

+123
-1
lines changed

include/swift/AST/TypeMatcher.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,13 @@ class TypeMatcher {
497497
sugaredFirstType);
498498
}
499499

500+
bool visitInverseType(CanInverseType firstInverse,
501+
Type secondType,
502+
Type sugaredFirstType) {
503+
// FIXME: If this visitor is reached, determine whether it should've been.
504+
llvm_unreachable("Yahaha! You found me!");
505+
}
506+
500507
bool visitLValueType(CanLValueType firstLValue, Type secondType,
501508
Type sugaredFirstType) {
502509
if (auto secondLValue = secondType->getAs<LValueType>()) {

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ ARTIFICIAL_TYPE(SILMoveOnlyWrapped, Type)
180180
ALWAYS_CANONICAL_ARTIFICIAL_TYPE(SILPack, Type)
181181
ARTIFICIAL_TYPE(SILToken, Type)
182182
TYPE(ProtocolComposition, Type)
183+
UNCHECKED_TYPE(Inverse, Type)
183184
TYPE(ParameterizedProtocol, Type)
184185
TYPE(Existential, Type)
185186
TYPE(LValue, Type)

include/swift/AST/Types.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1528,6 +1528,39 @@ class NominalOrBoundGenericNominalType : public AnyGenericType {
15281528
};
15291529
DEFINE_EMPTY_CAN_TYPE_WRAPPER(NominalOrBoundGenericNominalType, AnyGenericType)
15301530

1531+
/// InverseType represents the "inverse" of a ProtocolType as a constraint.
1532+
/// An inverse represents the _absence_ of an implicit constraint to the given
1533+
/// protocol. It is not a real type.
1534+
class InverseType final : public TypeBase {
1535+
Type protocol;
1536+
1537+
// The Error type is always canonical.
1538+
InverseType(Type type,
1539+
const ASTContext *canonicalContext,
1540+
RecursiveTypeProperties properties)
1541+
: TypeBase(TypeKind::Inverse, canonicalContext, properties),
1542+
protocol(type) {
1543+
assert(protocol->is<ProtocolType>());
1544+
}
1545+
1546+
public:
1547+
/// Produce an inverse constraint type for the given protocol type.
1548+
static Type get(Type protocolType);
1549+
1550+
1551+
Type getInvertedProtocol() const {
1552+
return protocol;
1553+
}
1554+
1555+
// Implement isa/cast/dyncast/etc.
1556+
static bool classof(const TypeBase *T) {
1557+
return T->getKind() == TypeKind::Inverse;
1558+
}
1559+
};
1560+
BEGIN_CAN_TYPE_WRAPPER(InverseType, Type)
1561+
PROXY_CAN_TYPE_SIMPLE_GETTER(getInvertedProtocol)
1562+
END_CAN_TYPE_WRAPPER(InverseType, Type)
1563+
15311564
/// ErrorType - Represents the type of an erroneously constructed declaration,
15321565
/// expression, or type. When creating ErrorTypes, an associated error
15331566
/// diagnostic should always be emitted. That way when later stages of
@@ -7217,7 +7250,8 @@ inline bool TypeBase::isConstraintType() const {
72177250
inline bool CanType::isConstraintTypeImpl(CanType type) {
72187251
return (isa<ProtocolType>(type) ||
72197252
isa<ProtocolCompositionType>(type) ||
7220-
isa<ParameterizedProtocolType>(type));
7253+
isa<ParameterizedProtocolType>(type) ||
7254+
isa<InverseType>(type));
72217255
}
72227256

72237257
inline bool TypeBase::isExistentialType() {

lib/AST/ASTContext.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3821,6 +3821,30 @@ Type ExistentialMetatypeType::getExistentialInstanceType() {
38213821
return ExistentialType::get(getInstanceType());
38223822
}
38233823

3824+
Type InverseType::get(Type protocol) {
3825+
auto &C = protocol->getASTContext();
3826+
llvm_unreachable("TODO");
3827+
// // ExistentialMetatypeType is already an existential type.
3828+
// if (constraint->is<ExistentialMetatypeType>())
3829+
// return constraint;
3830+
//
3831+
// bool printWithAny = true;
3832+
// if (constraint->isEqual(C.TheAnyType) || constraint->isAnyObject())
3833+
// printWithAny = false;
3834+
//
3835+
// auto properties = constraint->getRecursiveProperties();
3836+
// auto arena = getArena(properties);
3837+
//
3838+
// auto &entry = C.getImpl().getArena(arena).ExistentialTypes[constraint];
3839+
// if (entry)
3840+
// return entry;
3841+
//
3842+
// const ASTContext *canonicalContext = constraint->isCanonical() ? &C : nullptr;
3843+
// return entry = new (C, arena) ExistentialType(constraint, printWithAny,
3844+
// canonicalContext,
3845+
// properties);
3846+
}
3847+
38243848
ModuleType *ModuleType::get(ModuleDecl *M) {
38253849
ASTContext &C = M->getASTContext();
38263850

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4318,6 +4318,12 @@ namespace {
43184318
printFoot();
43194319
}
43204320

4321+
void visitInverseType(InverseType *T, StringRef label) {
4322+
printCommon("inverse_type", label);
4323+
printRec(T->getInvertedProtocol());
4324+
printFoot();
4325+
}
4326+
43214327
void visitLValueType(LValueType *T, StringRef label) {
43224328
printCommon("lvalue_type", label);
43234329
printRec(T->getObjectType());

lib/AST/ASTMangler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,9 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
14011401
case TypeKind::LValue:
14021402
llvm_unreachable("@lvalue types should not occur in function interfaces");
14031403

1404+
case TypeKind::Inverse:
1405+
llvm_unreachable("inverse types should not appear in interfaces");
1406+
14041407
case TypeKind::InOut:
14051408
appendType(cast<InOutType>(tybase)->getObjectType(), sig, forDecl);
14061409
return appendOperator("z");

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6201,6 +6201,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
62016201
Printer << "_";
62026202
}
62036203

6204+
void visitInverseType(InverseType *T) {
6205+
Printer << "~";
6206+
visit(T->getInvertedProtocol());
6207+
}
6208+
62046209
void visitPlaceholderType(PlaceholderType *T) {
62056210
if (Options.PrintTypesForDebugging) {
62066211
Printer << "<<placeholder for ";

lib/AST/ExistentialGeneralization.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ class Generalizer : public CanTypeVisitor<Generalizer, Type> {
110110
origType->hasExplicitAnyObject());
111111
}
112112

113+
Type visitInverseType(CanInverseType type) {
114+
llvm_unreachable("todo: determine how to handle inverses for Generalizer");
115+
}
116+
113117
// Generalize the type arguments of nominal types.
114118
Type visitBoundGenericType(CanBoundGenericType origType) {
115119
return generalizeGenericArguments(origType->getDecl(), origType);

lib/AST/Type.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ bool CanType::isReferenceTypeImpl(CanType type, const GenericSignatureImpl *sig,
299299
case TypeKind::Module:
300300
case TypeKind::LValue:
301301
case TypeKind::InOut:
302+
case TypeKind::Inverse:
302303
case TypeKind::TypeVariable:
303304
case TypeKind::Placeholder:
304305
case TypeKind::BoundGenericEnum:
@@ -1852,6 +1853,12 @@ CanType TypeBase::computeCanonicalType() {
18521853
Result = ParameterizedProtocolType::get(C, Base, CanArgs);
18531854
break;
18541855
}
1856+
case TypeKind::Inverse: {
1857+
auto *inverse = cast<InverseType>(this);
1858+
auto protocol = inverse->getInvertedProtocol()->getCanonicalType();
1859+
Result = InverseType::get(protocol).getPointer();
1860+
break;
1861+
}
18551862
case TypeKind::Existential: {
18561863
auto *existential = cast<ExistentialType>(this);
18571864
auto constraint = existential->getConstraintType()->getCanonicalType();
@@ -5107,6 +5114,20 @@ case TypeKind::Id:
51075114
return ExistentialType::get(constraint);
51085115
}
51095116

5117+
case TypeKind::Inverse: {
5118+
auto *inverse = cast<InverseType>(base);
5119+
auto protocol =
5120+
inverse->getInvertedProtocol().transformWithPosition(pos, fn);
5121+
if (!protocol || protocol->hasError())
5122+
return protocol;
5123+
5124+
if (protocol.getPointer() ==
5125+
inverse->getInvertedProtocol().getPointer())
5126+
return *this;
5127+
5128+
return InverseType::get(protocol);
5129+
}
5130+
51105131
case TypeKind::ProtocolComposition: {
51115132
auto pc = cast<ProtocolCompositionType>(base);
51125133
SmallVector<Type, 4> substMembers;
@@ -5367,6 +5388,7 @@ ReferenceCounting TypeBase::getReferenceCounting() {
53675388
case TypeKind::Module:
53685389
case TypeKind::LValue:
53695390
case TypeKind::InOut:
5391+
case TypeKind::Inverse:
53705392
case TypeKind::TypeVariable:
53715393
case TypeKind::Placeholder:
53725394
case TypeKind::BoundGenericEnum:

lib/AST/TypeWalker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ class Traversal : public TypeVisitor<Traversal, bool>
209209
return doIt(ty->getConstraintType());
210210
}
211211

212+
bool visitInverseType(InverseType *ty) {
213+
return doIt(ty->getInvertedProtocol());
214+
}
215+
212216
bool visitLValueType(LValueType *ty) {
213217
return doIt(ty->getObjectType());
214218
}

0 commit comments

Comments
 (0)