@@ -112,7 +112,7 @@ Solution::computeSubstitutions(GenericSignature sig,
112
112
// On Windows and 32-bit platforms we need to force "Int" to actually be
113
113
// re-imported as "Int." This is needed because otherwise, we cannot round-trip
114
114
// "Int" and "UInt". For example, on Windows, "Int" will be imported into C++ as
115
- // "long long" and then back into Swift as "Int64" not "Int."
115
+ // "long long" and then back into Swift as "Int64" not "Int."
116
116
static ValueDecl *rewriteIntegerTypes (SubstitutionMap subst, ValueDecl *oldDecl,
117
117
AbstractFunctionDecl *newDecl) {
118
118
auto originalFnSubst = cast<AbstractFunctionDecl>(oldDecl)
@@ -172,116 +172,51 @@ static ValueDecl *rewriteIntegerTypes(SubstitutionMap subst, ValueDecl *oldDecl,
172
172
newFnDecl->setSelfAccessKind (func->getSelfAccessKind ());
173
173
newFnDecl->setSelfIndex (func->getSelfIndex ());
174
174
}
175
-
176
175
return newFnDecl;
177
176
}
178
177
}
179
178
180
179
return newDecl;
181
180
}
182
181
183
- // Synthesize a thunk body for the function created in
184
- // "addThunkForDependentTypes". This will just cast all params and forward them
185
- // along to the specialized function. It will also cast the result before
186
- // returning it.
187
- static std::pair<BraceStmt *, bool >
188
- synthesizeDependentTypeThunkParamForwarding (AbstractFunctionDecl *afd, void *context) {
189
- ASTContext &ctx = afd->getASTContext ();
190
-
191
- auto thunkDecl = cast<FuncDecl>(afd);
192
- auto specializedFuncDecl = static_cast <FuncDecl *>(context);
193
-
194
- SmallVector<Argument, 8 > forwardingParams;
195
- unsigned paramIndex = 0 ;
196
- for (auto param : *thunkDecl->getParameters ()) {
197
- if (isa<MetatypeType>(param->getType ().getPointer ())) {
198
- paramIndex++;
199
- continue ;
200
- }
201
-
202
- auto paramRefExpr = new (ctx) DeclRefExpr (param, DeclNameLoc (),
203
- /* Implicit=*/ true );
204
- paramRefExpr->setType (param->getType ());
205
-
206
- auto specParamTy = specializedFuncDecl->getParameters ()->get (paramIndex)->getType ();
207
- auto cast = ForcedCheckedCastExpr::createImplicit (
208
- ctx, paramRefExpr, specParamTy);
209
-
210
- forwardingParams.push_back (Argument (SourceLoc (), Identifier (), cast));
211
- paramIndex++;
182
+ // Derive a concrete function type for fdecl by substituting the generic args
183
+ // and use that to derive the corresponding function type and parameter list.
184
+ static std::pair<FunctionType *, ParameterList *>
185
+ substituteFunctionTypeAndParamList (ASTContext &ctx, AbstractFunctionDecl *fdecl,
186
+ SubstitutionMap subst) {
187
+ FunctionType *newFnType = nullptr ;
188
+ // Create a new ParameterList with the substituted type.
189
+ if (auto oldFnType = dyn_cast<GenericFunctionType>(
190
+ fdecl->getInterfaceType ().getPointer ())) {
191
+ newFnType = oldFnType->substGenericArgs (subst);
192
+ } else {
193
+ newFnType = cast<FunctionType>(fdecl->getInterfaceType ().getPointer ());
212
194
}
195
+ // The constructor type is a function type as follows:
196
+ // (CType.Type) -> (Generic) -> CType
197
+ // And a method's function type is as follows:
198
+ // (inout CType) -> (Generic) -> Void
199
+ // In either case, we only want the result of that function type because that
200
+ // is the function type with the generic params that need to be substituted:
201
+ // (Generic) -> CType
202
+ if (isa<ConstructorDecl>(fdecl) || fdecl->isInstanceMember () ||
203
+ fdecl->isStatic ())
204
+ newFnType = cast<FunctionType>(newFnType->getResult ().getPointer ());
205
+ SmallVector<ParamDecl *, 4 > newParams;
206
+ unsigned i = 0 ;
213
207
214
- auto *specializedFuncDeclRef = new (ctx) DeclRefExpr (ConcreteDeclRef (specializedFuncDecl),
215
- DeclNameLoc (), true );
216
- specializedFuncDeclRef->setType (specializedFuncDecl->getInterfaceType ());
217
-
218
- auto argList = ArgumentList::createImplicit (ctx, forwardingParams);
219
- auto *specializedFuncCallExpr = CallExpr::createImplicit (ctx, specializedFuncDeclRef, argList);
220
- specializedFuncCallExpr->setType (specializedFuncDecl->getResultInterfaceType ());
221
- specializedFuncCallExpr->setThrows (false );
222
-
223
- auto cast = ForcedCheckedCastExpr::createImplicit (
224
- ctx, specializedFuncCallExpr, thunkDecl->getResultInterfaceType ());
225
-
226
- auto returnStmt = new (ctx) ReturnStmt (SourceLoc (), cast, /* implicit=*/ true );
227
- auto body = BraceStmt::create (ctx, SourceLoc (), {returnStmt}, SourceLoc (),
228
- /* implicit=*/ true );
229
- return {body, /* isTypeChecked=*/ true };
230
- }
231
-
232
- // Create a thunk to map functions with dependent types to their specialized
233
- // version. For example, create a thunk with type (Any) -> Any to wrap a
234
- // specialized function template with type (Dependent<T>) -> Dependent<T>.
235
- static ValueDecl *addThunkForDependentTypes (FuncDecl *oldDecl,
236
- FuncDecl *newDecl) {
237
- bool updatedAnyParams = false ;
238
-
239
- SmallVector<ParamDecl *, 4 > fixedParameters;
240
- unsigned parameterIndex = 0 ;
241
- for (auto *newFnParam : *newDecl->getParameters ()) {
242
- // If the un-specialized function had a parameter with type "Any" preserve
243
- // that parameter. Otherwise, use the new function parameter.
244
- auto oldParamType = oldDecl->getParameters ()->get (parameterIndex)->getType ();
245
- if (oldParamType->isEqual (newDecl->getASTContext ().TheAnyType )) {
246
- updatedAnyParams = true ;
247
- auto newParam =
248
- ParamDecl::cloneWithoutType (newDecl->getASTContext (), newFnParam);
249
- newParam->setInterfaceType (oldParamType);
250
- fixedParameters.push_back (newParam);
251
- } else {
252
- fixedParameters.push_back (newFnParam);
253
- }
254
- parameterIndex++;
208
+ for (auto paramTy : newFnType->getParams ()) {
209
+ auto *oldParamDecl = fdecl->getParameters ()->get (i);
210
+ auto *newParamDecl =
211
+ ParamDecl::cloneWithoutType (fdecl->getASTContext (), oldParamDecl);
212
+ newParamDecl->setInterfaceType (paramTy.getParameterType ());
213
+ newParams.push_back (newParamDecl);
214
+ (void )++i;
255
215
}
216
+ auto *newParamList =
217
+ ParameterList::create (ctx, SourceLoc (), newParams, SourceLoc ());
256
218
257
- // If we don't need this thunk, bail out.
258
- if (!updatedAnyParams &&
259
- !oldDecl->getResultInterfaceType ()->isEqual (
260
- oldDecl->getASTContext ().TheAnyType ))
261
- return newDecl;
262
-
263
- auto fixedParams =
264
- ParameterList::create (newDecl->getASTContext (), fixedParameters);
265
-
266
- Type fixedResultType;
267
- if (oldDecl->getResultInterfaceType ()->isEqual (
268
- oldDecl->getASTContext ().TheAnyType ))
269
- fixedResultType = oldDecl->getASTContext ().TheAnyType ;
270
- else
271
- fixedResultType = newDecl->getResultInterfaceType ();
272
-
273
- // We have to rebuild the whole function.
274
- auto newFnDecl = FuncDecl::createImplicit (
275
- newDecl->getASTContext (), newDecl->getStaticSpelling (),
276
- newDecl->getName (), newDecl->getNameLoc (), newDecl->hasAsync (),
277
- newDecl->hasThrows (), /* genericParams=*/ nullptr , fixedParams,
278
- fixedResultType, newDecl->getDeclContext ());
279
- newFnDecl->copyFormalAccessFrom (newDecl);
280
- newFnDecl->setBodySynthesizer (synthesizeDependentTypeThunkParamForwarding, newDecl);
281
- newFnDecl->setSelfAccessKind (newDecl->getSelfAccessKind ());
282
- newFnDecl->getAttrs ().add (
283
- new (newDecl->getASTContext ()) TransparentAttr (/* IsImplicit=*/ true ));
284
- return newFnDecl;
219
+ return {newFnType, newParamList};
285
220
}
286
221
287
222
// Synthesizes the body of a thunk that takes extra metatype arguments and
@@ -332,55 +267,16 @@ static ValueDecl *generateThunkForExtraMetatypes(SubstitutionMap subst,
332
267
// specialization, which are no longer now that we've specialized
333
268
// this function. Create a thunk that only forwards the original
334
269
// parameters along to the clang function.
335
- SmallVector<ParamDecl *, 4 > newParams;
336
-
337
- for (auto param : *newDecl->getParameters ()) {
338
- auto *newParamDecl = ParamDecl::clone (newDecl->getASTContext (), param);
339
- newParams.push_back (newParamDecl);
340
- }
341
-
342
- auto originalFnSubst = cast<AbstractFunctionDecl>(oldDecl)
343
- ->getInterfaceType ()
344
- ->getAs <GenericFunctionType>()
345
- ->substGenericArgs (subst);
346
- // The constructor type is a function type as follows:
347
- // (CType.Type) -> (Generic) -> CType
348
- // And a method's function type is as follows:
349
- // (inout CType) -> (Generic) -> Void
350
- // In either case, we only want the result of that function type because that
351
- // is the function type with the generic params that need to be substituted:
352
- // (Generic) -> CType
353
- if (isa<ConstructorDecl>(oldDecl) || oldDecl->isInstanceMember () ||
354
- oldDecl->isStatic ())
355
- originalFnSubst = cast<FunctionType>(originalFnSubst->getResult ().getPointer ());
356
-
357
- for (auto paramTy : originalFnSubst->getParams ()) {
358
- if (!paramTy.getPlainType ()->is <MetatypeType>())
359
- continue ;
360
-
361
- auto dc = newDecl->getDeclContext ();
362
- auto paramVarDecl =
363
- new (newDecl->getASTContext ()) ParamDecl (
364
- SourceLoc (), SourceLoc (), Identifier (), SourceLoc (),
365
- newDecl->getASTContext ().getIdentifier (" _" ), dc);
366
- paramVarDecl->setInterfaceType (paramTy.getPlainType ());
367
- paramVarDecl->setSpecifier (ParamSpecifier::Default);
368
- newParams.push_back (paramVarDecl);
369
- }
370
-
371
- auto *newParamList =
372
- ParameterList::create (newDecl->getASTContext (), SourceLoc (), newParams, SourceLoc ());
373
-
270
+ auto thunkTypeAndParamList = substituteFunctionTypeAndParamList (oldDecl->getASTContext (),
271
+ oldDecl, subst);
374
272
auto thunk = FuncDecl::createImplicit (
375
- newDecl ->getASTContext (), newDecl ->getStaticSpelling (), oldDecl->getName (),
376
- newDecl ->getNameLoc (), newDecl ->hasAsync (), newDecl ->hasThrows (),
377
- /* genericParams=*/ nullptr , newParamList ,
378
- newDecl-> getResultInterfaceType (), newDecl ->getDeclContext ());
379
- thunk->copyFormalAccessFrom (newDecl );
273
+ oldDecl ->getASTContext (), oldDecl ->getStaticSpelling (), oldDecl->getName (),
274
+ oldDecl ->getNameLoc (), oldDecl ->hasAsync (), oldDecl ->hasThrows (),
275
+ /* genericParams=*/ nullptr , thunkTypeAndParamList. second ,
276
+ thunkTypeAndParamList. first -> getResult (), oldDecl ->getDeclContext ());
277
+ thunk->copyFormalAccessFrom (oldDecl );
380
278
thunk->setBodySynthesizer (synthesizeForwardingThunkBody, newDecl);
381
- thunk->setSelfAccessKind (newDecl->getSelfAccessKind ());
382
- thunk->getAttrs ().add (
383
- new (newDecl->getASTContext ()) TransparentAttr (/* IsImplicit=*/ true ));
279
+ thunk->setSelfAccessKind (oldDecl->getSelfAccessKind ());
384
280
385
281
return thunk;
386
282
}
@@ -430,10 +326,6 @@ static ConcreteDeclRef getCXXFunctionTemplateSpecialization(SubstitutionMap subs
430
326
}
431
327
}
432
328
433
- if (auto fn = dyn_cast<FuncDecl>(decl)) {
434
- newDecl = addThunkForDependentTypes (fn, cast<FuncDecl>(newDecl));
435
- }
436
-
437
329
if (auto fn = dyn_cast<FuncDecl>(decl)) {
438
330
if (newFn->getNumParams () != fn->getParameters ()->size ()) {
439
331
newDecl = generateThunkForExtraMetatypes (subst, fn,
0 commit comments