Skip to content

Commit 13824e9

Browse files
committed
[AST] Allocate GenericSignature(Builders) in the arena
Opaque result type archetypes can involve type variables, which then get introduced into GenericSignatureBuilders and the generated GenericSignatures. Allocate them in the proper arena So we don’t end up with use-after-free errors. Fixes rdar://problem/50309503.
1 parent 16641da commit 13824e9

File tree

5 files changed

+106
-26
lines changed

5 files changed

+106
-26
lines changed

include/swift/AST/GenericSignature.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,12 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
312312
/// generic parameters to themselves.
313313
SubstitutionMap getIdentitySubstitutionMap() const;
314314

315+
/// Whether this generic signature involves a type variable.
316+
bool hasTypeVariable() const;
317+
318+
/// Whether the given set of requirements involves a type variable.
319+
static bool hasTypeVariable(ArrayRef<Requirement> requirements);
320+
315321
static void Profile(llvm::FoldingSetNodeID &ID,
316322
TypeArrayView<GenericTypeParamType> genericParams,
317323
ArrayRef<Requirement> requirements);

lib/AST/ASTContext.cpp

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -259,16 +259,6 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
259259
/// Stores information about lazy deserialization of various declarations.
260260
llvm::DenseMap<const DeclContext *, LazyContextData *> LazyContexts;
261261

262-
/// Stored generic signature builders for canonical generic signatures.
263-
llvm::DenseMap<GenericSignature *, std::unique_ptr<GenericSignatureBuilder>>
264-
GenericSignatureBuilders;
265-
266-
/// Canonical generic environments for canonical generic signatures.
267-
///
268-
/// The keys are the generic signature builders in \c GenericSignatureBuilders.
269-
llvm::DenseMap<GenericSignatureBuilder *, GenericEnvironment *>
270-
CanonicalGenericEnvironments;
271-
272262
/// The single-parameter generic signature with no constraints, <T>.
273263
CanGenericSignature SingleGenericParameterSignature;
274264

@@ -334,6 +324,19 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
334324
llvm::FoldingSet<LayoutConstraintInfo> LayoutConstraints;
335325
llvm::FoldingSet<OpaqueTypeArchetypeType> OpaqueArchetypes;
336326

327+
llvm::FoldingSet<GenericSignature> GenericSignatures;
328+
329+
/// Stored generic signature builders for canonical generic signatures.
330+
llvm::DenseMap<GenericSignature *, std::unique_ptr<GenericSignatureBuilder>>
331+
GenericSignatureBuilders;
332+
333+
/// Canonical generic environments for canonical generic signatures.
334+
///
335+
/// The keys are the generic signature builders in
336+
/// \c GenericSignatureBuilders.
337+
llvm::DenseMap<GenericSignatureBuilder *, GenericEnvironment *>
338+
CanonicalGenericEnvironments;
339+
337340
/// The set of function types.
338341
llvm::FoldingSet<FunctionType> FunctionTypes;
339342

@@ -384,7 +387,6 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
384387
llvm::FoldingSet<SILBoxType> SILBoxTypes;
385388
llvm::DenseMap<BuiltinIntegerWidth, BuiltinIntegerType*> IntegerTypes;
386389
llvm::FoldingSet<BuiltinVectorType> BuiltinVectorTypes;
387-
llvm::FoldingSet<GenericSignature> GenericSignatures;
388390
llvm::FoldingSet<DeclName::CompoundDeclName> CompoundNames;
389391
llvm::DenseMap<UUID, OpenedArchetypeType *> OpenedExistentialArchetypes;
390392

@@ -1506,34 +1508,50 @@ void ASTContext::getVisibleTopLevelClangModules(
15061508
collectAllModules(Modules);
15071509
}
15081510

