Skip to content

Commit 2e60f2a

Browse files
committed
Delay the creation of the generic environment for OpaqueTypeArchetypeType
As a small step toward moving away from having a bespoke generic environment for each OpaqueTypeArchetypeType, create the types without the generic environment and only build it lazily.
1 parent ef7df1d commit 2e60f2a

File tree

3 files changed

+87
-79
lines changed

3 files changed

+87
-79
lines changed

include/swift/AST/Types.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5562,7 +5562,7 @@ class OpaqueTypeArchetypeType final : public ArchetypeType,
55625562

55635563
/// A GenericEnvironment with this opaque archetype bound to the interface
55645564
/// type of the output type from the OpaqueDecl.
5565-
GenericEnvironment *Environment;
5565+
mutable GenericEnvironment *Environment = nullptr;
55665566

55675567
public:
55685568
/// Get an opaque archetype representing the underlying type of the given
@@ -5586,9 +5586,7 @@ class OpaqueTypeArchetypeType final : public ArchetypeType,
55865586
GenericSignature getBoundSignature() const;
55875587

55885588
/// Get a generic environment that has this opaque archetype bound within it.
5589-
GenericEnvironment *getGenericEnvironment() const {
5590-
return Environment;
5591-
}
5589+
GenericEnvironment *getGenericEnvironment() const;
55925590

55935591
static bool classof(const TypeBase *T) {
55945592
return T->getKind() == TypeKind::OpaqueTypeArchetype;

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4318,74 +4318,8 @@ OpaqueTypeArchetypeType::get(OpaqueTypeDecl *Decl, unsigned ordinal,
43184318
}
43194319
}
43204320

