Skip to content

Commit 6412581

Browse files
authored
Merge pull request #28698 from slavapestov/sr-75
Sema: Rewrite partial applications into closures
2 parents d6ebb03 + c543838 commit 6412581

File tree

73 files changed

+944
-884
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+944
-884
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,19 @@ Swift Next
4646
// OK, <U where U: Equatable> has broader visibility than <T where T == Int>
4747
override func foo() where U: Equatable { ... }
4848
}
49+
50+
* [SR-75][]:
51+
52+
Unapplied references to protocol methods methods are now supported. Previously this
53+
only worked for methods defined in structs, enums and classes.
54+
55+
```swift
56+
protocol Cat {
57+
func play(catToy: Toy)
58+
}
59+
60+
let fn = Cat.play
61+
fn(myCat)(myToy)
4962
```
5063

5164
* [SE-0266][]:
@@ -7939,6 +7952,7 @@ Swift 1.0
79397952
[SE-0267]: <https://github.com/apple/swift-evolution/blob/master/proposals/0267-where-on-contextually-generic.md>
79407953
[SE-0269]: <https://github.com/apple/swift-evolution/blob/master/proposals/0269-implicit-self-explicit-capture.md>
79417954

7955+
[SR-75]: <https://bugs.swift.org/browse/SR-75>
79427956
[SR-106]: <https://bugs.swift.org/browse/SR-106>
79437957
[SR-419]: <https://bugs.swift.org/browse/SR-419>
79447958
[SR-631]: <https://bugs.swift.org/browse/SR-631>

