Skip to content

Commit 24d24c0

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 2bf9bfa commit 24d24c0

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
@@ -245,16 +245,6 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
245245
/// Stores information about lazy deserialization of various declarations.
246246
llvm::DenseMap<const DeclContext *, LazyContextData *> LazyContexts;
247247

248-
/// Stored generic signature builders for canonical generic signatures.
249-
llvm::DenseMap<GenericSignature *, std::unique_ptr<GenericSignatureBuilder>>
250-
GenericSignatureBuilders;
251-
252-
/// Canonical generic environments for canonical generic signatures.
253-
///
254-
/// The keys are the generic signature builders in \c GenericSignatureBuilders.
255-
llvm::DenseMap<GenericSignatureBuilder *, GenericEnvironment *>
256-
CanonicalGenericEnvironments;
257-
258248
/// The single-parameter generic signature with no constraints, <T>.
259249
CanGenericSignature SingleGenericParameterSignature;
260250

@@ -327,6 +317,19 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
327317
llvm::FoldingSet<LayoutConstraintInfo> LayoutConstraints;
328318
llvm::FoldingSet<OpaqueTypeArchetypeType> OpaqueArchetypes;
329319

320+
llvm::FoldingSet<GenericSignature> GenericSignatures;
321+
322+
/// Stored generic signature builders for canonical generic signatures.
323+
llvm::DenseMap<GenericSignature *, std::unique_ptr<GenericSignatureBuilder>>
324+
GenericSignatureBuilders;
325+
326+
/// Canonical generic environments for canonical generic signatures.
327+
///
328+
/// The keys are the generic signature builders in
329+
/// \c GenericSignatureBuilders.
330+
llvm::DenseMap<GenericSignatureBuilder *, GenericEnvironment *>
331+
CanonicalGenericEnvironments;
332+
330333
/// The set of function types.
331334
llvm::FoldingSet<FunctionType> FunctionTypes;
332335

@@ -377,7 +380,6 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
377380
llvm::FoldingSet<SILBoxType> SILBoxTypes;
378381
llvm::DenseMap<BuiltinIntegerWidth, BuiltinIntegerType*> IntegerTypes;
379382
llvm::FoldingSet<BuiltinVectorType> BuiltinVectorTypes;
380-
llvm::FoldingSet<GenericSignature> GenericSignatures;
381383
llvm::FoldingSet<DeclName::CompoundDeclName> CompoundNames;
382384
llvm::DenseMap<UUID, OpenedArchetypeType *> OpenedExistentialArchetypes;
383385

@@ -1427,34 +1429,50 @@ void ASTContext::getVisibleTopLevelClangModules(
14271429
collectAllModules(Modules);
14281430
}
14291431

