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