@@ -112,7 +112,7 @@ Solution::computeSubstitutions(GenericSignature sig,
112112// On Windows and 32-bit platforms we need to force "Int" to actually be
113113// re-imported as "Int." This is needed because otherwise, we cannot round-trip
114114// "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."
116116static ValueDecl *rewriteIntegerTypes (SubstitutionMap subst, ValueDecl *oldDecl,
117117 AbstractFunctionDecl *newDecl) {
118118 auto originalFnSubst = cast<AbstractFunctionDecl>(oldDecl)
@@ -172,116 +172,51 @@ static ValueDecl *rewriteIntegerTypes(SubstitutionMap subst, ValueDecl *oldDecl,
172172 newFnDecl->setSelfAccessKind (func->getSelfAccessKind ());
173173 newFnDecl->setSelfIndex (func->getSelfIndex ());
174174 }
175-
176175 return newFnDecl;
177176 }
178177 }
179178
180179 return newDecl;
181180}
182181
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 ());
212194 }
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 ;
213207
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;
255215 }
216+ auto *newParamList =
217+ ParameterList::create (ctx, SourceLoc (), newParams, SourceLoc ());
256218
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};
285220}
286221
287222// Synthesizes the body of a thunk that takes extra metatype arguments and
@@ -332,55 +267,16 @@ static ValueDecl *generateThunkForExtraMetatypes(SubstitutionMap subst,
332267 // specialization, which are no longer now that we've specialized
333268 // this function. Create a thunk that only forwards the original
334269 // 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);
374272 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 );
380278 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 ());
384280
385281 return thunk;
386282}
@@ -430,10 +326,6 @@ static ConcreteDeclRef getCXXFunctionTemplateSpecialization(SubstitutionMap subs
430326 }
431327 }
432328
433- if (auto fn = dyn_cast<FuncDecl>(decl)) {
434- newDecl = addThunkForDependentTypes (fn, cast<FuncDecl>(newDecl));
435- }
436-
437329 if (auto fn = dyn_cast<FuncDecl>(decl)) {
438330 if (newFn->getNumParams () != fn->getParameters ()->size ()) {
439331 newDecl = generateThunkForExtraMetatypes (subst, fn,
0 commit comments