1432+
static AllocationArena getArena(GenericSignature *genericSig) {
1433+
if (!genericSig)
1434+
return AllocationArena::Permanent;
1435+
1436+
if (genericSig->hasTypeVariable())
1437+
return AllocationArena::ConstraintSolver;
1438+
1439+
return AllocationArena::Permanent;
1440+
}
1441+
14301442
void ASTContext::registerGenericSignatureBuilder(
14311443
GenericSignature *sig,
14321444
GenericSignatureBuilder &&builder) {
14331445
auto canSig = sig->getCanonicalSignature();
1434-
auto known = getImpl().GenericSignatureBuilders.find(canSig);
1435-
if (known != getImpl().GenericSignatureBuilders.end()) {
1446+
auto arena = getArena(sig);
1447+
auto &genericSignatureBuilders =
1448+
getImpl().getArena(arena).GenericSignatureBuilders;
1449+
auto known = genericSignatureBuilders.find(canSig);
1450+
if (known != genericSignatureBuilders.end()) {
14361451
++NumRegisteredGenericSignatureBuildersAlready;
14371452
return;
14381453
}
14391454

14401455
++NumRegisteredGenericSignatureBuilders;
1441-
getImpl().GenericSignatureBuilders[canSig] =
1456+
genericSignatureBuilders[canSig] =
14421457
llvm::make_unique<GenericSignatureBuilder>(std::move(builder));
14431458
}
14441459

14451460
GenericSignatureBuilder *ASTContext::getOrCreateGenericSignatureBuilder(
14461461
CanGenericSignature sig) {
14471462
// Check whether we already have a generic signature builder for this
14481463
// signature and module.
1449-
auto known = getImpl().GenericSignatureBuilders.find(sig);
1450-
if (known != getImpl().GenericSignatureBuilders.end())
1464+
auto arena = getArena(sig);
1465+
auto &genericSignatureBuilders =
1466+
getImpl().getArena(arena).GenericSignatureBuilders;
1467+
auto known = genericSignatureBuilders.find(sig);
1468+
if (known != genericSignatureBuilders.end())
14511469
return known->second.get();
14521470

14531471
// Create a new generic signature builder with the given signature.
14541472
auto builder = new GenericSignatureBuilder(*this);
14551473

14561474
// Store this generic signature builder (no generic environment yet).
1457-
getImpl().GenericSignatureBuilders[sig] =
1475+
genericSignatureBuilders[sig] =
14581476
std::unique_ptr<GenericSignatureBuilder>(builder);
14591477

14601478
builder->addGenericSignature(sig);
@@ -1525,12 +1543,16 @@ GenericSignatureBuilder *ASTContext::getOrCreateGenericSignatureBuilder(
15251543
GenericEnvironment *ASTContext::getOrCreateCanonicalGenericEnvironment(
15261544
GenericSignatureBuilder *builder,
15271545
GenericSignature *sig) {
1528-
auto known = getImpl().CanonicalGenericEnvironments.find(builder);
1529-
if (known != getImpl().CanonicalGenericEnvironments.end())
1546+
auto arena = getArena(sig);
1547+
auto &canonicalGenericEnvironments =
1548+
getImpl().getArena(arena).CanonicalGenericEnvironments;
1549+
1550+
auto known = canonicalGenericEnvironments.find(builder);
1551+
if (known != canonicalGenericEnvironments.end())
15301552
return known->second;
15311553

15321554
auto env = sig->createGenericEnvironment();
1533-
getImpl().CanonicalGenericEnvironments[builder] = env;
1555+
canonicalGenericEnvironments[builder] = env;
15341556
return env;
15351557
}
15361558

@@ -3774,10 +3796,14 @@ GenericSignature::get(TypeArrayView<GenericTypeParamType> params,
37743796
llvm::FoldingSetNodeID ID;
37753797
GenericSignature::Profile(ID, params, requirements);
37763798

3799+
auto arena = GenericSignature::hasTypeVariable(requirements)
3800+
? AllocationArena::ConstraintSolver
3801+
: AllocationArena::Permanent;
3802+
37773803
auto &ctx = getASTContext(params, requirements);
37783804
void *insertPos;
3779-
if (auto *sig = ctx.getImpl().GenericSignatures.FindNodeOrInsertPos(ID,
3780-
insertPos)) {
3805+
if (auto *sig = ctx.getImpl().getArena(arena).GenericSignatures
3806+
.FindNodeOrInsertPos(ID, insertPos)) {
37813807
if (isKnownCanonical)
37823808
sig->CanonicalSignatureOrASTContext = &ctx;
37833809

@@ -3790,7 +3816,7 @@ GenericSignature::get(TypeArrayView<GenericTypeParamType> params,
37903816
void *mem = ctx.Allocate(bytes, alignof(GenericSignature));
37913817
auto newSig = new (mem) GenericSignature(params, requirements,
37923818
isKnownCanonical);
3793-
ctx.getImpl().GenericSignatures.InsertNode(newSig, insertPos);
3819+
ctx.getImpl().getArena(arena).GenericSignatures.InsertNode(newSig, insertPos);
37943820
return newSig;
37953821
}
37963822

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
@@ -5404,9 +5404,15 @@ namespace {
54045404
ArrayRef<Constraint<T>> constraints,
54055405
llvm::function_ref<bool(const Constraint<T> &)>
54065406
isSuitableRepresentative) {
5407+
Optional<Constraint<T>> fallbackConstraint;
5408+
54075409
// Find a representative constraint.
54085410
Optional<Constraint<T>> representativeConstraint;
54095411
for (const auto &constraint : constraints) {
5412+
// Make sure we have a constraint to fall back on.
5413+
if (!fallbackConstraint)
5414+
fallbackConstraint = constraint;
5415+
54105416
// If this isn't a suitable representative constraint, ignore it.
54115417
if (!isSuitableRepresentative(constraint))
54125418
continue;
@@ -5457,7 +5463,8 @@ namespace {
54575463
representativeConstraint = constraint;
54585464
}
54595465

5460-
return representativeConstraint;
5466+
return representativeConstraint ? representativeConstraint
5467+
: fallbackConstraint;
54615468
}
54625469
} // end anonymous namespace
54635470

@@ -6996,9 +7003,11 @@ void GenericSignatureBuilder::checkConcreteTypeConstraints(
69967003
if (concreteType->isEqual(equivClass->concreteType))
69977004
return ConstraintRelation::Redundant;
69987005

6999-
// If either has a type parameter, call them unrelated.
7006+
// If either has a type parameter or type variable, call them unrelated.
70007007
if (concreteType->hasTypeParameter() ||
7001-
equivClass->concreteType->hasTypeParameter())
7008+
equivClass->concreteType->hasTypeParameter() ||
7009+
concreteType->hasTypeVariable() ||
7010+
equivClass->concreteType->hasTypeVariable())
70027011
return ConstraintRelation::Unrelated;
70037012

70047013
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)