Skip to content

Commit 8c8d78c

Browse files
committed
AST: Factor out LocalArchetypeRequirementCollector from SIL
1 parent 3b2a6d8 commit 8c8d78c

File tree

3 files changed

+304
-0
lines changed

3 files changed

+304
-0
lines changed
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 genericSigWithCaptures;
47+
ArrayRef<GenericEnvironment *> capturedEnvs;
48+
49+
MapLocalArchetypesOutOfContext(GenericSignature genericSigWithCaptures,
50+
ArrayRef<GenericEnvironment *> capturedEnvs)
51+
: genericSigWithCaptures(genericSigWithCaptures), 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/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
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
//===--- LocalArchetypeRequirementCollector.cpp ---------------------------===//1
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 implements the LocalArchetypeRequirementCollector class.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "swift/AST/LocalArchetypeRequirementCollector.h"
18+
#include "swift/AST/ASTContext.h"
19+
#include "swift/AST/GenericEnvironment.h"
20+
#include "swift/AST/GenericSignature.h"
21+
#include "swift/AST/Requirement.h"
22+
#include "swift/AST/Types.h"
23+
24+
using namespace swift;
25+
26+
LocalArchetypeRequirementCollector::LocalArchetypeRequirementCollector(
27+
const ASTContext &ctx, GenericSignature sig)
28+
: Context(ctx), OuterSig(sig), Depth(sig.getNextDepth()) {}
29+
30+
void LocalArchetypeRequirementCollector::addOpenedExistential(Type constraint) {
31+
assert(constraint->isConstraintType() ||
32+
constraint->getClassOrBoundGenericClass());
33+
assert(OuterSig || !constraint->hasTypeParameter() &&
34+
"Interface type here requires a parent signature");
35+
36+
auto param = addParameter();
37+
38+
Requirements.emplace_back(RequirementKind::Conformance, param, constraint);
39+
40+
++Depth;
41+
}
42+
43+
void LocalArchetypeRequirementCollector::addOpenedElement(
44+
CanGenericTypeParamType shapeClass) {
45+
46+
size_t startingIndex = Params.size();
47+
48+
/// Add a parameter for each of the opened elements in this shape class.
49+
SmallVector<GenericTypeParamType *, 2> packParams;
50+
for (auto paramType : OuterSig.getGenericParams()) {
51+
if (paramType->isParameterPack() &&
52+
OuterSig->haveSameShape(paramType, shapeClass)) {
53+
packParams.push_back(paramType);
54+
addParameter();
55+
}
56+
}
57+
58+
assert(!packParams.empty());
59+
60+
// Clone the element requirements.
61+
62+
// Helper function: replace references to type parameter packs
63+
// with one of the opened element type parameters we just created for this
64+
// shape class.
65+
auto rewriteElementType = [=](Type type) {
66+
return type.transformTypeParameterPacks(
67+
[&](SubstitutableType *t) -> std::optional<Type> {
68+
auto *paramType = cast<GenericTypeParamType>(t);
69+
for (unsigned packElementIndex : indices(packParams)) {
70+
if (paramType == packParams[packElementIndex])
71+
return Params[startingIndex + packElementIndex];
72+
}
73+
74+
return std::nullopt;
75+
});
76+
};
77+
78+
// Clone the pack requirements that apply to this shape class.
79+
for (auto req : OuterSig.getRequirements()) {
80+
switch (req.getKind()) {
81+
case RequirementKind::SameShape:
82+
// These never involve element types.
83+
break;
84+
case RequirementKind::Conformance:
85+
case RequirementKind::Superclass:
86+
case RequirementKind::SameType: {
87+
auto substFirstType = rewriteElementType(req.getFirstType());
88+
auto substSecondType = rewriteElementType(req.getSecondType());
89+
if (!substFirstType->isEqual(req.getFirstType()) ||
90+
!substSecondType->isEqual(req.getSecondType())) {
91+
Requirements.emplace_back(req.getKind(), substFirstType, substSecondType);
92+
}
93+
break;
94+
}
95+
case RequirementKind::Layout: {
96+
auto substFirstType = rewriteElementType(req.getFirstType());
97+
if (!substFirstType->isEqual(req.getFirstType())) {
98+
Requirements.emplace_back(req.getKind(), substFirstType,
99+
req.getLayoutConstraint());
100+
}
101+
break;
102+
}
103+
}
104+
}
105+
106+
++Depth;
107+
}
108+
109+
GenericTypeParamType *LocalArchetypeRequirementCollector::addParameter() {
110+
unsigned index = 0;
111+
if (!Params.empty() &&
112+
Params.back()->getDepth() == Depth) {
113+
index = Params.back()->getIndex() + 1;
114+
}
115+
116+
auto *param = GenericTypeParamType::get(/*pack*/ false, Depth,
117+
index, Context);
118+
Params.push_back(param);
119+
return param;
120+
}
121+
122+
GenericSignature swift::buildGenericSignatureWithCapturedEnvironments(
123+
ASTContext &ctx,
124+
GenericSignature sig,
125+
ArrayRef<GenericEnvironment *> capturedEnvs) {
126+
// Add new generic parameters to replace the local archetypes.
127+
LocalArchetypeRequirementCollector collector(ctx, sig);
128+
129+
for (auto *genericEnv : capturedEnvs) {
130+
switch (genericEnv->getKind()) {
131+
case GenericEnvironment::Kind::Primary:
132+
case GenericEnvironment::Kind::Opaque:
133+
break;
134+
135+
case GenericEnvironment::Kind::OpenedExistential: {
136+
auto constraint = genericEnv->getOpenedExistentialType();
137+
if (auto existential = constraint->getAs<ExistentialType>())
138+
constraint = existential->getConstraintType();
139+
collector.addOpenedExistential(constraint);
140+
continue;
141+
}
142+
case GenericEnvironment::Kind::OpenedElement: {
143+
collector.addOpenedElement(
144+
genericEnv->getOpenedElementShapeClass());
145+
continue;
146+
}
147+
}
148+
149+
llvm_unreachable("Cannot happen");
150+
}
151+
152+
return buildGenericSignature(ctx,
153+
collector.OuterSig,
154+
collector.Params,
155+
collector.Requirements,
156+
/*allowInverses=*/false);
157+
}
158+
159+
Type MapLocalArchetypesOutOfContext::operator()(SubstitutableType *type) const {
160+
auto *archetypeTy = cast<ArchetypeType>(type);
161+
162+
// Primary archetypes just map out of context.
163+
if (isa<PrimaryArchetypeType>(archetypeTy) ||
164+
isa<PackArchetypeType>(archetypeTy)) {
165+
return archetypeTy->getInterfaceType();
166+
}
167+
168+
assert(isa<LocalArchetypeType>(archetypeTy));
169+
170+
// Handle dependent member types recursively in the usual way.
171+
if (!archetypeTy->isRoot())
172+
return Type();
173+
174+
// Root local archetypes change depth.
175+
auto *genericEnv = archetypeTy->getGenericEnvironment();
176+
auto rootParam = archetypeTy->getInterfaceType()
177+
->castTo<GenericTypeParamType>();
178+
assert(!rootParam->isParameterPack());
179+
assert(rootParam->getDepth() == genericEnv->getGenericSignature()->getMaxDepth());
180+
181+
// The new depth is determined by counting how many captured environments
182+
// precede this one.
183+
unsigned depth = genericSigWithCaptures->getMaxDepth();
184+
for (auto *capturedEnv : llvm::reverse(capturedEnvs)) {
185+
if (capturedEnv == genericEnv) {
186+
return GenericTypeParamType::get(/*isParameterPack=*/false,
187+
depth, rootParam->getIndex(),
188+
rootParam->getASTContext());
189+
}
190+
191+
--depth;
192+
}
193+
194+
llvm_unreachable("Fell off the end");
195+
}
196+
197+
/// Given a substitution map for a call to a local function or closure, extend
198+
/// it to include all captured element archetypes; they become primary archetypes
199+
/// inside the body of the function.
200+
SubstitutionMap
201+
swift::buildSubstitutionMapWithCapturedEnvironments(
202+
SubstitutionMap baseSubMap,
203+
GenericSignature genericSigWithCaptures,
204+
ArrayRef<GenericEnvironment *> capturedEnvs) {
205+
206+
if (capturedEnvs.empty()) {
207+
assert((!baseSubMap && !genericSigWithCaptures) ||
208+
baseSubMap.getGenericSignature()->isEqual(genericSigWithCaptures));
209+
return baseSubMap;
210+
}
211+
212+
unsigned baseDepth = genericSigWithCaptures.getNextDepth() - capturedEnvs.size();
213+
214+
return SubstitutionMap::get(
215+
genericSigWithCaptures,
216+
[&](SubstitutableType *type) -> Type {
217+
auto param = cast<GenericTypeParamType>(type);
218+
if (param->getDepth() >= baseDepth) {
219+
assert(!param->isParameterPack());
220+
unsigned envIndex = param->getDepth() - baseDepth;
221+
assert(envIndex < capturedEnvs.size());
222+
auto *capturedEnv = capturedEnvs[envIndex];
223+
auto localInterfaceType = capturedEnv->getGenericSignature()
224+
.getInnermostGenericParams()[param->getIndex()];
225+
return capturedEnvs[envIndex]->mapTypeIntoContext(localInterfaceType);
226+
}
227+
return Type(type).subst(baseSubMap);
228+
},
229+
[&](CanType origType, Type substType,
230+
ProtocolDecl *proto) -> ProtocolConformanceRef {
231+
if (origType->getRootGenericParam()->getDepth() >= baseDepth)
232+
return ProtocolConformanceRef(proto);
233+
return baseSubMap.lookupConformance(origType, proto);
234+
});
235+
}

0 commit comments

Comments
 (0)