Skip to content

Commit fda9368

Browse files
authored
Merge pull request #73363 from slavapestov/pack-expansion-closures-part-2
Extract common code for building opened existential and element signatures
2 parents 5cbf815 + 9e13db0 commit fda9368

19 files changed

+392
-334
lines changed

include/swift/AST/GenericSignature.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ class GenericSignature {
197197
/// array of the generic parameters for the innermost generic type.
198198
ArrayRef<GenericTypeParamType *> getInnermostGenericParams() const;
199199

200+
/// Returns the depth that a generic parameter at the next level of
201+
/// nesting would have. This is zero for the empty signature,
202+
/// and one plus the depth of the final generic parameter otherwise.
203+
unsigned getNextDepth() const;
204+
200205
/// Retrieve the requirements.
201206
ArrayRef<Requirement> getRequirements() const;
202207

@@ -307,6 +312,9 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final
307312
return Mem;
308313
}
309314

315+
/// Returns the depth of the last generic parameter.
316+
unsigned getMaxDepth() const;
317+
310318
/// Transform the requirements into a form where implicit Copyable and
311319
/// Escapable conformances are omitted, and their absence is explicitly
312320
/// noted.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//===--- LocalArchetypeRequirementCollector.h -------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file has utility code for extending a generic signature with opened
14+
// existentials and shape classes.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef SWIFT_AST_LOCAL_ARCHETYPE_REQUIREMENT_COLLECTOR_H
19+
#define SWIFT_AST_LOCAL_ARCHETYPE_REQUIREMENT_COLLECTOR_H
20+
21+
#include "swift/AST/ASTContext.h"
22+
#include "swift/AST/GenericSignature.h"
23+
#include "swift/AST/Requirement.h"
24+
#include "swift/AST/Types.h"
25+
26+
namespace swift {
27+
28+
struct LocalArchetypeRequirementCollector {
29+
const ASTContext &Context;
30+
GenericSignature OuterSig;
31+
unsigned Depth;
32+
33+
/// The lists of new parameters and requirements to add to the signature.
34+
SmallVector<GenericTypeParamType *, 2> Params;
35+
SmallVector<Requirement, 2> Requirements;
36+
37+
LocalArchetypeRequirementCollector(const ASTContext &ctx, GenericSignature sig);
38+
39+
void addOpenedExistential(Type constraint);
40+
void addOpenedElement(CanGenericTypeParamType shapeClass);
41+
42+
GenericTypeParamType *addParameter();
43+
};
44+
45+
struct MapLocalArchetypesOutOfContext {
46+
GenericSignature baseGenericSig;
47+
ArrayRef<GenericEnvironment *> capturedEnvs;
48+
49+
MapLocalArchetypesOutOfContext(GenericSignature baseGenericSig,
50+
ArrayRef<GenericEnvironment *> capturedEnvs)
51+
: baseGenericSig(baseGenericSig), capturedEnvs(capturedEnvs) {}
52+
53+
Type operator()(SubstitutableType *type) const;
54+
};
55+
56+
GenericSignature buildGenericSignatureWithCapturedEnvironments(
57+
ASTContext &ctx,
58+
GenericSignature sig,
59+
ArrayRef<GenericEnvironment *> capturedEnvs);
60+
61+
SubstitutionMap buildSubstitutionMapWithCapturedEnvironments(
62+
SubstitutionMap baseSubMap,
63+
GenericSignature genericSigWithCaptures,
64+
ArrayRef<GenericEnvironment *> capturedEnvs);
65+
66+
}
67+
68+
#endif // SWIFT_AST_LOCAL_ARCHETYPE_REQUIREMENT_COLLECTOR_H

lib/AST/ASTContext.cpp

