Skip to content

Commit 76e6156

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 ce813f7 commit 76e6156

File tree

15 files changed

+88
-41
lines changed

15 files changed

+88
-41
lines changed

include/swift/AST/Types.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5654,7 +5654,7 @@ class OpenedArchetypeType final : public ArchetypeType,
56545654
/// \param knownID When non-empty, the known ID of the archetype. When empty,
56555655
/// a fresh archetype with a unique ID will be opened.
56565656
static CanTypeWrapper<OpenedArchetypeType> get(
5657-
Type existential, Optional<UUID> knownID = None);
5657+
CanType existential, Optional<UUID> knownID = None);
56585658

56595659
/// Get or create an archetype that represents the opened type
56605660
/// of an existential value.
@@ -5665,20 +5665,20 @@ class OpenedArchetypeType final : public ArchetypeType,
56655665
/// \param knownID When non-empty, the known ID of the archetype. When empty,
56665666
/// a fresh archetype with a unique ID will be opened.
56675667
static CanTypeWrapper<OpenedArchetypeType> get(
5668-
Type existential, Type interfaceType, Optional<UUID> knownID = None);
5668+
CanType existential, Type interfaceType, Optional<UUID> knownID = None);
56695669

56705670
/// Create a new archetype that represents the opened type
56715671
/// of an existential value.
56725672
///
56735673
/// \param existential The existential type or existential metatype to open.
56745674
/// \param interfaceType The interface type represented by this archetype.
5675-
static CanType getAny(Type existential, Type interfaceType);
5675+
static CanType getAny(CanType existential, Type interfaceType);
56765676

56775677
/// Create a new archetype that represents the opened type
56785678
/// of an existential value.
56795679
///
56805680
/// \param existential The existential type or existential metatype to open.
5681-
static CanType getAny(Type existential);
5681+
static CanType getAny(CanType existential);
56825682

56835683
/// Retrieve the ID number of this opened existential.
56845684
UUID getOpenedExistentialID() const;

lib/AST/ASTContext.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4286,15 +4286,25 @@ CanTypeWrapper<OpenedArchetypeType> OpenedArchetypeType::getNew(
42864286
}
42874287

42884288
CanTypeWrapper<OpenedArchetypeType> OpenedArchetypeType::get(
4289-
Type existential, Optional<UUID> knownID) {
4289+
CanType existential, Optional<UUID> knownID) {
42904290
Type interfaceType = GenericTypeParamType::get(
42914291
/*isTypeSequence=*/false, 0, 0, existential->getASTContext());
42924292
return get(existential, interfaceType, knownID);
42934293
}
42944294

