Skip to content

Commit 1db29e7

Browse files
authored
Merge pull request swiftlang#21243 from slavapestov/clean-up-outer-parameters
Simplify GenericParamList nesting
2 parents c3ca9a7 + 3c174a9 commit 1db29e7

16 files changed

+151
-196
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 22 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
@@ -4107,10 +4094,6 @@ class ProtocolDecl final : public NominalTypeDecl {
41074094
/// with the Objective-C runtime.
41084095
StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;
41094096

4110-
/// Create the implicit generic parameter list for a protocol or
4111-
/// extension thereof.
4112-
GenericParamList *createGenericParams(DeclContext *dc);
4113-
41144097
/// Create the generic parameters of this protocol if the haven't been
41154098
/// created yet.
41164099
void createGenericParamsIfMissing();

include/swift/AST/DeclContext.h

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

339-
/// Retrieve the innermost generic parameters of this context or any
340-
/// of its parents.
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.
341345
///
342-
/// FIXME: Remove this
343-
GenericParamList *getGenericParamsOfContext() const;
346+
/// This is (unsigned)-1 if none of the outer contexts are generic.
347+
unsigned getGenericContextDepth() const;
344348

345349
/// Retrieve the innermost generic signature of this context or any
346350
/// of its parents.

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: 41 additions & 65 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,24 +1103,27 @@ void ExtensionDecl::createGenericParamsIfMissing(NominalTypeDecl *nominal) {
11251103
outerDC = outerDC->getParent();
11261104
}
11271105

1128-
configureOuterGenericParams(nominal);
1106+
// Create the generic parameter list for the extension by cloning the
1107+
// generic parameter lists of the nominal and any of its parent types.
1108+
auto &ctx = getASTContext();
1109+
auto *genericParams = createExtensionGenericParams(ctx, this, nominal);
1110+
setGenericParams(genericParams);
11291111

1130-
if (auto proto = dyn_cast<ProtocolDecl>(nominal)) {
1131-
// For a protocol extension, build the generic parameter list directly
1132-
// since we want it to have an inheritance clause.
1133-
setGenericParams(proto->createGenericParams(this));
1134-
} else if (auto genericParams = nominal->getGenericParamsOfContext()) {
1135-
// Clone the generic parameter list of a generic type.
1136-
setGenericParams(
1137-
cloneGenericParams(getASTContext(), this, genericParams));
1112+
// Protocol extensions need an inheritance clause due to how name lookup
1113+
// is implemented.
1114+
if (auto *proto = dyn_cast<ProtocolDecl>(nominal)) {
1115+
auto protoType = proto->getDeclaredType();
1116+
TypeLoc selfInherited[1] = { TypeLoc::withoutLoc(protoType) };
1117+
genericParams->getParams().front()->setInherited(
1118+
ctx.AllocateCopy(selfInherited));
11381119
}
11391120

11401121
// Set the depth of every generic parameter.
1141-
auto *genericParams = getGenericParams();
1122+
unsigned depth = nominal->getGenericContextDepth();
11421123
for (auto *outerParams = genericParams;
11431124
outerParams != nullptr;
11441125
outerParams = outerParams->getOuterParameters())
1145-
outerParams->configureGenericParamDepth();
1126+
outerParams->setDepth(depth--);
11461127

11471128
// If we have a trailing where clause, deal with it now.
11481129
// For now, trailing where clauses are only permitted on protocol extensions.
@@ -4291,16 +4272,17 @@ StringRef ProtocolDecl::getObjCRuntimeName(
42914272
return mangleObjCRuntimeName(this, buffer);
42924273
}
42934274

4294-
GenericParamList *ProtocolDecl::createGenericParams(DeclContext *dc) {
4295-
auto *outerGenericParams = getParent()->getGenericParamsOfContext();
4275+
void ProtocolDecl::createGenericParamsIfMissing() {
4276+
if (getGenericParams())
4277+
return;
42964278

42974279
// The generic parameter 'Self'.
42984280
auto &ctx = getASTContext();
42994281
auto selfId = ctx.Id_Self;
43004282
auto selfDecl = new (ctx) GenericTypeParamDecl(
4301-
dc, selfId,
4283+
this, selfId,
43024284
SourceLoc(),
4303-
GenericTypeParamDecl::InvalidDepth, /*index=*/0);
4285+
/*depth=*/getGenericContextDepth() + 1, /*index=*/0);
43044286
auto protoType = getDeclaredType();
43054287
TypeLoc selfInherited[1] = { TypeLoc::withoutLoc(protoType) };
43064288
selfDecl->setInherited(ctx.AllocateCopy(selfInherited));
@@ -4309,13 +4291,7 @@ GenericParamList *ProtocolDecl::createGenericParams(DeclContext *dc) {
43094291
// The generic parameter list itself.
43104292
auto result = GenericParamList::create(ctx, SourceLoc(), selfDecl,
43114293
SourceLoc());
4312-
result->setOuterParameters(outerGenericParams);
4313-
return result;
4314-
}
4315-
4316-
void ProtocolDecl::createGenericParamsIfMissing() {
4317-
if (!getGenericParams())
4318-
setGenericParams(createGenericParams(this));
4294+
setGenericParams(result);
43194295
}
43204296

43214297
void ProtocolDecl::computeRequirementSignature() {

lib/AST/DeclContext.cpp

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,20 +123,33 @@ Type DeclContext::getDeclaredInterfaceType() const {
123123
return Type();
124124
}
125125

126-
GenericParamList *DeclContext::getGenericParamsOfContext() const {
126+
void DeclContext::forEachGenericContext(
127+
llvm::function_ref<void (GenericParamList *)> fn) const {
127128
auto dc = this;
128129
do {
129130
if (auto decl = dc->getAsDecl()) {
130-
if (auto GC = decl->getAsGenericContext()) {
131-
auto GP = GC->getGenericParams();
132-
// Extensions do not capture outer generic parameters.
133-
if (GP != nullptr || isa<ExtensionDecl>(decl))
134-
return GP;
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;
135140
}
141+
142+
if (auto genericCtx = decl->getAsGenericContext())
143+
if (auto *gpList = genericCtx->getGenericParams())
144+
fn(gpList);
136145
}
137146
} while ((dc = dc->getParent()));
147+
}
138148

139-
return nullptr;
149+
unsigned DeclContext::getGenericContextDepth() const {
150+
unsigned depth = -1;
151+
forEachGenericContext([&](GenericParamList *) { ++depth; });
152+
return depth;
140153
}
141154

142155
GenericSignature *DeclContext::getGenericSignatureOfContext() const {
@@ -275,7 +288,21 @@ DeclContext *DeclContext::getModuleScopeContext() const {
275288

276289
/// Determine whether the given context is generic at any level.
277290
bool DeclContext::isGenericContext() const {
278-
return getGenericParamsOfContext() != nullptr;
291+
auto dc = this;
292+
do {
293+
if (auto decl = dc->getAsDecl()) {
294+
if (auto GC = decl->getAsGenericContext()) {
295+
if (GC->getGenericParams())
296+
return true;
297+
298+
// Extensions do not capture outer generic parameters.
299+
if (isa<ExtensionDecl>(decl))
300+
break;
301+
}
302+
}
303+
} while ((dc = dc->getParent()));
304+
305+
return false;
279306
}
280307

281308
/// Get the most optimal resilience expansion for the body of this function.

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7490,29 +7490,14 @@ GenericSignature *GenericSignatureBuilder::computeGenericSignature(
74907490
return sig;
74917491
}
74927492

7493-
/// Add all of the generic parameters from the given parameter list (and it's
7494-
/// outer generic parameter lists) to the given generic signature builder.
7495-
static void addAllGenericParams(GenericSignatureBuilder &builder,
7496-
GenericParamList *genericParams) {
7497-
if (!genericParams) return;
7498-
7499-
addAllGenericParams(builder, genericParams->getOuterParameters());
7500-
for (auto gp : *genericParams)
7501-
builder.addGenericParameter(gp);
7502-
}
7503-
75047493
GenericSignature *GenericSignatureBuilder::computeRequirementSignature(
75057494
ProtocolDecl *proto) {
75067495
GenericSignatureBuilder builder(proto->getASTContext());
75077496

7508-
if (!proto->hasInterfaceType()) {
7509-
// FIXME: Overkill.
7510-
if (auto lazyResolver = proto->getASTContext().getLazyResolver())
7511-
lazyResolver->resolveDeclSignature(proto);
7512-
}
7513-
75147497
// Add all of the generic parameters.
7515-
addAllGenericParams(builder, proto->getGenericParams());
7498+
proto->createGenericParamsIfMissing();
7499+
for (auto gp : *proto->getGenericParams())
7500+
builder.addGenericParameter(gp);
75167501

75177502
// Add the conformance of 'self' to the protocol.
75187503
auto selfType =

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/ClangImporter/ImportDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8053,7 +8053,7 @@ ClangImporter::Implementation::importDeclContextOf(
80538053
ext->setMemberLoader(this, reinterpret_cast<uintptr_t>(declSubmodule));
80548054

80558055
if (auto protoDecl = ext->getExtendedProtocolDecl()) {
8056-
ext->setGenericParams(protoDecl->createGenericParams(ext));
8056+
ext->createGenericParamsIfMissing(protoDecl);
80578057

80588058
auto *env = buildGenericEnvironment(ext->getGenericParams(), ext);
80598059
ext->setGenericEnvironment(env);

0 commit comments

Comments
 (0)