Lines changed: 12 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "swift/AST/IndexSubset.h"
3737
#include "swift/AST/KnownProtocols.h"
3838
#include "swift/AST/LazyResolver.h"
39+
#include "swift/AST/LocalArchetypeRequirementCollector.h"
3940
#include "swift/AST/MacroDiscriminatorContext.h"
4041
#include "swift/AST/ModuleDependencies.h"
4142
#include "swift/AST/ModuleLoader.h"
@@ -5884,11 +5885,8 @@ CanGenericSignature ASTContext::getSingleGenericParameterSignature() const {
58845885

58855886
Type OpenedArchetypeType::getSelfInterfaceTypeFromContext(GenericSignature parentSig,
58865887
ASTContext &ctx) {
5887-
unsigned depth = 0;
5888-
if (!parentSig.getGenericParams().empty())
5889-
depth = parentSig.getGenericParams().back()->getDepth() + 1;
58905888
return GenericTypeParamType::get(/*isParameterPack=*/ false,
5891-
/*depth=*/ depth, /*index=*/ 0,
5889+
parentSig.getNextDepth(), /*index=*/ 0,
58925890
ctx);
58935891
}
58945892

@@ -5900,33 +5898,25 @@ ASTContext::getOpenedExistentialSignature(Type type, GenericSignature parentSig)
59005898
type = existential->getConstraintType();
59015899

59025900
const CanType constraint = type->getCanonicalType();
5903-
assert(parentSig || !constraint->hasTypeParameter() &&
5904-
"Interface type here requires a parent signature");
59055901

59065902
auto canParentSig = parentSig.getCanonicalSignature();
59075903
auto key = std::make_pair(constraint, canParentSig.getPointer());
59085904
auto found = getImpl().ExistentialSignatures.find(key);
59095905
if (found != getImpl().ExistentialSignatures.end())
59105906
return found->second;
59115907

5912-
auto genericParam = OpenedArchetypeType::getSelfInterfaceTypeFromContext(
5913-
canParentSig, *this)
5914-
->castTo<GenericTypeParamType>();
5915-
Requirement requirement(RequirementKind::Conformance, genericParam,
5916-
constraint);
5908+
LocalArchetypeRequirementCollector collector(*this, canParentSig);
5909+
collector.addOpenedExistential(type);
59175910
auto genericSig = buildGenericSignature(
5918-
*this, canParentSig,
5919-
{genericParam}, {requirement},
5920-
/*allowInverses=*/true);
5921-
5922-
CanGenericSignature canGenericSig(genericSig);
5911+
*this, collector.OuterSig, collector.Params, collector.Requirements,
5912+
/*allowInverses=*/true).getCanonicalSignature();
59235913

59245914
auto result = getImpl().ExistentialSignatures.insert(
5925-
std::make_pair(key, canGenericSig));
5915+
std::make_pair(key, genericSig));
59265916
assert(result.second);
59275917
(void) result;
59285918

5929-
return canGenericSig;
5919+
return genericSig;
59305920
}
59315921

59325922
CanGenericSignature
@@ -5938,100 +5928,12 @@ ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig,
59385928
if (found != sigs.end())
59395929
return found->second;
59405930