4295-
CanOpenedArchetypeType OpenedArchetypeType::get(Type existential,
4295+
CanOpenedArchetypeType OpenedArchetypeType::get(CanType existential,
42964296
Type interfaceType,
42974297
Optional<UUID> knownID) {
4298+
// FIXME: Opened archetypes can't be transformed because the
4299+
// the identity of the archetype has to be preserved. This
4300+
// means that simplifying an opened archetype in the constraint
4301+
// system to replace type variables with fixed types is not
4302+
// yet supported. For now, assert that an opened archetype never
4303+
// contains type variables to catch cases where type variables
4304+
// would be applied to the type-checked AST.
4305+
assert(!existential->hasTypeVariable() &&
4306+
"opened existentials containing type variables cannot be simplified");
4307+
42984308
auto &ctx = existential->getASTContext();
42994309
auto &openedExistentialEnvironments =
43004310
ctx.getImpl().OpenedExistentialEnvironments;
@@ -4327,17 +4337,18 @@ CanOpenedArchetypeType OpenedArchetypeType::get(Type existential,
43274337
}
43284338

43294339

4330-
CanType OpenedArchetypeType::getAny(Type existential, Type interfaceType) {
4340+
CanType OpenedArchetypeType::getAny(CanType existential, Type interfaceType) {
43314341
if (auto metatypeTy = existential->getAs<ExistentialMetatypeType>()) {
4332-
auto instanceTy = metatypeTy->getExistentialInstanceType();
4342+
auto instanceTy =
4343+
metatypeTy->getExistentialInstanceType()->getCanonicalType();
43334344
return CanMetatypeType::get(
43344345
OpenedArchetypeType::getAny(instanceTy, interfaceType));
43354346
}
43364347
assert(existential->isExistentialType());
43374348
return OpenedArchetypeType::get(existential, interfaceType);
43384349
}
43394350

4340-
CanType OpenedArchetypeType::getAny(Type existential) {
4351+
CanType OpenedArchetypeType::getAny(CanType existential) {
43414352
Type interfaceType = GenericTypeParamType::get(
43424353
/*isTypeSequence=*/false, 0, 0, existential->getASTContext());
43434354
return getAny(existential, interfaceType);

lib/AST/Type.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5613,13 +5613,14 @@ SILBoxType::SILBoxType(ASTContext &C,
56135613
Type TypeBase::openAnyExistentialType(OpenedArchetypeType *&opened) {
56145614
assert(isAnyExistentialType());
56155615
if (auto metaty = getAs<ExistentialMetatypeType>()) {
5616-
opened = OpenedArchetypeType::get(metaty->getExistentialInstanceType());
5616+
opened = OpenedArchetypeType::get(
5617+
metaty->getExistentialInstanceType()->getCanonicalType());
56175618
if (metaty->hasRepresentation())
56185619
return MetatypeType::get(opened, metaty->getRepresentation());
56195620
else
56205621
return MetatypeType::get(opened);
56215622
}
5622-
opened = OpenedArchetypeType::get(this);
5623+
opened = OpenedArchetypeType::get(getCanonicalType());
56235624
return opened;
56245625
}
56255626

lib/IDE/CodeCompletion.cpp

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

41014101
if (!ExprType->getMetatypeInstanceType()->isAnyObject())
41024102
if (ExprType->isAnyExistentialType())
4103-
ExprType = OpenedArchetypeType::getAny(ExprType);
4103+
ExprType = OpenedArchetypeType::getAny(ExprType->getCanonicalType());
41044104

41054105
if (!IsSelfRefExpr && !IsSuperRefExpr && ExprType->getAnyNominal() &&
41064106
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
@@ -1850,7 +1850,8 @@ RValue RValueEmitter::visitErasureExpr(ErasureExpr *E, SGFContext C) {
18501850
auto &existentialTL = SGF.getTypeLowering(E->getType());
18511851
auto concreteFormalType = E->getSubExpr()->getType()->getCanonicalType();
18521852

1853-
auto archetype = OpenedArchetypeType::getAny(E->getType());
1853+
auto archetype = OpenedArchetypeType::getAny(
1854+
E->getType()->getCanonicalType());
18541855
AbstractionPattern abstractionPattern(archetype);
18551856
auto &concreteTL = SGF.getTypeLowering(abstractionPattern,
18561857
concreteFormalType);

lib/SILGen/SILGenType.cpp

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

844844
// Open the protocol type.
845-
auto openedType = OpenedArchetypeType::get(protocol->getExistentialType());
845+
auto openedType = OpenedArchetypeType::get(
846+
protocol->getExistentialType()->getCanonicalType());
846847

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

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5370,7 +5370,8 @@ Expr *ExprRewriter::coerceSuperclass(Expr *expr, Type toType) {
53705370
if (fromInstanceType->isExistentialType()) {
53715371
// Coercion from superclass-constrained existential to its
53725372
// concrete superclass.
5373-
auto fromArchetype = OpenedArchetypeType::getAny(fromType);
5373+
auto fromArchetype = OpenedArchetypeType::getAny(
5374+
fromType->getCanonicalType());
53745375

53755376
auto *archetypeVal = cs.cacheType(new (ctx) OpaqueValueExpr(
53765377
expr->getSourceRange(), fromArchetype));
@@ -5433,7 +5434,7 @@ Expr *ExprRewriter::coerceExistential(Expr *expr, Type toType) {
54335434

54345435
// For existential-to-existential coercions, open the source existential.
54355436
if (fromType->isAnyExistentialType()) {
5436-
fromType = OpenedArchetypeType::getAny(fromType);
5437+
fromType = OpenedArchetypeType::getAny(fromType->getCanonicalType());
54375438

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

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9785,7 +9785,7 @@ ConstraintSystem::simplifyOpenedExistentialOfConstraint(
97859785
instanceTy = metaTy->getExistentialInstanceType();
97869786
}
97879787
assert(instanceTy->isExistentialType());
9788-
Type openedTy = OpenedArchetypeType::get(instanceTy);
9788+
Type openedTy = OpenedArchetypeType::get(instanceTy->getCanonicalType());
97899789
if (isMetatype)
97909790
openedTy = MetatypeType::get(openedTy, getASTContext());
97919791
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
@@ -1907,7 +1907,8 @@ ConstraintSystem::getTypeOfMemberReference(
19071907
}
19081908
}
19091909
} else if (baseObjTy->isExistentialType()) {
1910-
auto openedArchetype = OpenedArchetypeType::get(baseObjTy);
1910+
auto openedArchetype = OpenedArchetypeType::get(
1911+
baseObjTy->getCanonicalType());
19111912
OpenedExistentialTypes.insert(
19121913
{getConstraintLocator(locator), openedArchetype});
19131914
baseOpenedTy = openedArchetype;

0 commit comments

Comments
 (0)