@@ -1259,6 +1259,103 @@ namespace {
1259
1259
return thunk;
1260
1260
}
1261
1261
1262
+ // / Build a "{ self in { args in self.fn(args) } }" nested curry thunk.
1263
+ // /
1264
+ // / \param memberRef The expression to be called in the inner thunk by
1265
+ // / consecutively applying the captured outer thunk's 'self' parameter and
1266
+ // / the parameters of the inner thunk.
1267
+ // / \param member The underlying function declaration to be called.
1268
+ // / \param outerThunkTy The type of the outer thunk.
1269
+ // / \param memberLocator The locator pinned on the member reference. If the
1270
+ // / function has associated applied property wrappers, the locator is used
1271
+ // / to pull them in.
1272
+ AutoClosureExpr *
1273
+ buildDoubleCurryThunk (DeclRefExpr *memberRef, ValueDecl *member,
1274
+ FunctionType *outerThunkTy,
1275
+ ConstraintLocatorBuilder memberLocator) {
1276
+ auto &ctx = cs.getASTContext ();
1277
+
1278
+ const auto selfThunkParam = outerThunkTy->getParams ().front ();
1279
+ const auto selfThunkParamTy = selfThunkParam.getPlainType ();
1280
+
1281
+ // Build the 'self' param for the outer thunk, "{ self in ... }".
1282
+ auto *const selfParamDecl =
1283
+ new (ctx) ParamDecl (SourceLoc (),
1284
+ /* argument label*/ SourceLoc (), Identifier (),
1285
+ /* parameter name*/ SourceLoc (), ctx.Id_self , dc);
1286
+ selfParamDecl->setInterfaceType (selfThunkParamTy->mapTypeOutOfContext ());
1287
+ selfParamDecl->setSpecifier (
1288
+ ParamDecl::getParameterSpecifierForValueOwnership (
1289
+ selfThunkParam.getValueOwnership ()));
1290
+ selfParamDecl->setImplicit ();
1291
+
1292
+ // Build a reference to the 'self' parameter.
1293
+ Expr *selfParamRef = new (ctx) DeclRefExpr (selfParamDecl, DeclNameLoc (),
1294
+ /* implicit=*/ true );
1295
+ selfParamRef->setType (selfThunkParam.isInOut ()
1296
+ ? LValueType::get (selfThunkParamTy)
1297
+ : selfThunkParamTy);
1298
+ cs.cacheType (selfParamRef);
1299
+
1300
+ if (selfThunkParam.isInOut ()) {
1301
+ selfParamRef =
1302
+ new (ctx) InOutExpr (SourceLoc (), selfParamRef, selfThunkParamTy,
1303
+ /* implicit=*/ true );
1304
+ cs.cacheType (selfParamRef);
1305
+ }
1306
+
1307
+ const auto selfCalleeParam =
1308
+ cs.getType (memberRef)->castTo <FunctionType>()->getParams ().front ();
1309
+ const auto selfCalleeParamTy = selfCalleeParam.getPlainType ();
1310
+
1311
+ // Open the 'self' parameter reference if warranted.
1312
+ Expr *selfOpenedRef = selfParamRef;
1313
+ if (selfCalleeParamTy->hasOpenedExistential ()) {
1314
+ // If we're opening an existential:
1315
+ // - The type of 'ref' inside the thunk is written in terms of the
1316
+ // open existental archetype.
1317
+ // - The type of the thunk is written in terms of the
1318
+ // erased existential bounds.
1319
+ auto opaqueValueTy = selfCalleeParamTy;
1320
+ if (selfCalleeParam.isInOut ())
1321
+ opaqueValueTy = LValueType::get (opaqueValueTy);
1322
+
1323
+ selfOpenedRef = new (ctx) OpaqueValueExpr (SourceLoc (), opaqueValueTy);
1324
+ cs.cacheType (selfOpenedRef);
1325
+
1326
+ // If we're opening an existential and the thunk's 'self' parameter has
1327
+ // non-trivial ownership, we must adjust the parameter reference type
1328
+ // here, because the body will use the opaque value instead.
1329
+ adjustExprOwnershipForParam (selfParamRef, selfThunkParam);
1330
+ }
1331
+
1332
+ // The inner thunk, "{ args... in self.member(args...) }".
1333
+ auto *const innerThunk = buildSingleCurryThunk (
1334
+ selfOpenedRef, memberRef, cast<DeclContext>(member),
1335
+ outerThunkTy->getResult ()->castTo <FunctionType>(), memberLocator);
1336
+
1337
+ // Rewrite the body to close the existential if warranted.
1338
+ if (selfCalleeParamTy->hasOpenedExistential ()) {
1339
+ auto *body = innerThunk->getSingleExpressionBody ();
1340
+ body = new (ctx) OpenExistentialExpr (
1341
+ selfParamRef, cast<OpaqueValueExpr>(selfOpenedRef), body,
1342
+ body->getType ());
1343
+ cs.cacheType (body);
1344
+
1345
+ innerThunk->setBody (body);
1346
+ }
1347
+
1348
+ // Finally, construct the outer thunk.
1349
+ auto outerThunk = new (ctx) AutoClosureExpr (
1350
+ innerThunk, outerThunkTy, AutoClosureExpr::InvalidDiscriminator, dc);
1351
+ outerThunk->setThunkKind (AutoClosureExpr::Kind::DoubleCurryThunk);
1352
+ outerThunk->setParameterList (
1353
+ ParameterList::create (ctx, SourceLoc (), selfParamDecl, SourceLoc ()));
1354
+ cs.cacheType (outerThunk);
1355
+
1356
+ return outerThunk;
1357
+ }
1358
+
1262
1359
// / Build a new member reference with the given base and member.
1263
1360
Expr *buildMemberRef (Expr *base, SourceLoc dotLoc,
1264
1361
SelectedOverload overload, DeclNameLoc memberLoc,
@@ -1597,65 +1694,10 @@ namespace {
1597
1694
->castTo <FunctionType>();
1598
1695
}
1599
1696
1600
- auto discriminator = AutoClosureExpr::InvalidDiscriminator;
1601
-
1602
- // The outer closure.
1603
- //
1604
- // let outerClosure = "{ self in \(closure) }"
1605
- auto selfParam = curryThunkTy->getParams ()[0 ];
1606
- auto selfParamDecl = new (context) ParamDecl (
1607
- SourceLoc (),
1608
- /* argument label*/ SourceLoc (), Identifier (),
1609
- /* parameter name*/ SourceLoc (), context.Id_self ,
1610
- dc);
1611
-
1612
- auto selfParamTy = selfParam.getPlainType ();
1613
- bool isLValue = selfParam.isInOut ();
1614
-
1615
- selfParamDecl->setInterfaceType (selfParamTy->mapTypeOutOfContext ());
1616
- selfParamDecl->setSpecifier (
1617
- ParamDecl::getParameterSpecifierForValueOwnership (
1618
- selfParam.getValueOwnership ()));
1619
- selfParamDecl->setImplicit ();
1620
-
1621
- auto *outerParams =
1622
- ParameterList::create (context, SourceLoc (), selfParamDecl,
1623
- SourceLoc ());
1624
-
1625
- // The inner closure.
1626
- //
1627
- // let closure = "{ args... in self.member(args...) }"
1628
- auto selfFnTy = curryThunkTy->getResult ()->castTo <FunctionType>();
1629
-
1630
- Expr *selfParamRef =
1631
- new (context) DeclRefExpr (selfParamDecl, DeclNameLoc (),
1632
- /* implicit=*/ true );
1633
-
1634
- selfParamRef->setType (
1635
- isLValue ? LValueType::get (selfParamTy) : selfParamTy);
1636
- cs.cacheType (selfParamRef);
1637
-
1638
- if (isLValue) {
1639
- selfParamRef =
1640
- new (context) InOutExpr (SourceLoc (), selfParamRef, selfParamTy,
1641
- /* implicit=*/ true );
1642
- cs.cacheType (selfParamRef);
1643
- }
1644
-
1645
- auto closure = buildCurryThunk (member, selfFnTy, selfParamRef, ref,
1646
- memberLocator);
1647
-
1648
- auto outerClosure =
1649
- new (context) AutoClosureExpr (closure, selfFnTy, discriminator, dc);
1650
- outerClosure->setThunkKind (AutoClosureExpr::Kind::DoubleCurryThunk);
1651
-
1652
- outerClosure->setParameterList (outerParams);
1653
- outerClosure->setType (curryThunkTy);
1654
- cs.cacheType (outerClosure);
1655
-
1656
1697
// Replace the DeclRefExpr with a closure expression which SILGen
1657
1698
// knows how to emit.
1658
- ref = outerClosure;
1699
+ ref = buildDoubleCurryThunk (declRefExpr, member, curryThunkTy,
1700
+ memberLocator);
1659
1701
}
1660
1702
1661
1703
// If the member is a method with a dynamic 'Self' result type, wrap an
0 commit comments