lib/AST/Expr.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,11 @@ Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
18511851
case AutoClosureExpr::Kind::SingleCurryThunk: {
18521852
auto *body = getSingleExpressionBody();
18531853
body = body->getSemanticsProvidingExpr();
1854+
1855+
if (auto *openExistential = dyn_cast<OpenExistentialExpr>(body)) {
1856+
body = openExistential->getSubExpr();
1857+
}
1858+
18541859
if (auto *outerCall = dyn_cast<ApplyExpr>(body)) {
18551860
return outerCall->getFn();
18561861
}
@@ -1866,6 +1871,11 @@ Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
18661871
AutoClosureExpr::Kind::SingleCurryThunk);
18671872
auto *innerBody = innerClosure->getSingleExpressionBody();
18681873
innerBody = innerBody->getSemanticsProvidingExpr();
1874+
1875+
if (auto *openExistential = dyn_cast<OpenExistentialExpr>(innerBody)) {
1876+
innerBody = openExistential->getSubExpr();
1877+
}
1878+
18691879
if (auto *outerCall = dyn_cast<ApplyExpr>(innerBody)) {
18701880
if (auto *innerCall = dyn_cast<ApplyExpr>(outerCall->getFn())) {
18711881
if (auto *declRef = dyn_cast<DeclRefExpr>(innerCall->getFn())) {

lib/IDE/SourceEntityWalker.cpp

Lines changed: 55 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -246,14 +246,23 @@ static SemaReferenceKind getReferenceKind(Expr *Parent, Expr *E) {
246246
std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
247247
assert(E);
248248

249+
std::pair<bool, Expr *> stopTraversal = { false, nullptr };
250+
std::pair<bool, Expr *> skipChildren = { false, E };
251+
252+
auto doSkipChildren = [&]() -> std::pair<bool, Expr *> {
253+
if (!SEWalker.walkToExprPost(E))
254+
return stopTraversal;
255+
return skipChildren;
256+
};
257+
249258
if (isDone())
250-
return { false, nullptr };
259+
return stopTraversal;
251260

252261
if (ExprsToSkip.count(E) != 0)
253-
return { false, E };
262+
return skipChildren;
254263

255264
if (!SEWalker.walkToExprPre(E))
256-
return { false, E };
265+
return skipChildren;
257266

258267
if (auto *CtorRefE = dyn_cast<ConstructorRefCallExpr>(E))
259268
CtorRefs.push_back(CtorRefE);
@@ -262,15 +271,16 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
262271
if (auto *SubExpr = ACE->getUnwrappedCurryThunkExpr()) {
263272
if (auto *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
264273
if (!passReference(DRE->getDecl(), DRE->getType(),
265-
DRE->getNameLoc(),
266-
ReferenceMetaData(getReferenceKind(Parent.getAsExpr(), DRE),
267-
OpAccess))) {
268-
return { false, nullptr };
269-
}
274+
DRE->getNameLoc(),
275+
ReferenceMetaData(getReferenceKind(Parent.getAsExpr(), DRE),
276+
OpAccess)))
277+
return stopTraversal;
270278

271-
return { true, E };
279+
return doSkipChildren();
272280
}
273281
}
282+
283+
return { true, E };
274284
}
275285

276286
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
@@ -300,12 +310,12 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
300310
if (auto *module = dyn_cast<ModuleDecl>(DRE->getDecl())) {
301311
if (!passReference(ModuleEntity(module),
302312
{module->getName(), E->getLoc()}))
303-
return { false, nullptr };
313+
return stopTraversal;
304314
} else if (!passReference(DRE->getDecl(), DRE->getType(),
305315
DRE->getNameLoc(),
306316
ReferenceMetaData(getReferenceKind(Parent.getAsExpr(), DRE),
307317
OpAccess))) {
308-
return { false, nullptr };
318+
return stopTraversal;
309319
}
310320
} else if (auto *MRE = dyn_cast<MemberRefExpr>(E)) {
311321
{
@@ -324,31 +334,29 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
324334

325335
// Visit in source order.
326336
if (!MRE->getBase()->walk(*this))
327-
return { false, nullptr };
337+
return stopTraversal;
328338
}
329339

330340
if (!passReference(MRE->getMember().getDecl(), MRE->getType(),
331341
MRE->getNameLoc(),
332342
ReferenceMetaData(SemaReferenceKind::DeclMemberRef,
333343
OpAccess)))
334-
return { false, nullptr };
344+
return stopTraversal;
335345

336346
// We already visited the children.
337-
if (!walkToExprPost(E))
338-
return { false, nullptr };
339-
return { false, E };
347+
return doSkipChildren();
340348

341349
} else if (auto OtherCtorE = dyn_cast<OtherConstructorDeclRefExpr>(E)) {
342350
if (!passReference(OtherCtorE->getDecl(), OtherCtorE->getType(),
343351
OtherCtorE->getConstructorLoc(),
344352
ReferenceMetaData(SemaReferenceKind::DeclConstructorRef,
345353
OpAccess)))
346-
return { false, nullptr };
354+
return stopTraversal;
347355

348356
} else if (auto *SE = dyn_cast<SubscriptExpr>(E)) {
349357
// Visit in source order.
350358
if (!SE->getBase()->walk(*this))
351-
return { false, nullptr };
359+
return stopTraversal;
352360

353361
ValueDecl *SubscrD = nullptr;
354362
if (SE->hasDecl())
@@ -359,21 +367,19 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
359367

360368
if (SubscrD) {
361369
if (!passSubscriptReference(SubscrD, E->getLoc(), data, true))
362-
return { false, nullptr };
370+
return stopTraversal;
363371
}
364372

365373
if (!SE->getIndex()->walk(*this))
366-
return { false, nullptr };
374+
return stopTraversal;
367375

368376
if (SubscrD) {
369377
if (!passSubscriptReference(SubscrD, E->getEndLoc(), data, false))
370-
return { false, nullptr };
378+
return stopTraversal;
371379
}
372380

373381
// We already visited the children.
374-
if (!walkToExprPost(E))
375-
return { false, nullptr };
376-
return { false, E };
382+
return doSkipChildren();
377383

378384
} else if (auto *KPE = dyn_cast<KeyPathExpr>(E)) {
379385
for (auto &component : KPE->getComponents()) {
@@ -406,60 +412,54 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
406412
} else if (auto *BinE = dyn_cast<BinaryExpr>(E)) {
407413
// Visit in source order.
408414
if (!BinE->getArg()->getElement(0)->walk(*this))
409-
return { false, nullptr };
415+
return stopTraversal;
410416
if (!BinE->getFn()->walk(*this))
411-
return { false, nullptr };
417+
return stopTraversal;
412418
if (!BinE->getArg()->getElement(1)->walk(*this))
413-
return { false, nullptr };
419+
return stopTraversal;
414420

415421
// We already visited the children.
416-
if (!walkToExprPost(E))
417-
return { false, nullptr };
418-
return { false, E };
422+
return doSkipChildren();
419423

420424
} else if (auto TupleE = dyn_cast<TupleExpr>(E)) {
421425
if (auto CallE = dyn_cast_or_null<CallExpr>(Parent.getAsExpr())) {
422426
if (!passCallArgNames(CallE->getFn(), TupleE))
423-
return { false, nullptr };
427+
return stopTraversal;
424428
}
425429
} else if (auto IOE = dyn_cast<InOutExpr>(E)) {
426430
llvm::SaveAndRestore<Optional<AccessKind>>
427431
C(this->OpAccess, AccessKind::ReadWrite);
428432

429433
if (!IOE->getSubExpr()->walk(*this))
430-
return { false, nullptr };
434+
return stopTraversal;
431435

432436
// We already visited the children.
433437
if (!walkToExprPost(E))
434-
return { false, nullptr };
435-
return { false, E };
438+
return stopTraversal;
439+
return skipChildren;
436440
} else if (auto LE = dyn_cast<LoadExpr>(E)) {
437441
llvm::SaveAndRestore<Optional<AccessKind>>
438442
C(this->OpAccess, AccessKind::Read);
439443

440444
if (!LE->getSubExpr()->walk(*this))
441-
return { false, nullptr };
445+
return stopTraversal;
442446

443447
// We already visited the children.
444-
if (!walkToExprPost(E))
445-
return { false, nullptr };
446-
return { false, E };
448+
return doSkipChildren();
447449
} else if (auto AE = dyn_cast<AssignExpr>(E)) {
448450
{
449451
llvm::SaveAndRestore<Optional<AccessKind>>
450452
C(this->OpAccess, AccessKind::Write);
451453

452454
if (AE->getDest() && !AE->getDest()->walk(*this))
453-
return { false, nullptr };
455+
return stopTraversal;
454456
}
455457

456458
if (AE->getSrc() && !AE->getSrc()->walk(*this))
457-
return { false, nullptr };
459+
return stopTraversal;
458460

459461
// We already visited the children.
460-
if (!walkToExprPost(E))
461-
return { false, nullptr };
462-
return { false, E };
462+
return doSkipChildren();
463463
} else if (auto OEE = dyn_cast<OpenExistentialExpr>(E)) {
464464
// Record opaque value.
465465
OpaqueValueMap[OEE->getOpaqueValue()] = OEE->getExistentialValue();
@@ -468,44 +468,39 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
468468
};
469469

470470
if (!OEE->getSubExpr()->walk(*this))
471-
return { false, nullptr };
472-
if (!walkToExprPost(E))
473-
return { false, nullptr };
474-
return { false, E };
471+
return stopTraversal;
472+
473+
return doSkipChildren();
475474
} else if (auto MTEE = dyn_cast<MakeTemporarilyEscapableExpr>(E)) {
476475
// Manually walk to original arguments in order. We don't handle
477476
// OpaqueValueExpr here.
478477

479478
// Original non-escaping closure.
480479
if (!MTEE->getNonescapingClosureValue()->walk(*this))
481-
return { false, nullptr };
480+
return stopTraversal;
482481

483482
// Body, which is called by synthesized CallExpr.
484483
auto *callExpr = cast<CallExpr>(MTEE->getSubExpr());
485484
if (!callExpr->getFn()->walk(*this))
486-
return { false, nullptr };
485+
return stopTraversal;
487486

488-
if (!walkToExprPost(E))
489-
return { false, nullptr };
490-
return { false, E };
487+
return doSkipChildren();
491488
} else if (auto CUCE = dyn_cast<CollectionUpcastConversionExpr>(E)) {
492489
// Ignore conversion expressions. We don't handle OpaqueValueExpr here
493490
// because it's only in conversion expressions. Instead, just walk into
494491
// sub expression.
495492
if (!CUCE->getSubExpr()->walk(*this))
496-
return { false, nullptr };
497-
if (!walkToExprPost(E))
498-
return { false, nullptr };
499-
return { false, E };
493+
return stopTraversal;
494+
495+
return doSkipChildren();
500496
} else if (auto OVE = dyn_cast<OpaqueValueExpr>(E)) {
501497
// Walk into mapped value.
502498
auto value = OpaqueValueMap.find(OVE);
503499
if (value != OpaqueValueMap.end()) {
504500
if (!value->second->walk(*this))
505-
return { false, nullptr };
506-
if (!walkToExprPost(E))
507-
return { false, nullptr };
508-
return { false, E };
501+
return stopTraversal;
502+
503+
return doSkipChildren();
509504
}
510505
}
511506

lib/SIL/SILDeclRef.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,8 +450,11 @@ bool SILDeclRef::isTransparent() const {
450450
if (isStoredPropertyInitializer())
451451
return true;
452452

453-
if (hasAutoClosureExpr())
454-
return true;
453+
if (hasAutoClosureExpr()) {
454+
auto *ace = getAutoClosureExpr();
455+
if (ace->getThunkKind() == AutoClosureExpr::Kind::None)
456+
return true;
457+
}
455458

456459
if (hasDecl()) {
457460
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(getDecl()))

lib/SIL/SILProfiler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ static bool isUnmapped(ASTNode N) {
6868
LLVM_DEBUG(llvm::dbgs() << "Skipping ASTNode: implicit closure expr\n");
6969
return true;
7070
}
71+
72+
if (isa<AutoClosureExpr>(CE) &&
73+
cast<AutoClosureExpr>(CE)->getThunkKind() != AutoClosureExpr::Kind::None) {
74+
LLVM_DEBUG(llvm::dbgs() << "Skipping ASTNode: curry thunk expr\n");
75+
return true;
76+
}
7177
}
7278

7379
// Map all other kinds of expressions.

0 commit comments

Comments
 (0)