5941-
// This operation doesn't make sense if the input signature does not contain`
5942-
// any pack generic parameters.
5943-
#ifndef NDEBUG
5944-
{
5945-
auto found = std::find_if(baseGenericSig.getGenericParams().begin(),
5946-
baseGenericSig.getGenericParams().end(),
5947-
[](GenericTypeParamType *paramType) {
5948-
return paramType->isParameterPack();
5949-
});
5950-
assert(found != baseGenericSig.getGenericParams().end());
5951-
}
5952-
#endif
5953-
5954-
// The pack element signature includes all type parameters and requirements
5955-
// from the outer context, plus a new set of type parameters representing
5956-
// open pack elements and their corresponding element requirements.
5957-
5958-
llvm::SmallMapVector<GenericTypeParamType *,
5959-
GenericTypeParamType *, 2> packElementParams;
5960-
SmallVector<GenericTypeParamType *, 2> genericParams(
5961-
baseGenericSig.getGenericParams().begin(), baseGenericSig.getGenericParams().end());
5962-
SmallVector<Requirement, 2> requirements;
5963-
5964-
auto packElementDepth =
5965-
baseGenericSig.getInnermostGenericParams().front()->getDepth() + 1;
5966-
5967-
for (auto paramType : baseGenericSig.getGenericParams()) {
5968-
if (!paramType->isParameterPack())
5969-
continue;
5970-
5971-
// Only include opened element parameters for packs in the given
5972-
// shape equivalence class.
5973-
if (!baseGenericSig->haveSameShape(paramType, shapeClass))
5974-
continue;
5975-
5976-
auto *elementParam = GenericTypeParamType::get(/*isParameterPack*/false,
5977-
packElementDepth,
5978-
packElementParams.size(),
5979-
*this);
5980-
genericParams.push_back(elementParam);
5981-
packElementParams[paramType] = elementParam;
5982-
}
5983-
5984-
auto eraseParameterPackRec = [&](Type type) -> Type {
5985-
return type.transformTypeParameterPacks(
5986-
[&](SubstitutableType *t) -> std::optional<Type> {
5987-
if (auto *paramType = dyn_cast<GenericTypeParamType>(t)) {
5988-
if (packElementParams.find(paramType) != packElementParams.end()) {
5989-
return Type(packElementParams[paramType]);
5990-
}
5991-
5992-
return Type(t);
5993-
}
5994-
return std::nullopt;
5995-
});
5996-
};
5997-
5998-
for (auto requirement : baseGenericSig.getRequirements()) {
5999-
requirements.push_back(requirement);
6000-
6001-
// If this requirement contains parameter packs, create a new requirement
6002-
// for the corresponding pack element.
6003-
switch (requirement.getKind()) {
6004-
case RequirementKind::SameShape:
6005-
// Drop same-shape requirements from the element signature.
6006-
break;
6007-
case RequirementKind::Conformance:
6008-
case RequirementKind::Superclass:
6009-
case RequirementKind::SameType: {
6010-
auto firstType = eraseParameterPackRec(requirement.getFirstType());
6011-
auto secondType = eraseParameterPackRec(requirement.getSecondType());
6012-
if (firstType->isEqual(requirement.getFirstType()) &&
6013-
secondType->isEqual(requirement.getSecondType()))
6014-
break;
6015-
6016-
requirements.emplace_back(requirement.getKind(),
6017-
firstType, secondType);
6018-
break;
6019-
}
6020-
case RequirementKind::Layout: {
6021-
auto firstType = eraseParameterPackRec(requirement.getFirstType());
6022-
if (firstType->isEqual(requirement.getFirstType()))
6023-
break;
6024-
6025-
requirements.emplace_back(requirement.getKind(), firstType,
6026-
requirement.getLayoutConstraint());
6027-
break;
6028-
}
6029-
}
6030-
}
6031-
5931+
LocalArchetypeRequirementCollector collector(*this, baseGenericSig);
5932+
collector.addOpenedElement(shapeClass);
60325933
auto elementSig = buildGenericSignature(
6033-
*this, GenericSignature(), genericParams, requirements,
5934+
*this, collector.OuterSig, collector.Params, collector.Requirements,
60345935
/*allowInverses=*/false).getCanonicalSignature();
5936+
60355937
sigs[key] = elementSig;
60365938
return elementSig;
60375939
}

