Skip to content

Commit d971d48

Browse files
committed
[Type System] With explicit existential types, make sure existential
metatypes always wrap the constraint type directly, and the instance type of an existential metatype is an existential type.
1 parent 733648b commit d971d48

File tree

13 files changed

+62
-13
lines changed

13 files changed

+62
-13
lines changed

include/swift/AST/Types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,6 +2734,8 @@ class ExistentialMetatypeType : public AnyMetatypeType {
27342734
static bool classof(const TypeBase *T) {
27352735
return T->getKind() == TypeKind::ExistentialMetatype;
27362736
}
2737+
2738+
Type getExistentialInstanceType();
27372739

27382740
private:
27392741
ExistentialMetatypeType(Type T, const ASTContext *C,

include/swift/SIL/SILCloner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2220,7 +2220,7 @@ visitOpenExistentialMetatypeInst(OpenExistentialMetatypeInst *Inst) {
22202220
auto openedType = Inst->getType().getASTType();
22212221
auto exType = Inst->getOperand()->getType().getASTType();
22222222
while (auto exMetatype = dyn_cast<ExistentialMetatypeType>(exType)) {
2223-
exType = exMetatype.getInstanceType();
2223+
exType = exMetatype->getExistentialInstanceType()->getCanonicalType();
22242224
openedType = cast<MetatypeType>(openedType).getInstanceType();
22252225
}
22262226
remapOpenedType(cast<OpenedArchetypeType>(openedType));

include/swift/SIL/SILInstruction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7072,7 +7072,7 @@ class InitExistentialMetatypeInst final
70727072
auto exType = getType().getASTType();
70737073
auto concreteType = getOperand()->getType().getASTType();
70747074
while (auto exMetatype = dyn_cast<ExistentialMetatypeType>(exType)) {
7075-
exType = exMetatype.getInstanceType();
7075+
exType = exMetatype->getExistentialInstanceType()->getCanonicalType();
70767076
concreteType = cast<MetatypeType>(concreteType).getInstanceType();
70777077
}
70787078
assert(exType.isExistentialType());

lib/AST/ASTContext.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3329,6 +3329,11 @@ MetatypeType::MetatypeType(Type T, const ASTContext *C,
33293329
ExistentialMetatypeType *
33303330
ExistentialMetatypeType::get(Type T, Optional<MetatypeRepresentation> repr,
33313331
const ASTContext &ctx) {
3332+
// If we're creating an existential metatype from an
3333+
// existential type, wrap the constraint type direcly.
3334+
if (auto existential = T->getAs<ExistentialType>())
3335+
T = existential->getConstraintType();
3336+
33323337
auto properties = T->getRecursiveProperties();
33333338
auto arena = getArena(properties);
33343339

@@ -3361,6 +3366,18 @@ ExistentialMetatypeType::ExistentialMetatypeType(Type T,
33613366
}
33623367
}
33633368

3369+
Type ExistentialMetatypeType::getExistentialInstanceType() {
3370+
auto instanceType = getInstanceType();
3371+
// Note that Any and AnyObject don't yet use ExistentialType.
3372+
if (getASTContext().LangOpts.EnableExplicitExistentialTypes &&
3373+
!instanceType->is<ExistentialMetatypeType>() &&
3374+
!(instanceType->isAny() || instanceType->isAnyObject())) {
3375+
instanceType = ExistentialType::get(instanceType);
3376+
}
3377+
3378+
return instanceType;
3379+
}
3380+
33643381
ModuleType *ModuleType::get(ModuleDecl *M) {
33653382
ASTContext &C = M->getASTContext();
33663383

@@ -4326,7 +4343,7 @@ GenericEnvironment *OpenedArchetypeType::getGenericEnvironment() const {
43264343

43274344
CanType OpenedArchetypeType::getAny(Type existential) {
43284345
if (auto metatypeTy = existential->getAs<ExistentialMetatypeType>()) {
4329-
auto instanceTy = metatypeTy->getInstanceType();
4346+
auto instanceTy = metatypeTy->getExistentialInstanceType();
43304347
return CanMetatypeType::get(OpenedArchetypeType::getAny(instanceTy));
43314348
}
43324349
assert(existential->isExistentialType());

lib/AST/ASTVerifier.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2067,7 +2067,10 @@ class Verifier : public ASTWalker {
20672067
abort();
20682068
}
20692069

2070-
checkSameType(E->getBase()->getType(), metatype->getInstanceType(),
2070+
auto instance = metatype->getInstanceType();
2071+
if (auto existential = metatype->getAs<ExistentialMetatypeType>())
2072+
instance = existential->getExistentialInstanceType();
2073+
checkSameType(E->getBase()->getType(), instance,
20712074
"base type of .Type expression");
20722075
verifyCheckedBase(E);
20732076
}

lib/AST/Type.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,8 @@ Type TypeBase::eraseOpenedExistential(OpenedArchetypeType *opened) {
464464
auto instanceType = metatypeType->getInstanceType();
465465
if (instanceType->hasOpenedExistential()) {
466466
instanceType = instanceType->eraseOpenedExistential(opened);
467+
if (auto existential = instanceType->getAs<ExistentialType>())
468+
instanceType = existential->getConstraintType();
467469
return ExistentialMetatypeType::get(instanceType);
468470
}
469471
}
@@ -1199,6 +1201,9 @@ Type TypeBase::replaceSelfParameterType(Type newSelf) {
11991201
/// Look through a metatype, or just return the original type if it is
12001202
/// not a metatype.
12011203
Type TypeBase::getMetatypeInstanceType() {
1204+
if (auto existentialMetaType = getAs<ExistentialMetatypeType>())
1205+
return existentialMetaType->getExistentialInstanceType();
1206+
12021207
if (auto metaTy = getAs<AnyMetatypeType>())
12031208
return metaTy->getInstanceType();
12041209

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2960,8 +2960,19 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
29602960
"value_metatype instruction must have a metatype representation");
29612961
require(MI->getOperand()->getType().isAnyExistentialType(),
29622962
"existential_metatype operand must be of protocol type");
2963+
2964+
// The result of an existential_metatype instruction is an existential
2965+
// metatype with the same constraint type as its existential operand.
29632966
auto formalInstanceTy
29642967
= MI->getType().castTo<ExistentialMetatypeType>().getInstanceType();
2968+
if (M->getASTContext().LangOpts.EnableExplicitExistentialTypes &&
2969+
formalInstanceTy->isConstraintType() &&
2970+
!(formalInstanceTy->isAny() || formalInstanceTy->isAnyObject())) {
2971+
require(MI->getOperand()->getType().is<ExistentialType>(),
2972+
"existential_metatype operand must be an existential type");
2973+
formalInstanceTy =
2974+
ExistentialType::get(formalInstanceTy)->getCanonicalType();
2975+
}
29652976
require(isLoweringOf(MI->getOperand()->getType(), formalInstanceTy),
29662977
"existential_metatype result must be formal metatype of "
29672978
"lowered operand type");

lib/SILGen/SILGenPoly.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ static ManagedValue emitTransformExistential(SILGenFunction &SGF,
220220
fromInstanceType = cast<MetatypeType>(fromInstanceType)
221221
.getInstanceType();
222222
toInstanceType = cast<ExistentialMetatypeType>(toInstanceType)
223-
.getInstanceType();
223+
->getExistentialInstanceType()->getCanonicalType();
224224
}
225225

226226
ArrayRef<ProtocolConformanceRef> conformances =

lib/Sema/CSApply.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,8 @@ namespace {
13791379
baseIsInstance = false;
13801380
isExistentialMetatype = baseMeta->is<ExistentialMetatypeType>();
13811381
baseTy = baseMeta->getInstanceType();
1382+
if (auto existential = baseTy->getAs<ExistentialType>())
1383+
baseTy = existential->getConstraintType();
13821384

13831385
// A valid reference to a static member (computed property or a method)
13841386
// declared on a protocol is only possible if result type conforms to
@@ -5346,10 +5348,8 @@ Expr *ExprRewriter::coerceSuperclass(Expr *expr, Type toType) {
53465348

53475349
while (fromInstanceType->is<AnyMetatypeType>() &&
53485350
toInstanceType->is<MetatypeType>()) {
5349-
fromInstanceType = fromInstanceType->castTo<AnyMetatypeType>()
5350-
->getInstanceType();
5351-
toInstanceType = toInstanceType->castTo<MetatypeType>()
5352-
->getInstanceType();
5351+
fromInstanceType = fromInstanceType->getMetatypeInstanceType();
5352+
toInstanceType = toInstanceType->getMetatypeInstanceType();
53535353
}
53545354

53555355
if (fromInstanceType->is<ArchetypeType>()) {
@@ -5422,7 +5422,7 @@ Expr *ExprRewriter::coerceExistential(Expr *expr, Type toType) {
54225422
toInstanceType->is<ExistentialMetatypeType>()) {
54235423
if (!fromInstanceType->is<UnresolvedType>())
54245424
fromInstanceType = fromInstanceType->castTo<AnyMetatypeType>()->getInstanceType();
5425-
toInstanceType = toInstanceType->castTo<ExistentialMetatypeType>()->getInstanceType();
5425+
toInstanceType = toInstanceType->castTo<ExistentialMetatypeType>()->getExistentialInstanceType();
54265426
}
54275427

54285428
ASTContext &ctx = cs.getASTContext();
@@ -7511,7 +7511,7 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
75117511
openedInstanceTy = metaTy->getInstanceType();
75127512
existentialInstanceTy = existentialInstanceTy
75137513
->castTo<ExistentialMetatypeType>()
7514-
->getInstanceType();
7514+
->getExistentialInstanceType();
75157515
}
75167516
assert(openedInstanceTy->castTo<OpenedArchetypeType>()
75177517
->getOpenedExistentialType()

lib/Sema/ConstraintSystem.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,8 +1995,12 @@ ConstraintSystem::getTypeOfMemberReference(
19951995
if (t->isEqual(selfTy))
19961996
return baseObjTy;
19971997
if (auto *metatypeTy = t->getAs<MetatypeType>())
1998-
if (metatypeTy->getInstanceType()->isEqual(selfTy))
1999-
return ExistentialMetatypeType::get(baseObjTy);
1998+
if (metatypeTy->getInstanceType()->isEqual(selfTy)) {
1999+
auto constraint = baseObjTy;
2000+
if (auto existential = baseObjTy->getAs<ExistentialType>())
2001+
constraint = existential->getConstraintType();
2002+
return ExistentialMetatypeType::get(constraint);
2003+
}
20002004
return t;
20012005
});
20022006
}

0 commit comments

Comments
 (0)