Skip to content

Commit 067a00b

Browse files
committed
[Sema] Construct OpenedArchetypeType with a canonical existential type.
Opened archetypes can be created in the constraint system, and the existential type it wraps can contain type variables. This can happen when the existential type is inferred through a typealias inside a generic type, and a member reference whose base is the opened existential gets bound before binding the generic arguments of the parent type. However, simplifying opened archetypes to replace type variables is not yet supported, which leads to type variables escaping the constraint system. We can support cases where the underlying existential type doesn't depend on the type variables by canonicalizing it when opening the existential. Cases where the underlying type requires resolved generic arguments are still unsupported for now.
1 parent 46c2e8d commit 067a00b

File tree

15 files changed

+84
-37
lines changed

15 files changed

+84
-37
lines changed

include/swift/AST/Types.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5666,14 +5666,14 @@ class OpenedArchetypeType final : public ArchetypeType,
56665666
/// \param knownID When non-empty, the known ID of the archetype. When empty,
56675667
/// a fresh archetype with a unique ID will be opened.
56685668
static CanTypeWrapper<OpenedArchetypeType>
5669-
get(Type existential,
5669+
get(CanType existential,
56705670
Optional<UUID> knownID = None);
56715671

56725672
/// Create a new archetype that represents the opened type
56735673
/// of an existential value.
56745674
///
56755675
/// \param existential The existential type or existential metatype to open.
5676-
static CanType getAny(Type existential);
5676+
static CanType getAny(CanType existential);
56775677

56785678
/// Retrieve the ID number of this opened existential.
56795679
UUID getOpenedExistentialID() const { return ID; }

lib/AST/ASTContext.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4349,8 +4349,18 @@ OpaqueTypeArchetypeType::get(OpaqueTypeDecl *Decl, unsigned ordinal,
43494349
return newOpaque;
43504350
}
43514351

4352-
CanOpenedArchetypeType OpenedArchetypeType::get(Type existential,
4352+
CanOpenedArchetypeType OpenedArchetypeType::get(CanType existential,
43534353
Optional<UUID> knownID) {
4354+
// FIXME: Opened archetypes can't be transformed because the
4355+
// the identity of the archetype has to be preserved. This
4356+
// means that simplifying an opened archetype in the constraint
4357+
// system to replace type variables with fixed types is not
4358+
// yet supported. For now, assert that an opened archetype never
4359+
// contains type variables to catch cases where type variables
4360+
// would be applied to the type-checked AST.
4361+
assert(!existential->hasTypeVariable() &&
4362+
"opened existentials containing type variables cannot be simplified");
4363+
43544364
auto &ctx = existential->getASTContext();
43554365
auto &openedExistentialArchetypes = ctx.getImpl().OpenedExistentialArchetypes;
43564366
// If we know the ID already...
@@ -4418,9 +4428,10 @@ GenericEnvironment *OpenedArchetypeType::getGenericEnvironment() const {
44184428
return env;
44194429
}
44204430

4421-
CanType OpenedArchetypeType::getAny(Type existential) {
4431+
CanType OpenedArchetypeType::getAny(CanType existential) {
44224432
if (auto metatypeTy = existential->getAs<ExistentialMetatypeType>()) {
4423-
auto instanceTy = metatypeTy->getExistentialInstanceType();
4433+
auto instanceTy =
4434+
metatypeTy->getExistentialInstanceType()->getCanonicalType();
44244435
return CanMetatypeType::get(OpenedArchetypeType::getAny(instanceTy));
44254436
}
44264437
assert(existential->isExistentialType());

lib/AST/Type.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5568,13 +5568,14 @@ SILBoxType::SILBoxType(ASTContext &C,
55685568
Type TypeBase::openAnyExistentialType(OpenedArchetypeType *&opened) {
55695569
assert(isAnyExistentialType());
55705570
if (auto metaty = getAs<ExistentialMetatypeType>()) {
5571-
opened = OpenedArchetypeType::get(metaty->getExistentialInstanceType());
5571+
opened = OpenedArchetypeType::get(
5572+
metaty->getExistentialInstanceType()->getCanonicalType());
55725573
if (metaty->hasRepresentation())
55735574
return MetatypeType::get(opened, metaty->getRepresentation());
55745575
else
55755576
return MetatypeType::get(opened);
55765577
}
5577-
opened = OpenedArchetypeType::get(this);
5578+
opened = OpenedArchetypeType::get(getCanonicalType());
55785579
return opened;
55795580
}
55805581

lib/IDE/CodeCompletion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4101,7 +4101,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
41014101

41024102
if (!ExprType->getMetatypeInstanceType()->isAnyObject())
41034103
if (ExprType->isAnyExistentialType())
4104-
ExprType = OpenedArchetypeType::getAny(ExprType);
4104+
ExprType = OpenedArchetypeType::getAny(ExprType->getCanonicalType());
41054105

41064106
if (!IsSelfRefExpr && !IsSuperRefExpr && ExprType->getAnyNominal() &&
41074107
ExprType->getAnyNominal()->isActor()) {

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ static ManagedValue emitCastToReferenceType(SILGenFunction &SGF,
297297

298298
// If the argument is existential, open it.
299299
if (argTy->isClassExistentialType()) {
300-
auto openedTy = OpenedArchetypeType::get(argTy);
300+
auto openedTy = OpenedArchetypeType::get(argTy->getCanonicalType());
301301
SILType loweredOpenedTy = SGF.getLoweredLoadableType(openedTy);
302302
arg = SGF.B.createOpenExistentialRef(loc, arg, loweredOpenedTy);
303303
}
@@ -790,7 +790,7 @@ static ManagedValue emitBuiltinCastToBridgeObject(SILGenFunction &SGF,
790790

791791
// If the argument is existential, open it.
792792
if (sourceType->isClassExistentialType()) {
793-
auto openedTy = OpenedArchetypeType::get(sourceType);
793+
auto openedTy = OpenedArchetypeType::get(sourceType->getCanonicalType());
794794
SILType loweredOpenedTy = SGF.getLoweredLoadableType(openedTy);
795795
ref = SGF.B.createOpenExistentialRef(loc, ref, loweredOpenedTy);
796796
}

lib/SILGen/SILGenExpr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1841,7 +1841,8 @@ RValue RValueEmitter::visitErasureExpr(ErasureExpr *E, SGFContext C) {
18411841
auto &existentialTL = SGF.getTypeLowering(E->getType());
18421842
auto concreteFormalType = E->getSubExpr()->getType()->getCanonicalType();
18431843

1844-
auto archetype = OpenedArchetypeType::getAny(E->getType());
1844+
auto archetype = OpenedArchetypeType::getAny(
1845+
E->getType()->getCanonicalType());
18451846
AbstractionPattern abstractionPattern(archetype);
18461847
auto &concreteTL = SGF.getTypeLowering(abstractionPattern,
18471848
concreteFormalType);

lib/SILGen/SILGenType.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,8 @@ static SILFunction *emitSelfConformanceWitness(SILGenModule &SGM,
831831
ProtocolConformanceRef(conformance));
832832

833833
// Open the protocol type.
834-
auto openedType = OpenedArchetypeType::get(protocol->getExistentialType());
834+
auto openedType = OpenedArchetypeType::get(
835+
protocol->getExistentialType()->getCanonicalType());
835836

836837
// Form the substitutions for calling the witness.
837838
auto witnessSubs = SubstitutionMap::getProtocolSubstitutions(protocol,

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5365,7 +5365,8 @@ Expr *ExprRewriter::coerceSuperclass(Expr *expr, Type toType) {
53655365
if (fromInstanceType->isExistentialType()) {
53665366
// Coercion from superclass-constrained existential to its
53675367
// concrete superclass.
5368-
auto fromArchetype = OpenedArchetypeType::getAny(fromType);
5368+
auto fromArchetype = OpenedArchetypeType::getAny(
5369+
fromType->getCanonicalType());
53695370

53705371
auto *archetypeVal = cs.cacheType(new (ctx) OpaqueValueExpr(
53715372
expr->getSourceRange(), fromArchetype));
@@ -5428,7 +5429,7 @@ Expr *ExprRewriter::coerceExistential(Expr *expr, Type toType) {
54285429

54295430
// For existential-to-existential coercions, open the source existential.
54305431
if (fromType->isAnyExistentialType()) {
5431-
fromType = OpenedArchetypeType::getAny(fromType);
5432+
fromType = OpenedArchetypeType::getAny(fromType->getCanonicalType());
54325433

54335434
auto *archetypeVal = cs.cacheType(
54345435
new (ctx) OpaqueValueExpr(expr->getSourceRange(), fromType));

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9653,7 +9653,7 @@ ConstraintSystem::simplifyOpenedExistentialOfConstraint(
96539653
instanceTy = metaTy->getExistentialInstanceType();
96549654
}
96559655
assert(instanceTy->isExistentialType());
9656-
Type openedTy = OpenedArchetypeType::get(instanceTy);
9656+
Type openedTy = OpenedArchetypeType::get(instanceTy->getCanonicalType());
96579657
if (isMetatype)
96589658
openedTy = MetatypeType::get(openedTy, getASTContext());
96599659
return matchTypes(type1, openedTy, ConstraintKind::Bind, subflags, locator);

lib/Sema/ConstraintSystem.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1876,7 +1876,8 @@ ConstraintSystem::getTypeOfMemberReference(
18761876
}
18771877
}
18781878
} else if (baseObjTy->isExistentialType()) {
1879-
auto openedArchetype = OpenedArchetypeType::get(baseObjTy);
1879+
auto openedArchetype = OpenedArchetypeType::get(
1880+
baseObjTy->getCanonicalType());
18801881
OpenedExistentialTypes.insert(
18811882
{getConstraintLocator(locator), openedArchetype});
18821883
baseOpenedTy = openedArchetype;

0 commit comments

Comments
 (0)