Skip to content

Commit 544e0a0

Browse files
committed
AST: Don't link together GenericParamLists of nested generic types
GenericParamList::OuterParameters would mirror the nesting structure of generic DeclContexts. This resulted in redundant code and caused unnecessary complications for extensions and protocols, whose GenericParamLists are constructed after parse time. Instead, lets only use OuterParameters to link together the multiple parameter lists of a single extension, or parameter lists in SIL functions.
1 parent c0bfaaf commit 544e0a0

File tree

12 files changed

+98
-105
lines changed

12 files changed

+98
-105
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,22 +1377,11 @@ class GenericParamList final :
13771377
void addTrailingWhereClause(ASTContext &ctx, SourceLoc trailingWhereLoc,
13781378
ArrayRef<RequirementRepr> trailingRequirements);
13791379

1380-
/// Retrieve the outer generic parameter list, which provides the
1381-
/// generic parameters of the context in which this generic parameter list
1382-
/// exists.
1380+
/// Retrieve the outer generic parameter list.
13831381
///
1384-
/// Consider the following generic class:
1385-
///
1386-
/// \code
1387-
/// class Vector<T> {
1388-
/// init<R : Range where R.Element == T>(range : R) { }
1389-
/// }
1390-
/// \endcode
1391-
///
1392-
/// The generic parameter list <T> has no outer parameters, because it is
1393-
/// the outermost generic parameter list. The generic parameter list
1394-
/// <R : Range...> for the constructor has the generic parameter list <T> as
1395-
/// its outer generic parameter list.
1382+
/// This is used for extensions of nested types, and in SIL mode, where a
1383+
/// single lexical context can have multiple logical generic parameter
1384+
/// lists.
13961385
GenericParamList *getOuterParameters() const { return OuterParameters; }
13971386

13981387
/// Set the outer generic parameter list. See \c getOuterParameters
@@ -1422,10 +1411,8 @@ class GenericParamList final :
14221411
Requirements.back().getSourceRange().End);
14231412
}
14241413

1425-
unsigned getDepth() const;
1426-
14271414
/// Configure the depth of the generic parameters in this list.
1428-
void configureGenericParamDepth();
1415+
void setDepth(unsigned depth);
14291416

14301417
/// Create a copy of the generic parameter list and all of its generic
14311418
/// parameter declarations. The copied generic parameters are re-parented

include/swift/AST/DeclContext.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,16 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
336336
/// - Everything else falls back on getDeclaredInterfaceType().
337337
Type getSelfInterfaceType() const;
338338

339+
/// Visit the generic parameter list of every outer context, innermost first.
340+
void forEachGenericContext(
341+
llvm::function_ref<void (GenericParamList *)> fn) const;
342+
343+
/// Returns the depth of this generic context, or in other words,
344+
/// the number of nested generic contexts minus one.
345+
///
346+
/// This is (unsigned)-1 if none of the outer contexts are generic.
347+
unsigned getGenericContextDepth() const;
348+
339349
/// Retrieve the innermost generic parameters of this context or any
340350
/// of its parents.
341351
///

include/swift/Serialization/ModuleFile.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,7 @@ class ModuleFile
562562
///
563563
/// If the record at the cursor is not a generic param list, returns null
564564
/// without moving the cursor.
565-
GenericParamList *maybeReadGenericParams(DeclContext *DC,
566-
GenericParamList *outerParams = nullptr);
565+
GenericParamList *maybeReadGenericParams(DeclContext *DC);
567566

