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