@@ -1186,10 +1186,30 @@ namespace {
1186
1186
thunk->setParameterList (thunkParamList);
1187
1187
thunk->setThunkKind (AutoClosureExpr::Kind::SingleCurryThunk);
1188
1188
cs.cacheType (thunk);
1189
+
1190
+ // If the `self` type is existential, it must be opened.
1191
+ OpaqueValueExpr *baseOpened = nullptr ;
1192
+ Expr *origBaseExpr = baseExpr;
1193
+ if (baseExpr) {
1194
+ auto baseTy = cs.getType (baseExpr);
1195
+ if (baseTy->isAnyExistentialType ()) {
1196
+ Type openedTy = solution.OpenedExistentialTypes .lookup (
1197
+ cs.getConstraintLocator (locator));
1198
+ assert (openedTy);
1199
+
1200
+ Type opaqueValueTy = openedTy;
1201
+ if (baseTy->is <ExistentialMetatypeType>())
1202
+ opaqueValueTy = MetatypeType::get (opaqueValueTy);
1203
+
1204
+ baseOpened = new (ctx) OpaqueValueExpr (SourceLoc (), opaqueValueTy);
1205
+ cs.cacheType (baseOpened);
1206
+ baseExpr = baseOpened;
1207
+ }
1208
+ }
1189
1209
1190
1210
Expr *thunkBody = buildSingleCurryThunkBodyCall (
1191
1211
baseExpr, fnExpr, declOrClosure, thunkParamList, locator);
1192
-
1212
+
1193
1213
// If we called a function with a dynamic 'Self' result, we may need some
1194
1214
// special handling.
1195
1215
if (baseExpr) {
@@ -1219,6 +1239,15 @@ namespace {
1219
1239
// Now, coerce to the result type of the thunk.
1220
1240
thunkBody = coerceToType (thunkBody, thunkTy->getResult (), locator);
1221
1241
1242
+ // Close up the existential if necessary.
1243
+ if (baseOpened) {
1244
+ thunkBody = new (ctx) OpenExistentialExpr (origBaseExpr,
1245
+ baseOpened,
1246
+ thunkBody,
1247
+ thunkBody->getType ());
1248
+ cs.cacheType (thunkBody);
1249
+ }
1250
+
1222
1251
if (thunkTy->getExtInfo ().isThrowing ()) {
1223
1252
thunkBody = new (ctx)
1224
1253
TryExpr (thunkBody->getStartLoc (), thunkBody, cs.getType (thunkBody),
@@ -1529,13 +1558,14 @@ namespace {
1529
1558
// inside the curry thunk as well. This reduces abstraction and
1530
1559
// post-factum function type conversions, and results in better SILGen.
1531
1560
//
1532
- // For a partial application of a class method, however, we always want
1533
- // the thunk to accept a class to avoid potential abstraction, so the
1534
- // existential base must be opened eagerly in order to be upcast to the
1535
- // appropriate class reference type before it is passed to the thunk.
1561
+ // For a partial application of a class instance method, however, we
1562
+ // always want the thunk to accept a class to avoid potential
1563
+ // abstraction, so the existential base must be opened eagerly in order
1564
+ // to be upcast to the appropriate class reference type before it is
1565
+ // passed to the thunk.
1536
1566
if (!needsCurryThunk ||
1537
1567
(!member->getDeclContext ()->getSelfProtocolDecl () &&
1538
- !isUnboundInstanceMember )) {
1568
+ baseIsInstance && member-> isInstanceMember () )) {
1539
1569
// Open the existential before performing the member reference.
1540
1570
base = openExistentialReference (base, knownOpened->second , member);
1541
1571
baseTy = knownOpened->second ;
@@ -1790,26 +1820,79 @@ namespace {
1790
1820
memberLocator);
1791
1821
} else if (needsCurryThunk) {
1792
1822
// Another case where we want to build a single closure is when
1793
- // we have a partial application of a static member on a statically-
1794
- // derived metatype value. Again, there are no order of evaluation
1795
- // concerns here, and keeping the call and base together in the AST
1796
- // improves SILGen.
1797
- if ((isa<ConstructorDecl>(member)
1798
- || member->isStatic ()) &&
1799
- cs.isStaticallyDerivedMetatype (base)) {
1800
- // Add a useless ".self" to avoid downstream diagnostics.
1801
- base = new (context) DotSelfExpr (base, SourceLoc (), base->getEndLoc (),
1802
- cs.getType (base));
1803
- cs.setType (base, base->getType ());
1804
-
1805
- auto *closure = buildSingleCurryThunk (
1806
- base, declRefExpr, cast<AbstractFunctionDecl>(member),
1823
+ // we have a partial application of a static member. It is better
1824
+ // to either push the base reference down into the closure (if it's
1825
+ // just a literal type reference, in which case there are no order of
1826
+ // operation concerns with capturing vs. evaluating it in the closure),
1827
+ // or to evaluate the base as a capture and hand it down via the
1828
+ // capture list.
1829
+ if (isa<ConstructorDecl>(member) || member->isStatic ()) {
1830
+ if (cs.isStaticallyDerivedMetatype (base)) {
1831
+ // Add a useless ".self" to avoid downstream diagnostics.
1832
+ base = new (context) DotSelfExpr (base, SourceLoc (), base->getEndLoc (),
1833
+ cs.getType (base));
1834
+ cs.setType (base, base->getType ());
1835
+
1836
+ auto *closure = buildSingleCurryThunk (
1837
+ base, declRefExpr, cast<AbstractFunctionDecl>(member),
1838
+ memberLocator);
1839
+
1840
+ // Skip the code below -- we're not building an extra level of
1841
+ // call by applying the metatype; instead, the closure we just
1842
+ // built is the curried reference.
1843
+ return closure;
1844
+ } else {
1845
+ // Add a useless ".self" to avoid downstream diagnostics, in case
1846
+ // the type ref is still a TypeExpr.
1847
+ base = new (context) DotSelfExpr (base, SourceLoc (), base->getEndLoc (),
1848
+ cs.getType (base));
1849
+ // Introduce a capture variable.
1850
+ cs.cacheType (base);
1851
+ solution.setExprTypes (base);
1852
+ auto capture = new (context) VarDecl (/* static*/ false ,
1853
+ VarDecl::Introducer::Let,
1854
+ SourceLoc (),
1855
+ context.getIdentifier (" $base$" ),
1856
+ dc);
1857
+ capture->setImplicit ();
1858
+ capture->setInterfaceType (base->getType ()->mapTypeOutOfContext ());
1859
+
1860
+ NamedPattern *capturePat = new (context) NamedPattern (capture);
1861
+ capturePat->setImplicit ();
1862
+ capturePat->setType (base->getType ());
1863
+
1864
+ auto capturePBE = PatternBindingEntry (capturePat,
1865
+ SourceLoc (), base, dc);
1866
+ auto captureDecl = PatternBindingDecl::create (context, SourceLoc (),
1867
+ {}, SourceLoc (),
1868
+ capturePBE,
1869
+ dc);
1870
+ captureDecl->setImplicit ();
1871
+
1872
+ // Write the closure in terms of the capture.
1873
+ auto baseRef = new (context)
1874
+ DeclRefExpr (capture, DeclNameLoc (base->getLoc ()), /* implicit*/ true );
1875
+ baseRef->setType (base->getType ());
1876
+ cs.cacheType (baseRef);
1877
+
1878
+ auto *closure = buildSingleCurryThunk (
1879
+ baseRef, declRefExpr, cast<AbstractFunctionDecl>(member),
1880
+ simplifyType (adjustedOpenedType)->castTo <FunctionType>(),
1807
1881
memberLocator);
1808
-
1809
- // Skip the code below -- we're not building an extra level of
1810
- // call by applying the metatype; instead, the closure we just
1811
- // built is the curried reference.
1812
- return closure;
1882
+
1883
+ // Wrap the closure in a capture list.
1884
+ auto captureEntry = CaptureListEntry (captureDecl);
1885
+ auto captureExpr = CaptureListExpr::create (context, captureEntry,
1886
+ closure);
1887
+ captureExpr->setImplicit ();
1888
+ captureExpr->setType (cs.getType (closure));
1889
+ cs.cacheType (captureExpr);
1890
+
1891
+ Expr *finalExpr = captureExpr;
1892
+ closeExistentials (finalExpr, locator,
1893
+ /* force*/ openedExistential);
1894
+ return finalExpr;
1895
+ }
1813
1896
}
1814
1897
1815
1898
FunctionType *curryThunkTy = nullptr ;
0 commit comments