568567
/// Reads a set of requirements from \c DeclTypeCursor.
569568
void readGenericRequirements(SmallVectorImpl<Requirement> &requirements,

lib/AST/ASTMangler.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,8 +1053,6 @@ unsigned ASTMangler::appendBoundGenericArgs(DeclContext *dc,
10531053
if (genericContext->isGeneric()) {
10541054
auto genericParams = subs.getGenericSignature()->getGenericParams();
10551055
unsigned depth = genericParams[currentGenericParamIdx]->getDepth();
1056-
assert(genericContext->getGenericParams()->getDepth() == depth &&
1057-
"Depth mismatch mangling substitution map");
10581056
auto replacements = subs.getReplacementTypes();
10591057
for (unsigned lastGenericParamIdx = genericParams.size();
10601058
(currentGenericParamIdx != lastGenericParamIdx &&

lib/AST/ASTVerifier.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2762,7 +2762,14 @@ class Verifier : public ASTWalker {
27622762
abort();
27632763
}
27642764

2765-
unsigned currentDepth = paramList->getDepth();
2765+
if (paramList->getOuterParameters() &&
2766+
!isa<ExtensionDecl>(DC)) {
2767+
Out << "GenericParamList can only have outer parameters in an "
2768+
"extension\n";
2769+
abort();
2770+
}
2771+
2772+
unsigned currentDepth = DC->getGenericContextDepth();
27662773
if (currentDepth < GTPD->getDepth()) {
27672774
Out << "GenericTypeParamDecl has incorrect depth\n";
27682775
abort();

lib/AST/Decl.cpp

Lines changed: 24 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -687,17 +687,7 @@ void GenericParamList::addTrailingWhereClause(
687687
Requirements = newRequirements;
688688
}
689689

690-
unsigned GenericParamList::getDepth() const {
691-
unsigned depth = 0;
692-
for (auto gpList = getOuterParameters();
693-
gpList != nullptr;
694-
gpList = gpList->getOuterParameters())
695-
++depth;
696-
return depth;
697-
}
698-
699-
void GenericParamList::configureGenericParamDepth() {
700-
unsigned depth = getDepth();
690+
void GenericParamList::setDepth(unsigned depth) {
701691
for (auto param : *this)
702692
param->setDepth(depth);
703693
}
@@ -1059,13 +1049,13 @@ AccessLevel ExtensionDecl::getMaxAccessLevel() const {
10591049
/// Clone the given generic parameters in the given list. We don't need any
10601050
/// of the requirements, because they will be inferred.
10611051
static GenericParamList *cloneGenericParams(ASTContext &ctx,
1062-
DeclContext *dc,
1052+
ExtensionDecl *ext,
10631053
GenericParamList *fromParams) {
10641054
// Clone generic parameters.
10651055
SmallVector<GenericTypeParamDecl *, 2> toGenericParams;
10661056
for (auto fromGP : *fromParams) {
10671057
// Create the new generic parameter.
1068-
auto toGP = new (ctx) GenericTypeParamDecl(dc, fromGP->getName(),
1058+
auto toGP = new (ctx) GenericTypeParamDecl(ext, fromGP->getName(),
10691059
SourceLoc(),
10701060
fromGP->getDepth(),
10711061
fromGP->getIndex());
@@ -1075,40 +1065,28 @@ static GenericParamList *cloneGenericParams(ASTContext &ctx,
10751065
toGenericParams.push_back(toGP);
10761066
}
10771067

1078-
auto toParams = GenericParamList::create(ctx, SourceLoc(), toGenericParams,
1079-
SourceLoc());
1080-
1081-
auto outerParams = fromParams->getOuterParameters();
1082-
if (outerParams != nullptr)
1083-
outerParams = cloneGenericParams(ctx, dc, outerParams);
1084-
toParams->setOuterParameters(outerParams);
1085-
1086-
return toParams;
1068+
return GenericParamList::create(ctx, SourceLoc(), toGenericParams,
1069+
SourceLoc());
10871070
}
10881071

1089-
/// Ensure that the outer generic parameters of the given generic
1090-
/// context have been configured.
1091-
static void configureOuterGenericParams(const GenericContext *dc) {
1092-
auto genericParams = dc->getGenericParams();
1093-
1094-
// If we already configured the outer parameters, we're done.
1095-
if (genericParams && genericParams->getOuterParameters())
1096-
return;
1097-
1098-
DeclContext *outerDC = dc->getParent();
1099-
while (!outerDC->isModuleScopeContext()) {
1100-
if (auto outerDecl = outerDC->getAsDecl()) {
1101-
if (auto outerGenericDC = outerDecl->getAsGenericContext()) {
1102-
if (genericParams)
1103-
genericParams->setOuterParameters(outerGenericDC->getGenericParams());
1104-
1105-
configureOuterGenericParams(outerGenericDC);
1106-
return;
1107-
}
1108-
}
1072+
static GenericParamList *
1073+
createExtensionGenericParams(ASTContext &ctx,
1074+
ExtensionDecl *ext,
1075+
NominalTypeDecl *nominal) {
1076+
// Collect generic parameters from all outer contexts.
1077+
SmallVector<GenericParamList *, 2> allGenericParams;
1078+
nominal->forEachGenericContext([&](GenericParamList *gpList) {
1079+
allGenericParams.push_back(
1080+
cloneGenericParams(ctx, ext, gpList));
1081+
});
11091082

1110-
outerDC = outerDC->getParent();
1083+
GenericParamList *toParams = nullptr;
1084+
for (auto *gpList : reversed(allGenericParams)) {
1085+
gpList->setOuterParameters(toParams);
1086+
toParams = gpList;
11111087
}
1088+
1089+
return toParams;
11121090
}
11131091

11141092
void ExtensionDecl::createGenericParamsIfMissing(NominalTypeDecl *nominal) {
@@ -1125,14 +1103,10 @@ void ExtensionDecl::createGenericParamsIfMissing(NominalTypeDecl *nominal) {
11251103
outerDC = outerDC->getParent();
11261104
}
11271105

1128-
configureOuterGenericParams(nominal);
1129-
11301106
// Create the generic parameter list for the extension by cloning the
11311107
// generic parameter lists of the nominal and any of its parent types.
11321108
auto &ctx = getASTContext();
1133-
auto *genericParams = nominal->getGenericParamsOfContext();
1134-
if (genericParams != nullptr)
1135-
genericParams = cloneGenericParams(ctx, this, genericParams);
1109+
auto *genericParams = createExtensionGenericParams(ctx, this, nominal);
11361110
setGenericParams(genericParams);
11371111

11381112
// Protocol extensions need an inheritance clause due to how name lookup
@@ -1145,10 +1119,11 @@ void ExtensionDecl::createGenericParamsIfMissing(NominalTypeDecl *nominal) {
11451119
}
11461120

11471121
// Set the depth of every generic parameter.
1122+
unsigned depth = nominal->getGenericContextDepth();
11481123
for (auto *outerParams = genericParams;
11491124
outerParams != nullptr;
11501125
outerParams = outerParams->getOuterParameters())
1151-
outerParams->configureGenericParamDepth();
1126+
outerParams->setDepth(depth--);
11521127

11531128
// If we have a trailing where clause, deal with it now.
11541129
// For now, trailing where clauses are only permitted on protocol extensions.
@@ -4301,8 +4276,6 @@ void ProtocolDecl::createGenericParamsIfMissing() {
43014276
if (getGenericParams())
43024277
return;
43034278

4304-
auto *outerGenericParams = getParent()->getGenericParamsOfContext();
4305-
43064279
// The generic parameter 'Self'.
43074280
auto &ctx = getASTContext();
43084281
auto selfId = ctx.Id_Self;
@@ -4318,7 +4291,6 @@ void ProtocolDecl::createGenericParamsIfMissing() {
43184291
// The generic parameter list itself.
43194292
auto result = GenericParamList::create(ctx, SourceLoc(), selfDecl,
43204293
SourceLoc());
4321-
result->setOuterParameters(outerGenericParams);
43224294
setGenericParams(result);
43234295
}
43244296

lib/AST/DeclContext.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,42 @@ Type DeclContext::getDeclaredInterfaceType() const {
123123
return Type();
124124
}
125125

126+
void DeclContext::forEachGenericContext(
127+
llvm::function_ref<void (GenericParamList *)> fn) const {
128+
auto dc = this;
129+
do {
130+
if (auto decl = dc->getAsDecl()) {
131+
// Extensions do not capture outer generic parameters.
132+
if (auto *ext = dyn_cast<ExtensionDecl>(decl)) {
133+
for (auto *gpList = ext->getGenericParams();
134+
gpList != nullptr;
135+
gpList = gpList->getOuterParameters()) {
136+
fn(gpList);
137+
}
138+
139+
return;
140+
}
141+
142+
if (auto genericCtx = decl->getAsGenericContext())
143+
if (auto *gpList = genericCtx->getGenericParams())
144+
fn(gpList);
145+
}
146+
} while ((dc = dc->getParent()));
147+
}
148+
149+
unsigned DeclContext::getGenericContextDepth() const {
150+
unsigned depth = -1;
151+
forEachGenericContext([&](GenericParamList *) { ++depth; });
152+
return depth;
153+
}
154+
126155
GenericParamList *DeclContext::getGenericParamsOfContext() const {
127156
auto dc = this;
128157
do {
129158
if (auto decl = dc->getAsDecl()) {
130159
if (auto GC = decl->getAsGenericContext()) {
131160
auto GP = GC->getGenericParams();
161+
132162
// Extensions do not capture outer generic parameters.
133163
if (GP != nullptr || isa<ExtensionDecl>(decl))
134164
return GP;

lib/AST/NameLookup.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,11 +1077,6 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
10771077
if (shouldReturnBasedOnResults())
10781078
return;
10791079

1080-
// Extensions of nested types have multiple levels of
1081-
// generic parameters, so we have to visit them explicitly.
1082-
if (!isa<ExtensionDecl>(DC))
1083-
break;
1084-
10851080
dcGenericParams = dcGenericParams->getOuterParameters();
10861081
}
10871082

lib/Sema/CodeSynthesis.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1811,7 +1811,6 @@ configureGenericDesignatedInitOverride(ASTContext &ctx,
18111811
SourceLoc(),
18121812
ArrayRef<RequirementRepr>(),
18131813
SourceLoc());
1814-
genericParams->setOuterParameters(classDecl->getGenericParamsOfContext());
18151814

18161815
// Build a generic signature for the derived class initializer.
18171816
GenericSignatureBuilder builder(ctx);

lib/Sema/TypeCheckDecl.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -640,14 +640,16 @@ TypeChecker::handleSILGenericParams(GenericParamList *genericParams,
640640
nestedList.push_back(genericParams);
641641
}
642642

643+
std::reverse(nestedList.begin(), nestedList.end());
644+
643645
// Since the innermost GenericParamList is in the beginning of the vector,
644646
// we process in reverse order to handle the outermost list first.
645647
GenericSignature *parentSig = nullptr;
646648
GenericEnvironment *parentEnv = nullptr;
647649

648-
for (unsigned i = 0, e = nestedList.size(); i < e; i++) {
649-
auto genericParams = nestedList.rbegin()[i];
650-
genericParams->configureGenericParamDepth();
650+
for (unsigned i = 0, e = nestedList.size(); i < e; ++i) {
651+
auto genericParams = nestedList[i];
652+
genericParams->setDepth(i);
651653

652654
parentEnv = checkGenericEnvironment(genericParams, DC, parentSig,
653655
/*allowConcreteGenericParams=*/true,
@@ -4172,9 +4174,7 @@ void TypeChecker::validateDeclForNameLookup(ValueDecl *D) {
41724174
proto->computeType();
41734175

41744176
auto *gp = proto->getGenericParams();
4175-
unsigned depth = gp->getDepth();
4176-
for (auto paramDecl : *gp)
4177-
paramDecl->setDepth(depth);
4177+
gp->setDepth(proto->getGenericContextDepth());
41784178

41794179
for (auto ATD : proto->getAssociatedTypeMembers()) {
41804180
validateDeclForNameLookup(ATD);

0 commit comments

Comments
 (0)