4321-
// Create a new opaque archetype.
4322-
// It lives in an environment in which the interface generic arguments of the
4323-
// decl have all been same-type-bound to the arguments from our substitution
4324-
// map.
4325-
SmallVector<Requirement, 2> newRequirements;
4326-
4327-
// TODO: The proper thing to do to build the environment in which the opaque
4328-
// type's archetype exists would be to take the generic signature of the
4329-
// decl, feed it into a GenericSignatureBuilder, then add same-type
4330-
// constraints into the builder to bind the outer generic parameters
4331-
// to their substituted types provided by \c Substitutions. However,
4332-
// this is problematic for interface types. In a situation like this:
4333-
//
4334-
// __opaque_type Foo<t_0_0: P>: Q // internal signature <t_0_0: P, t_1_0: Q>
4335-
//
4336-
// func bar<t_0_0, t_0_1, t_0_2: P>() -> Foo<t_0_2>
4337-
//
4338-
// we'd want to feed the GSB constraints to form:
4339-
//
4340-
// <t_0_0: P, t_1_0: Q where t_0_0 == t_0_2>
4341-
//
4342-
// even though t_0_2 isn't *in* the generic signature being built; it
4343-
// represents a type
4344-
// bound elsewhere from some other generic context. If we knew the generic
4345-
// environment `t_0_2` came from, then maybe we could map it into that context,
4346-
// but currently we have no way to know that with certainty.
4347-
//
4348-
// Because opaque types are currently limited so that they only have immediate
4349-
// protocol constraints, and therefore don't interact with the outer generic
4350-
// parameters at all, we can get away without adding these constraints for now.
4351-
// Adding where clauses would break this hack.
4352-
#if DO_IT_CORRECTLY
4353-
// Same-type-constrain the arguments in the outer signature to their
4354-
// replacements in the substitution map.
4355-
if (auto outerSig = Decl->getGenericSignature()) {
4356-
for (auto outerParam : outerSig.getGenericParams()) {
4357-
auto boundType = Type(outerParam).subst(Substitutions);
4358-
newRequirements.push_back(
4359-
Requirement(RequirementKind::SameType, Type(outerParam), boundType));
4360-
}
4361-
}
4362-
#else
4363-
// Assert that there are no same type constraints on the opaque type or its
4364-
// associated types.
4365-
//
4366-
// This should not be possible until we add where clause support, with the
4367-
// exception of generic base class constraints (handled below).
4368-
(void)newRequirements;
4369-
# ifndef NDEBUG
4370-
for (auto req :
4371-
Decl->getOpaqueInterfaceGenericSignature().getRequirements()) {
4372-
auto reqBase = req.getFirstType()->getRootGenericParam();
4373-
if (reqBase->isEqual(opaqueParamType)) {
4374-
assert(req.getKind() != RequirementKind::SameType
4375-
&& "supporting where clauses on opaque types requires correctly "
4376-
"setting up the generic environment for "
4377-
"OpaqueTypeArchetypeTypes; see comment above");
4378-
}
4379-
}
4380-
# endif
4381-
#endif
4382-
auto signature = buildGenericSignature(
4383-
ctx,
4384-
Decl->getOpaqueInterfaceGenericSignature(),
4385-
/*genericParams=*/{ },
4386-
std::move(newRequirements));
4387-
4388-
auto reqs = signature->getLocalRequirements(opaqueParamType);
4321+
auto reqs = Decl->getOpaqueInterfaceGenericSignature()
4322+
->getLocalRequirements(opaqueParamType);
43894323
auto superclass = reqs.superclass;
43904324
#if !DO_IT_CORRECTLY
43914325
// Ad-hoc substitute the generic parameters of the superclass.
@@ -4406,12 +4340,6 @@ OpaqueTypeArchetypeType::get(OpaqueTypeDecl *Decl, unsigned ordinal,
44064340
OpaqueTypeArchetypeType(Decl, Substitutions, properties, opaqueParamType,
44074341
reqs.protos, superclass, reqs.layout);
44084342

4409-
// Create a generic environment and bind the opaque archetype to the
4410-
// opaque interface type from the decl's signature.
4411-
auto *env = GenericEnvironment::getIncomplete(signature);
4412-
env->addMapping(GenericParamKey(opaqueParamType), newOpaque);
4413-
newOpaque->Environment = env;
4414-
44154343
// Look up the insertion point in the folding set again in case something
44164344
// invalidated it above.
44174345
{

lib/AST/Type.cpp

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3304,8 +3304,90 @@ SequenceArchetypeType::SequenceArchetypeType(
33043304
assert(cast<GenericTypeParamType>(InterfaceType.getPointer())->isTypeSequence());
33053305
}
33063306

3307+
GenericEnvironment *OpaqueTypeArchetypeType::getGenericEnvironment() const {
3308+
if (Environment)
3309+
return Environment;
3310+
3311+
// Create a new opaque archetype.
3312+
// It lives in an environment in which the interface generic arguments of the
3313+
// decl have all been same-type-bound to the arguments from our substitution
3314+
// map.
3315+
SmallVector<Requirement, 2> newRequirements;
3316+
3317+
// TODO: The proper thing to do to build the environment in which the opaque
3318+
// type's archetype exists would be to take the generic signature of the
3319+
// decl, feed it into a GenericSignatureBuilder, then add same-type
3320+
// constraints into the builder to bind the outer generic parameters
3321+
// to their substituted types provided by \c Substitutions. However,
3322+
// this is problematic for interface types. In a situation like this:
3323+
//
3324+
// __opaque_type Foo<t_0_0: P>: Q // internal signature <t_0_0: P, t_1_0: Q>
3325+
//
3326+
// func bar<t_0_0, t_0_1, t_0_2: P>() -> Foo<t_0_2>
3327+
//
3328+
// we'd want to feed the GSB constraints to form:
3329+
//
3330+
// <t_0_0: P, t_1_0: Q where t_0_0 == t_0_2>
3331+
//
3332+
// even though t_0_2 isn't *in* the generic signature being built; it
3333+
// represents a type
3334+
// bound elsewhere from some other generic context. If we knew the generic
3335+
// environment `t_0_2` came from, then maybe we could map it into that context,
3336+
// but currently we have no way to know that with certainty.
3337+
//
3338+
// Because opaque types are currently limited so that they only have immediate
3339+
// protocol constraints, and therefore don't interact with the outer generic
3340+
// parameters at all, we can get away without adding these constraints for now.
3341+
// Adding where clauses would break this hack.
3342+
#if DO_IT_CORRECTLY
3343+
// Same-type-constrain the arguments in the outer signature to their
3344+
// replacements in the substitution map.
3345+
if (auto outerSig = Decl->getGenericSignature()) {
3346+
for (auto outerParam : outerSig.getGenericParams()) {
3347+
auto boundType = Type(outerParam).subst(Substitutions);
3348+
newRequirements.push_back(
3349+
Requirement(RequirementKind::SameType, Type(outerParam), boundType));
3350+
}
3351+
}
3352+
#else
3353+
// Assert that there are no same type constraints on the opaque type or its
3354+
// associated types.
3355+
//
3356+
// This should not be possible until we add where clause support, with the
3357+
// exception of generic base class constraints (handled below).
3358+
(void)newRequirements;
3359+
# ifndef NDEBUG
3360+
for (auto req : getDecl()
3361+
->getOpaqueInterfaceGenericSignature().getRequirements()) {
3362+
auto reqBase = req.getFirstType()->getRootGenericParam();
3363+
if (reqBase->isEqual(getInterfaceType())) {
3364+
assert(req.getKind() != RequirementKind::SameType
3365+
&& "supporting where clauses on opaque types requires correctly "
3366+
"setting up the generic environment for "
3367+
"OpaqueTypeArchetypeTypes; see comment above");
3368+
}
3369+
}
3370+
# endif
3371+
#endif
3372+
auto signature = buildGenericSignature(
3373+
getDecl()->getASTContext(),
3374+
getDecl()->getOpaqueInterfaceGenericSignature(),
3375+
/*genericParams=*/{ },
3376+
std::move(newRequirements));
3377+
3378+
// Create a generic environment and bind the opaque archetype to the
3379+
// opaque interface type from the decl's signature.
3380+
auto *env = GenericEnvironment::getIncomplete(signature);
3381+
env->addMapping(
3382+
GenericParamKey(getInterfaceType()->castTo<GenericTypeParamType>()),
3383+
Type(const_cast<OpaqueTypeArchetypeType *>(this)));
3384+
Environment = env;
3385+
3386+
return Environment;
3387+
}
3388+
33073389
GenericSignature OpaqueTypeArchetypeType::getBoundSignature() const {
3308-
return Environment->getGenericSignature();
3390+
return getGenericEnvironment()->getGenericSignature();
33093391
}
33103392

33113393
static Optional<std::pair<ArchetypeType *, OpaqueTypeArchetypeType*>>

0 commit comments

Comments
 (0)