1511+
static AllocationArena getArena(GenericSignature *genericSig) {
1512+
if (!genericSig)
1513+
return AllocationArena::Permanent;
1514+
1515+
if (genericSig->hasTypeVariable())
1516+
return AllocationArena::ConstraintSolver;
1517+
1518+
return AllocationArena::Permanent;
1519+
}
1520+
15091521
void ASTContext::registerGenericSignatureBuilder(
15101522
GenericSignature *sig,
15111523
GenericSignatureBuilder &&builder) {
15121524
auto canSig = sig->getCanonicalSignature();
1513-
auto known = getImpl().GenericSignatureBuilders.find(canSig);
1514-
if (known != getImpl().GenericSignatureBuilders.end()) {
1525+
auto arena = getArena(sig);
1526+
auto &genericSignatureBuilders =
1527+
getImpl().getArena(arena).GenericSignatureBuilders;
1528+
auto known = genericSignatureBuilders.find(canSig);
1529+
if (known != genericSignatureBuilders.end()) {
15151530
++NumRegisteredGenericSignatureBuildersAlready;
15161531
return;
15171532
}
15181533

15191534
++NumRegisteredGenericSignatureBuilders;
1520-
getImpl().GenericSignatureBuilders[canSig] =
1535+
genericSignatureBuilders[canSig] =
15211536
llvm::make_unique<GenericSignatureBuilder>(std::move(builder));
15221537
}
15231538

15241539
GenericSignatureBuilder *ASTContext::getOrCreateGenericSignatureBuilder(
15251540
CanGenericSignature sig) {
15261541
// Check whether we already have a generic signature builder for this
15271542
// signature and module.
1528-
auto known = getImpl().GenericSignatureBuilders.find(sig);
1529-
if (known != getImpl().GenericSignatureBuilders.end())
1543+
auto arena = getArena(sig);
1544+
auto &genericSignatureBuilders =
1545+
getImpl().getArena(arena).GenericSignatureBuilders;
1546+
auto known = genericSignatureBuilders.find(sig);
1547+
if (known != genericSignatureBuilders.end())
15301548
return known->second.get();
15311549

15321550
// Create a new generic signature builder with the given signature.
15331551
auto builder = new GenericSignatureBuilder(*this);
15341552

15351553
// Store this generic signature builder (no generic environment yet).
1536-
getImpl().GenericSignatureBuilders[sig] =
1554+
genericSignatureBuilders[sig] =
15371555
std::unique_ptr<GenericSignatureBuilder>(builder);
15381556

15391557
builder->addGenericSignature(sig);
@@ -1604,12 +1622,16 @@ GenericSignatureBuilder *ASTContext::getOrCreateGenericSignatureBuilder(
16041622
GenericEnvironment *ASTContext::getOrCreateCanonicalGenericEnvironment(
16051623
GenericSignatureBuilder *builder,
16061624
GenericSignature *sig) {
1607-
auto known = getImpl().CanonicalGenericEnvironments.find(builder);
1608-
if (known != getImpl().CanonicalGenericEnvironments.end())
1625+
auto arena = getArena(sig);
1626+
auto &canonicalGenericEnvironments =
1627+
getImpl().getArena(arena).CanonicalGenericEnvironments;
1628+
1629+
auto known = canonicalGenericEnvironments.find(builder);
1630+
if (known != canonicalGenericEnvironments.end())
16091631
return known->second;
16101632

16111633
auto env = sig->createGenericEnvironment();
1612-
getImpl().CanonicalGenericEnvironments[builder] = env;
1634+
canonicalGenericEnvironments[builder] = env;
16131635
return env;
16141636
}
16151637

@@ -4608,10 +4630,14 @@ GenericSignature::get(TypeArrayView<GenericTypeParamType> params,
46084630
llvm::FoldingSetNodeID ID;
46094631
GenericSignature::Profile(ID, params, requirements);
46104632

4633+
auto arena = GenericSignature::hasTypeVariable(requirements)
4634+
? AllocationArena::ConstraintSolver
4635+
: AllocationArena::Permanent;
4636+
46114637
auto &ctx = getASTContext(params, requirements);
46124638
void *insertPos;
4613-
if (auto *sig = ctx.getImpl().GenericSignatures.FindNodeOrInsertPos(ID,
4614-
insertPos)) {
4639+
if (auto *sig = ctx.getImpl().getArena(arena).GenericSignatures
4640+
.FindNodeOrInsertPos(ID, insertPos)) {
46154641
if (isKnownCanonical)
46164642
sig->CanonicalSignatureOrASTContext = &ctx;
46174643

@@ -4624,7 +4650,7 @@ GenericSignature::get(TypeArrayView<GenericTypeParamType> params,
46244650
void *mem = ctx.Allocate(bytes, alignof(GenericSignature));
46254651
auto newSig = new (mem) GenericSignature(params, requirements,
46264652
isKnownCanonical);
4627-
ctx.getImpl().GenericSignatures.InsertNode(newSig, insertPos);
4653+
ctx.getImpl().getArena(arena).GenericSignatures.InsertNode(newSig, insertPos);
46284654
return newSig;
46294655
}
46304656

lib/AST/GenericSignature.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,3 +1042,28 @@ unsigned GenericSignature::getGenericParamOrdinal(GenericTypeParamType *param) {
10421042
.findIndexIn(getGenericParams());
10431043
}
10441044

1045+
bool GenericSignature::hasTypeVariable() const {
1046+
return hasTypeVariable(getRequirements());
1047+
}
1048+
1049+
bool GenericSignature::hasTypeVariable(ArrayRef<Requirement> requirements) {
1050+
for (const auto &req : requirements) {
1051+
if (req.getFirstType()->hasTypeVariable())
1052+
return true;
1053+
1054+
switch (req.getKind()) {
1055+
case RequirementKind::Layout:
1056+
break;
1057+
1058+
case RequirementKind::Conformance:
1059+
case RequirementKind::SameType:
1060+
case RequirementKind::Superclass:
1061+
if (req.getSecondType()->hasTypeVariable())
1062+
return true;
1063+
break;
1064+
}
1065+
}
1066+
1067+
return false;
1068+
}
1069+

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5426,9 +5426,15 @@ namespace {
54265426
ArrayRef<Constraint<T>> constraints,
54275427
llvm::function_ref<bool(const Constraint<T> &)>
54285428
isSuitableRepresentative) {
5429+
Optional<Constraint<T>> fallbackConstraint;
5430+
54295431
// Find a representative constraint.
54305432
Optional<Constraint<T>> representativeConstraint;
54315433
for (const auto &constraint : constraints) {
5434+
// Make sure we have a constraint to fall back on.
5435+
if (!fallbackConstraint)
5436+
fallbackConstraint = constraint;
5437+
54325438
// If this isn't a suitable representative constraint, ignore it.
54335439
if (!isSuitableRepresentative(constraint))
54345440
continue;
@@ -5479,7 +5485,8 @@ namespace {
54795485
representativeConstraint = constraint;
54805486
}
54815487

5482-
return representativeConstraint;
5488+
return representativeConstraint ? representativeConstraint
5489+
: fallbackConstraint;
54835490
}
54845491
} // end anonymous namespace
54855492

@@ -7018,9 +7025,11 @@ void GenericSignatureBuilder::checkConcreteTypeConstraints(
70187025
if (concreteType->isEqual(equivClass->concreteType))
70197026
return ConstraintRelation::Redundant;
70207027

7021-
// If either has a type parameter, call them unrelated.
7028+
// If either has a type parameter or type variable, call them unrelated.
70227029
if (concreteType->hasTypeParameter() ||
7023-
equivClass->concreteType->hasTypeParameter())
7030+
equivClass->concreteType->hasTypeParameter() ||
7031+
concreteType->hasTypeVariable() ||
7032+
equivClass->concreteType->hasTypeVariable())
70247033
return ConstraintRelation::Unrelated;
70257034

70267035
return ConstraintRelation::Conflicting;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend -emit-ir -o /dev/null %s
2+
3+
protocol P {
4+
associatedtype AT
5+
func foo() -> AT
6+
}
7+
8+
struct X<C1: Collection, C2: Collection, T>: P
9+
where C1.Element == C2.Element
10+
{
11+
func foo() -> some P {
12+
return self
13+
}
14+
}

0 commit comments

Comments
 (0)