Skip to content

Commit 43c33d7

Browse files
committed
AST: Calculate recursive properties for opened existential types
1 parent 5577f27 commit 43c33d7

File tree

3 files changed

+52
-38
lines changed

3 files changed

+52
-38
lines changed

include/swift/AST/Types.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6870,8 +6870,10 @@ class OpenedArchetypeType final : public LocalArchetypeType,
68706870

68716871
private:
68726872
OpenedArchetypeType(GenericEnvironment *environment, Type interfaceType,
6873-
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
6874-
LayoutConstraint layout);
6873+
ArrayRef<ProtocolDecl *> conformsTo,
6874+
Type superclass,
6875+
LayoutConstraint layout,
6876+
RecursiveTypeProperties properties);
68756877
};
68766878
BEGIN_CAN_TYPE_WRAPPER(OpenedArchetypeType, LocalArchetypeType)
68776879
CanOpenedArchetypeType getRoot() const {

lib/AST/ASTContext.cpp

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,8 @@ struct ASTContext::Implementation {
520520
MetatypeRepresentation::Last_MetatypeRepresentation) + 1,
521521
"Use std::pair for MetatypeTypes and ExistentialMetatypeTypes.");
522522

523+
using OpenedExistentialKey = std::pair<SubstitutionMap, UUID>;
524+
523525
llvm::DenseMap<Type, ErrorType *> ErrorTypesWithOriginal;
524526
llvm::FoldingSet<TypeAliasType> TypeAliasTypes;
525527
llvm::FoldingSet<TupleType> TupleTypes;
@@ -555,6 +557,8 @@ struct ASTContext::Implementation {
555557
llvm::FoldingSet<LayoutConstraintInfo> LayoutConstraints;
556558
llvm::DenseMap<std::pair<OpaqueTypeDecl *, SubstitutionMap>,
557559
GenericEnvironment *> OpaqueArchetypeEnvironments;
560+
llvm::DenseMap<OpenedExistentialKey, GenericEnvironment *>
561+
OpenedExistentialEnvironments;
558562

559563
/// The set of function types.
560564
llvm::FoldingSet<FunctionType> FunctionTypes;
@@ -606,8 +610,6 @@ struct ASTContext::Implementation {
606610
void dump(llvm::raw_ostream &out) const;
607611
};
608612

609-
using OpenedExistentialKey = std::pair<SubstitutionMap, UUID>;
610-
611613
llvm::DenseMap<ModuleDecl*, ModuleType*> ModuleTypes;
612614
llvm::DenseMap<std::pair<unsigned, unsigned>, GenericTypeParamType *>
613615
GenericParamTypes;
@@ -620,8 +622,6 @@ struct ASTContext::Implementation {
620622
llvm::DenseMap<BuiltinIntegerWidth, BuiltinIntegerType*> IntegerTypes;
621623
llvm::FoldingSet<BuiltinVectorType> BuiltinVectorTypes;
622624
llvm::FoldingSet<DeclName::CompoundDeclName> CompoundNames;
623-
llvm::DenseMap<OpenedExistentialKey, GenericEnvironment *>
624-
OpenedExistentialEnvironments;
625625
llvm::DenseMap<UUID, GenericEnvironment *> OpenedElementEnvironments;
626626
llvm::FoldingSet<IndexSubset> IndexSubsets;
627627
llvm::FoldingSet<AutoDiffDerivativeFunctionIdentifier>
@@ -866,7 +866,6 @@ void ASTContext::Implementation::dump(llvm::raw_ostream &os) const {
866866
SIZE_AND_BYTES(SILBlockStorageTypes);
867867
SIZE_AND_BYTES(SILMoveOnlyWrappedTypes);
868868
SIZE_AND_BYTES(IntegerTypes);
869-
SIZE_AND_BYTES(OpenedExistentialEnvironments);
870869
SIZE_AND_BYTES(OpenedElementEnvironments);
871870
SIZE_AND_BYTES(ForeignRepresentableCache);
872871
SIZE(SearchPathsSet);
@@ -3128,7 +3127,6 @@ size_t ASTContext::getTotalMemory() const {
31283127
// getImpl().BuiltinVectorTypes ?
31293128
// getImpl().GenericSignatures ?
31303129
// getImpl().CompoundNames ?
3131-
getImpl().OpenedExistentialEnvironments.getMemorySize() +
31323130
getImpl().Permanent.getTotalMemory();
31333131

31343132
Size += getSolverMemory();
@@ -3165,7 +3163,9 @@ size_t ASTContext::Implementation::Arena::getTotalMemory() const {
31653163
llvm::capacity_in_bytes(StructTypes) +
31663164
llvm::capacity_in_bytes(ClassTypes) +
31673165
llvm::capacity_in_bytes(ProtocolTypes) +
3168-
llvm::capacity_in_bytes(DynamicSelfTypes);
3166+
llvm::capacity_in_bytes(DynamicSelfTypes) +
3167+
OpaqueArchetypeEnvironments.getMemorySize() +
3168+
OpenedExistentialEnvironments.getMemorySize();
31693169
// FunctionTypes ?
31703170
// UnboundGenericTypes ?
31713171
// BoundGenericTypes ?
@@ -3212,6 +3212,7 @@ void ASTContext::Implementation::Arena::dump(llvm::raw_ostream &os) const {
32123212
SIZE(ParameterizedProtocolTypes);
32133213
SIZE(LayoutConstraints);
32143214
SIZE_AND_BYTES(OpaqueArchetypeEnvironments);
3215+
SIZE_AND_BYTES(OpenedExistentialEnvironments);
32153216
SIZE(FunctionTypes);
32163217
SIZE(NormalConformances);
32173218
SIZE(SelfConformances);
@@ -5316,26 +5317,39 @@ Type OpaqueTypeArchetypeType::get(
53165317
return env->getOrCreateArchetypeFromInterfaceType(interfaceType);
53175318
}
53185319

5320+
/// Compute the recursive type properties of an opaque type archetype.
5321+
static RecursiveTypeProperties getOpenedArchetypeProperties(SubstitutionMap subs) {
5322+
// An opaque type isn't contextually dependent like other archetypes, so
5323+
// by itself, it doesn't impose the "Has Archetype" recursive property,
5324+
// but the substituted types might. A disjoint "Has Opaque Archetype" tracks
5325+
// the presence of opaque archetypes.
5326+
RecursiveTypeProperties properties =
5327+
RecursiveTypeProperties::HasOpenedExistential;
5328+
for (auto type : subs.getReplacementTypes()) {
5329+
properties |= type->getRecursiveProperties();
5330+
}
5331+
return properties;
5332+
}
5333+
53195334
CanTypeWrapper<OpenedArchetypeType> OpenedArchetypeType::getNew(
53205335
GenericEnvironment *environment, Type interfaceType,
53215336
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
53225337
LayoutConstraint layout) {
5323-
// FIXME: It'd be great if all of our callers could submit interface types.
5324-
// But the constraint solver submits archetypes when e.g. trying to issue
5325-
// checks against members of existential types.
5326-
// assert((!superclass || !superclass->hasArchetype())
5327-
// && "superclass must be interface type");
5328-
auto arena = AllocationArena::Permanent;
5329-
ASTContext &ctx = interfaceType->getASTContext();
5330-
void *mem = ctx.Allocate(
5331-
OpenedArchetypeType::totalSizeToAlloc<ProtocolDecl *,Type,LayoutConstraint>(
5338+
auto properties = getOpenedArchetypeProperties(
5339+
environment->getOuterSubstitutions());
5340+
auto arena = getArena(properties);
5341+
auto size = OpenedArchetypeType::totalSizeToAlloc<
5342+
ProtocolDecl *, Type, LayoutConstraint>(
53325343
conformsTo.size(),
53335344
superclass ? 1 : 0,
5334-
layout ? 1 : 0),
5335-
alignof(OpenedArchetypeType), arena);
5345+
layout ? 1 : 0);
5346+
5347+
ASTContext &ctx = interfaceType->getASTContext();
5348+
void *mem = ctx.Allocate(size, alignof(OpenedArchetypeType), arena);
53365349

53375350
return CanOpenedArchetypeType(::new (mem) OpenedArchetypeType(
5338-
environment, interfaceType, conformsTo, superclass, layout));
5351+
environment, interfaceType, conformsTo, superclass, layout,
5352+
properties));
53395353
}
53405354

53415355
CanTypeWrapper<OpenedArchetypeType>
@@ -5560,25 +5574,24 @@ GenericEnvironment *
55605574
GenericEnvironment::forOpenedExistential(
55615575
Type existential, SubstitutionMap subs, UUID uuid) {
55625576
assert(existential->isExistentialType());
5563-
// FIXME: Opened archetypes can't be transformed because the
5564-
// the identity of the archetype has to be preserved. This
5565-
// means that simplifying an opened archetype in the constraint
5566-
// system to replace type variables with fixed types is not
5567-
// yet supported. For now, assert that an opened archetype never
5568-
// contains type variables to catch cases where type variables
5569-
// would be applied to the type-checked AST.
5570-
assert(!existential->hasTypeVariable() &&
5571-
"opened existentials containing type variables cannot be simplified");
5577+
5578+
// TODO: We could attempt to preserve type sugar in the substitution map.
5579+
// Currently archetypes are assumed to be always canonical in many places,
5580+
// though, so doing so would require fixing those places.
5581+
subs = subs.getCanonical();
55725582

55735583
auto &ctx = existential->getASTContext();
55745584

5585+
auto properties = getOpenedArchetypeProperties(subs);
5586+
auto arena = getArena(properties);
5587+
55755588
auto key = std::make_pair(subs, uuid);
55765589

5577-
auto &openedExistentialEnvironments =
5578-
ctx.getImpl().OpenedExistentialEnvironments;
5579-
auto found = openedExistentialEnvironments.find(key);
5590+
auto &environments =
5591+
ctx.getImpl().getArena(arena).OpenedExistentialEnvironments;
5592+
auto found = environments.find(key);
55805593

5581-
if (found != openedExistentialEnvironments.end()) {
5594+
if (found != environments.end()) {
55825595
auto *existingEnv = found->second;
55835596
assert(existingEnv->getOpenedExistentialType()->isEqual(existential));
55845597
assert(existingEnv->getOuterSubstitutions() == subs);
@@ -5601,7 +5614,7 @@ GenericEnvironment::forOpenedExistential(
56015614
auto *genericEnv =
56025615
new (mem) GenericEnvironment(signature, existential, subs, uuid);
56035616

5604-
openedExistentialEnvironments[key] = genericEnv;
5617+
environments[key] = genericEnv;
56055618

56065619
return genericEnv;
56075620
}

lib/AST/Type.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3575,10 +3575,9 @@ SubstitutionMap OpaqueTypeArchetypeType::getSubstitutions() const {
35753575
OpenedArchetypeType::OpenedArchetypeType(
35763576
GenericEnvironment *environment, Type interfaceType,
35773577
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
3578-
LayoutConstraint layout)
3578+
LayoutConstraint layout, RecursiveTypeProperties properties)
35793579
: LocalArchetypeType(TypeKind::OpenedArchetype,
3580-
interfaceType->getASTContext(),
3581-
RecursiveTypeProperties::HasOpenedExistential,
3580+
interfaceType->getASTContext(), properties,
35823581
interfaceType, conformsTo, superclass, layout,
35833582
environment)
35843583
{

0 commit comments

Comments
 (0)