lib/AST/ASTMangler.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2748,7 +2748,7 @@ void ASTMangler::appendContextualInverses(const GenericTypeDecl *contextDecl,
27482748
parts.params = std::nullopt;
27492749

27502750
// The depth of parameters for this extension is +1 of the extended signature.
2751-
parts.initialParamDepth = sig.getGenericParams().back()->getDepth() + 1;
2751+
parts.initialParamDepth = sig.getNextDepth();
27522752

27532753
appendModule(module, alternateModuleName);
27542754
appendGenericSignatureParts(sig, parts);
@@ -3391,7 +3391,7 @@ void ASTMangler::gatherGenericSignatureParts(GenericSignature sig,
33913391
} else {
33923392
inverseReqs.clear();
33933393
}
3394-
base.setDepth(canSig.getGenericParams().back()->getDepth());
3394+
base.setDepth(canSig->getMaxDepth());
33953395

33963396
unsigned &initialParamDepth = parts.initialParamDepth;
33973397
auto &genericParams = parts.params;
@@ -3412,7 +3412,7 @@ void ASTMangler::gatherGenericSignatureParts(GenericSignature sig,
34123412

34133413
// The signature depth starts above the depth of the context signature.
34143414
if (!contextSig.getGenericParams().empty()) {
3415-
initialParamDepth = contextSig.getGenericParams().back()->getDepth() + 1;
3415+
initialParamDepth = contextSig.getNextDepth();
34163416
}
34173417

34183418
// If both signatures have exactly the same requirements, ignoring
@@ -4760,11 +4760,10 @@ static std::optional<unsigned> getEnclosingTypeGenericDepth(const Decl *decl) {
47604760
if (!typeDecl)
47614761
return std::nullopt;
47624762

4763-
auto genericParams = typeDecl->getGenericParams();
4764-
if (!genericParams)
4763+
if (!typeDecl->isGeneric())
47654764
return std::nullopt;
47664765

4767-
return genericParams->getParams().back()->getDepth();
4766+
return typeDecl->getGenericSignature()->getMaxDepth();
47684767
}
47694768

47704769
ASTMangler::BaseEntitySignature::BaseEntitySignature(const Decl *decl)

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,10 +1807,7 @@ void PrintAST::printSingleDepthOfGenericSignature(
18071807
auto *DC = Current->getInnermostDeclContext()->getInnermostTypeContext();
18081808
M = DC->getParentModule();
18091809
subMap = CurrentType->getContextSubstitutionMap(M, DC);
1810-
if (!subMap.empty()) {
1811-
typeContextDepth = subMap.getGenericSignature()
1812-
.getGenericParams().back()->getDepth() + 1;
1813-
}
1810+
typeContextDepth = subMap.getGenericSignature().getNextDepth();
18141811
}
18151812
}
18161813

@@ -7080,7 +7077,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
70807077

70817078
// The element archetypes are at a depth one past the max depth
70827079
// of the base signature.
7083-
unsigned elementDepth = params.back()->getDepth() + 1;
7080+
unsigned elementDepth = sig.getNextDepth();
70847081

70857082
// Transform the archetype's interface type to be based on the
70867083
// corresponding non-canonical type parameter.

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ add_swift_host_library(swiftAST STATIC
6262
InlinableText.cpp
6363
LayoutConstraint.cpp
6464
LifetimeDependence.cpp
65+
LocalArchetypeRequirementCollector.cpp
6566
Module.cpp
6667
ModuleDependencies.cpp
6768
ModuleLoader.cpp

lib/AST/GenericSignature.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ ArrayRef<GenericTypeParamType *>
7979
GenericSignatureImpl::getInnermostGenericParams() const {
8080
const auto params = getGenericParams();
8181

82-
const unsigned maxDepth = params.back()->getDepth();
82+
const unsigned maxDepth = getMaxDepth();
8383
if (params.front()->getDepth() == maxDepth)
8484
return params;
8585

@@ -95,6 +95,16 @@ GenericSignatureImpl::getInnermostGenericParams() const {
9595
return params.slice(sliceCount);
9696
}
9797

98+
unsigned GenericSignatureImpl::getMaxDepth() const {
99+
return getGenericParams().back()->getDepth();
100+
}
101+
102+
unsigned GenericSignature::getNextDepth() const {
103+
if (!getPointer())
104+
return 0;
105+
return getPointer()->getMaxDepth() + 1;
106+
}
107+
98108
void GenericSignatureImpl::forEachParam(
99109
llvm::function_ref<void(GenericTypeParamType *, bool)> callback) const {
100110
// Figure out which generic parameters are concrete or same-typed to another

0 commit comments

Comments
 (0)