Skip to content

Commit 70f7812

Browse files
committed
AST: Factor out LocalArchetypeRequirementCollector from SIL
1 parent 865b155 commit 70f7812

File tree

3 files changed

+320
-0
lines changed

3 files changed

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

0 commit comments

Comments
 (0)