Skip to content

Commit d1125e9

Browse files
authored
Merge pull request swiftlang#75995 from slavapestov/open-existential-recursive-properties
Track recursive properties and outer substitutions for opened existential environments
2 parents 2a04604 + 69bd0f0 commit d1125e9

File tree

14 files changed

+134
-138
lines changed

14 files changed

+134
-138
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,18 @@ class QueryInterfaceTypeSubstitutions {
5858
/// Extra data in a generic environment for an opaque type.
5959
struct OpaqueEnvironmentData {
6060
OpaqueTypeDecl *decl;
61-
SubstitutionMap subMap;
6261
};
6362

6463
/// Extra data in a generic environment for an opened existential.
6564
struct OpenedExistentialEnvironmentData {
6665
Type existential;
67-
GenericSignature parentSig;
6866
UUID uuid;
6967
};
7068

7169
/// Extra data in a generic environment for an opened pack element.
7270
struct OpenedElementEnvironmentData {
7371
UUID uuid;
7472
CanGenericTypeParamType shapeClass;
75-
SubstitutionMap outerSubstitutions;
7673
};
7774

7875
/// Describes the mapping between archetypes and interface types for the
@@ -86,6 +83,7 @@ struct OpenedElementEnvironmentData {
8683
class alignas(1 << DeclAlignInBits) GenericEnvironment final
8784
: private llvm::TrailingObjects<
8885
GenericEnvironment,
86+
SubstitutionMap,
8987
OpaqueEnvironmentData,
9088
OpenedExistentialEnvironmentData,
9189
OpenedElementEnvironmentData,
@@ -114,6 +112,7 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
114112
friend TrailingObjects;
115113
friend OpaqueTypeArchetypeType;
116114

115+
size_t numTrailingObjects(OverloadToken<SubstitutionMap>) const;
117116
size_t numTrailingObjects(OverloadToken<OpaqueEnvironmentData>) const;
118117
size_t numTrailingObjects(OverloadToken<OpenedExistentialEnvironmentData>) const;
119118
size_t numTrailingObjects(OverloadToken<OpenedElementEnvironmentData>) const;
@@ -147,8 +146,7 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
147146

148147
/// Private constructor for opened existential environments.
149148
explicit GenericEnvironment(
150-
GenericSignature signature,
151-
Type existential, GenericSignature parentSig, UUID uuid);
149+
GenericSignature signature, Type existential, SubstitutionMap subs, UUID uuid);
152150

153151
/// Private constructor for opened element environments.
154152
explicit GenericEnvironment(GenericSignature signature,
@@ -185,20 +183,16 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
185183
/// Retrieve the UUID for an opened existential environment.
186184
UUID getOpenedExistentialUUID() const;
187185

188-
/// Retrieve the parent signature for an opened existential environment.
189-
GenericSignature getOpenedExistentialParentSignature() const;
190-
191186
/// Retrieve the opaque type declaration for a generic environment describing
192187
/// opaque types.
193188
OpaqueTypeDecl *getOpaqueTypeDecl() const;
194189

195-
/// Retrieve the substitutions applied to an opaque type declaration to
196-
/// create a generic environment.
197-
SubstitutionMap getOpaqueSubstitutions() const;
198-
199-
/// Retrieve the substitutions for the outer generic parameters of an
200-
/// opened pack element generic environment.
201-
SubstitutionMap getPackElementContextSubstitutions() const;
190+
/// Retrieve the outer substitutions for an opaque or local environment.
191+
///
192+
/// Applying a substitution map to a local or opaque archetype outputs
193+
/// an archetype with the same interface type, and composed outer
194+
/// substitutions.
195+
SubstitutionMap getOuterSubstitutions() const;
202196

203197
/// Retrieve the shape equivalence class for an opened element environment.
204198
/// This is always a pack parameter.
@@ -238,10 +232,11 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
238232
/// Create a new generic environment for an opened existential.
239233
///
240234
/// \param existential The subject existential type
241-
/// \param parentSig The signature of the context where this existential type is being opened
235+
/// \param outerSubs The substitution map containing archetypes from the
236+
/// outer generic context
242237
/// \param uuid The unique identifier for this opened existential
243238
static GenericEnvironment *
244-
forOpenedExistential(Type existential, GenericSignature parentSig, UUID uuid);
239+
forOpenedExistential(Type existential, SubstitutionMap outerSubs, UUID uuid);
245240

246241
/// Create a new generic environment for an opened element.
247242
///
@@ -251,7 +246,7 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
251246
/// \param uuid The unique identifier for this opened element
252247
/// \param shapeClass The shape equivalence class for the originating packs
253248
/// \param outerSubs The substitution map containing archetypes from the
254-
/// outer generic context.
249+
/// outer generic context
255250
static GenericEnvironment *
256251
forOpenedElement(GenericSignature signature,
257252
UUID uuid, CanGenericTypeParamType shapeClass,
@@ -271,9 +266,6 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
271266
/// substitutions.
272267
Type maybeApplyOuterContextSubstitutions(Type type) const;
273268

274-
/// Compute the canonical interface type within this environment.
275-
Type getCanonicalInterfaceType(Type interfaceType);
276-
277269
/// Map an interface type to a contextual type.
278270
static Type mapTypeIntoContext(GenericEnvironment *genericEnv,
279271
Type type);

include/swift/AST/Types.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6679,10 +6679,6 @@ class OpaqueTypeArchetypeType final : public ArchetypeType,
66796679
/// Retrieve the set of substitutions applied to the opaque type.
66806680
SubstitutionMap getSubstitutions() const;
66816681

6682-
/// Compute the canonical interface type within the environment of this
6683-
/// opaque type archetype.
6684-
CanType getCanonicalInterfaceType(Type interfaceType);
6685-
66866682
static bool classof(const TypeBase *T) {
66876683
return T->getKind() == TypeKind::OpaqueTypeArchetype;
66886684
}
@@ -6870,8 +6866,10 @@ class OpenedArchetypeType final : public LocalArchetypeType,
68706866

68716867
private:
68726868
OpenedArchetypeType(GenericEnvironment *environment, Type interfaceType,
6873-
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
6874-
LayoutConstraint layout);
6869+
ArrayRef<ProtocolDecl *> conformsTo,
6870+
Type superclass,
6871+
LayoutConstraint layout,
6872+
RecursiveTypeProperties properties);
68756873
};
68766874
BEGIN_CAN_TYPE_WRAPPER(OpenedArchetypeType, LocalArchetypeType)
68776875
CanOpenedArchetypeType getRoot() const {

include/swift/SIL/SILCloner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2870,7 +2870,7 @@ void SILCloner<ImplClass>::visitOpenPackElementInst(
28702870

28712871
// Substitute the contextual substitutions.
28722872
auto newContextSubs =
2873-
getOpSubstitutionMap(origEnv->getPackElementContextSubstitutions());
2873+
getOpSubstitutionMap(origEnv->getOuterSubstitutions());
28742874

28752875
// The opened shape class is a parameter of the original signature,
28762876
// which is unchanged.

lib/AST/ASTContext.cpp

Lines changed: 66 additions & 43 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;
@@ -618,7 +622,6 @@ struct ASTContext::Implementation {
618622
llvm::DenseMap<BuiltinIntegerWidth, BuiltinIntegerType*> IntegerTypes;
619623
llvm::FoldingSet<BuiltinVectorType> BuiltinVectorTypes;
620624
llvm::FoldingSet<DeclName::CompoundDeclName> CompoundNames;
621-
llvm::DenseMap<UUID, GenericEnvironment *> OpenedExistentialEnvironments;
622625
llvm::DenseMap<UUID, GenericEnvironment *> OpenedElementEnvironments;
623626
llvm::FoldingSet<IndexSubset> IndexSubsets;
624627
llvm::FoldingSet<AutoDiffDerivativeFunctionIdentifier>
@@ -863,7 +866,6 @@ void ASTContext::Implementation::dump(llvm::raw_ostream &os) const {
863866
SIZE_AND_BYTES(SILBlockStorageTypes);
864867
SIZE_AND_BYTES(SILMoveOnlyWrappedTypes);
865868
SIZE_AND_BYTES(IntegerTypes);
866-
SIZE_AND_BYTES(OpenedExistentialEnvironments);
867869
SIZE_AND_BYTES(OpenedElementEnvironments);
868870
SIZE_AND_BYTES(ForeignRepresentableCache);
869871
SIZE(SearchPathsSet);
@@ -3125,7 +3127,6 @@ size_t ASTContext::getTotalMemory() const {
31253127
// getImpl().BuiltinVectorTypes ?
31263128
// getImpl().GenericSignatures ?
31273129
// getImpl().CompoundNames ?
3128-
getImpl().OpenedExistentialEnvironments.getMemorySize() +
31293130
getImpl().Permanent.getTotalMemory();
31303131

31313132
Size += getSolverMemory();
@@ -3162,7 +3163,9 @@ size_t ASTContext::Implementation::Arena::getTotalMemory() const {
31623163
llvm::capacity_in_bytes(StructTypes) +
31633164
llvm::capacity_in_bytes(ClassTypes) +
31643165
llvm::capacity_in_bytes(ProtocolTypes) +
3165-
llvm::capacity_in_bytes(DynamicSelfTypes);
3166+
llvm::capacity_in_bytes(DynamicSelfTypes) +
3167+
OpaqueArchetypeEnvironments.getMemorySize() +
3168+
OpenedExistentialEnvironments.getMemorySize();
31663169
// FunctionTypes ?
31673170
// UnboundGenericTypes ?
31683171
// BoundGenericTypes ?
@@ -3209,6 +3212,7 @@ void ASTContext::Implementation::Arena::dump(llvm::raw_ostream &os) const {
32093212
SIZE(ParameterizedProtocolTypes);
32103213
SIZE(LayoutConstraints);
32113214
SIZE_AND_BYTES(OpaqueArchetypeEnvironments);
3215+
SIZE_AND_BYTES(OpenedExistentialEnvironments);
32123216
SIZE(FunctionTypes);
32133217
SIZE(NormalConformances);
32143218
SIZE(SelfConformances);
@@ -5295,7 +5299,7 @@ OpaqueTypeArchetypeType *OpaqueTypeArchetypeType::getNew(
52955299
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
52965300
LayoutConstraint layout) {
52975301
auto properties = getOpaqueTypeArchetypeProperties(
5298-
environment->getOpaqueSubstitutions());
5302+
environment->getOuterSubstitutions());
52995303
auto arena = getArena(properties);
53005304
auto size = OpaqueTypeArchetypeType::totalSizeToAlloc<
53015305
ProtocolDecl *, Type, LayoutConstraint>(
@@ -5313,26 +5317,39 @@ Type OpaqueTypeArchetypeType::get(
53135317
return env->getOrCreateArchetypeFromInterfaceType(interfaceType);
53145318
}
53155319

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+
53165334
CanTypeWrapper<OpenedArchetypeType> OpenedArchetypeType::getNew(
53175335
GenericEnvironment *environment, Type interfaceType,
53185336
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
53195337
LayoutConstraint layout) {
5320-
// FIXME: It'd be great if all of our callers could submit interface types.
5321-
// But the constraint solver submits archetypes when e.g. trying to issue
5322-
// checks against members of existential types.
5323-
// assert((!superclass || !superclass->hasArchetype())
5324-
// && "superclass must be interface type");
5325-
auto arena = AllocationArena::Permanent;
5326-
ASTContext &ctx = interfaceType->getASTContext();
5327-
void *mem = ctx.Allocate(
5328-
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>(
53295343
conformsTo.size(),
53305344
superclass ? 1 : 0,
5331-
layout ? 1 : 0),
5332-
alignof(OpenedArchetypeType), arena);
5345+
layout ? 1 : 0);
5346+
5347+
ASTContext &ctx = interfaceType->getASTContext();
5348+
void *mem = ctx.Allocate(size, alignof(OpenedArchetypeType), arena);
53335349

53345350
return CanOpenedArchetypeType(::new (mem) OpenedArchetypeType(
5335-
environment, interfaceType, conformsTo, superclass, layout));
5351+
environment, interfaceType, conformsTo, superclass, layout,
5352+
properties));
53365353
}
53375354

53385355
CanTypeWrapper<OpenedArchetypeType>
@@ -5353,7 +5370,7 @@ CanOpenedArchetypeType OpenedArchetypeType::get(CanType existential,
53535370

53545371
auto *genericEnv =
53555372
GenericEnvironment::forOpenedExistential(
5356-
existential, GenericSignature(), *knownID);
5373+
existential, SubstitutionMap(), *knownID);
53575374

53585375
// Map the interface type into that environment.
53595376
auto result = genericEnv->mapTypeIntoContext(interfaceType)
@@ -5508,10 +5525,11 @@ GenericEnvironment *GenericEnvironment::forPrimary(GenericSignature signature) {
55085525

55095526
// Allocate and construct the new environment.
55105527
unsigned numGenericParams = signature.getGenericParams().size();
5511-
size_t bytes = totalSizeToAlloc<OpaqueEnvironmentData,
5528+
size_t bytes = totalSizeToAlloc<SubstitutionMap,
5529+
OpaqueEnvironmentData,
55125530
OpenedExistentialEnvironmentData,
55135531
OpenedElementEnvironmentData, Type>(
5514-
0, 0, 0, numGenericParams);
5532+
0, 0, 0, 0, numGenericParams);
55155533
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
55165534
return new (mem) GenericEnvironment(signature);
55175535
}
@@ -5537,10 +5555,11 @@ GenericEnvironment *GenericEnvironment::forOpaqueType(
55375555
// Allocate and construct the new environment.
55385556
auto signature = opaque->getOpaqueInterfaceGenericSignature();
55395557
unsigned numGenericParams = signature.getGenericParams().size();
5540-
size_t bytes = totalSizeToAlloc<OpaqueEnvironmentData,
5558+
size_t bytes = totalSizeToAlloc<SubstitutionMap,
5559+
OpaqueEnvironmentData,
55415560
OpenedExistentialEnvironmentData,
55425561
OpenedElementEnvironmentData, Type>(
5543-
1, 0, 0, numGenericParams);
5562+
1, 1, 0, 0, numGenericParams);
55445563
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment), arena);
55455564
env = new (mem) GenericEnvironment(signature, opaque, subs);
55465565

@@ -5553,46 +5572,49 @@ GenericEnvironment *GenericEnvironment::forOpaqueType(
55535572
/// Create a new generic environment for an opened archetype.
55545573
GenericEnvironment *
55555574
GenericEnvironment::forOpenedExistential(
5556-
Type existential, GenericSignature parentSig, UUID uuid) {
5575+
Type existential, SubstitutionMap subs, UUID uuid) {
55575576
assert(existential->isExistentialType());
5558-
// FIXME: Opened archetypes can't be transformed because the
5559-
// the identity of the archetype has to be preserved. This
5560-
// means that simplifying an opened archetype in the constraint
5561-
// system to replace type variables with fixed types is not
5562-
// yet supported. For now, assert that an opened archetype never
5563-
// contains type variables to catch cases where type variables
5564-
// would be applied to the type-checked AST.
5565-
assert(!existential->hasTypeVariable() &&
5566-
"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();
55675582

55685583
auto &ctx = existential->getASTContext();
55695584

5570-
auto &openedExistentialEnvironments =
5571-
ctx.getImpl().OpenedExistentialEnvironments;
5572-
auto found = openedExistentialEnvironments.find(uuid);
5585+
auto properties = getOpenedArchetypeProperties(subs);
5586+
auto arena = getArena(properties);
5587+
5588+
auto key = std::make_pair(subs, uuid);
5589+
5590+
auto &environments =
5591+
ctx.getImpl().getArena(arena).OpenedExistentialEnvironments;
5592+
auto found = environments.find(key);
55735593

5574-
if (found != openedExistentialEnvironments.end()) {
5594+
if (found != environments.end()) {
55755595
auto *existingEnv = found->second;
55765596
assert(existingEnv->getOpenedExistentialType()->isEqual(existential));
5577-
assert(existingEnv->getOpenedExistentialParentSignature().getPointer() == parentSig.getPointer());
5597+
assert(existingEnv->getOuterSubstitutions() == subs);
55785598
assert(existingEnv->getOpenedExistentialUUID() == uuid);
55795599

55805600
return existingEnv;
55815601
}
55825602

5603+
auto parentSig = subs.getGenericSignature().getCanonicalSignature();
55835604
auto signature = ctx.getOpenedExistentialSignature(existential, parentSig);
55845605

55855606
// Allocate and construct the new environment.
55865607
unsigned numGenericParams = signature.getGenericParams().size();
5587-
size_t bytes = totalSizeToAlloc<OpaqueEnvironmentData,
5608+
size_t bytes = totalSizeToAlloc<SubstitutionMap,
5609+
OpaqueEnvironmentData,
55885610
OpenedExistentialEnvironmentData,
55895611
OpenedElementEnvironmentData, Type>(
5590-
0, 1, 0, numGenericParams);
5612+
1, 0, 1, 0, numGenericParams);
55915613
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
55925614
auto *genericEnv =
5593-
new (mem) GenericEnvironment(signature, existential, parentSig, uuid);
5615+
new (mem) GenericEnvironment(signature, existential, subs, uuid);
55945616

5595-
openedExistentialEnvironments[uuid] = genericEnv;
5617+
environments[key] = genericEnv;
55965618

55975619
return genericEnv;
55985620
}
@@ -5621,11 +5643,12 @@ GenericEnvironment::forOpenedElement(GenericSignature signature,
56215643
// Allocate and construct the new environment.
56225644
unsigned numGenericParams = signature.getGenericParams().size();
56235645
unsigned numOpenedParams = signature.getInnermostGenericParams().size();
5624-
size_t bytes = totalSizeToAlloc<OpaqueEnvironmentData,
5646+
size_t bytes = totalSizeToAlloc<SubstitutionMap,
5647+
OpaqueEnvironmentData,
56255648
OpenedExistentialEnvironmentData,
56265649
OpenedElementEnvironmentData,
56275650
Type>(
5628-
0, 0, 1, numGenericParams + numOpenedParams);
5651+
1, 0, 0, 1, numGenericParams + numOpenedParams);
56295652
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
56305653
auto *genericEnv = new (mem) GenericEnvironment(signature,
56315654
uuid, shapeClass,

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6955,7 +6955,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
69556955
// the generic signature of the contextual substitution map in the
69566956
// opened element environment.
69576957
auto env = T->getGenericEnvironment();
6958-
auto subs = env->getPackElementContextSubstitutions();
6958+
auto subs = env->getOuterSubstitutions();
69596959
auto sig = subs.getGenericSignature();
69606960
auto params = sig.getGenericParams();
69616961

0 commit comments

Comments
 (0)