Skip to content

Commit 784c4a5

Browse files
committed
[IDE] Skip synthesized curry thunks and walk their unwrapped expression
SemaAnnotator was walking into an autoclosure and then manually running `passReference` on the unwrapped expression without walking it. Since its synthesized anyway, skip walking the autoclosure entirely and walk the unwrapped expression instead. Fix `swift::ide::isBeingCalled` to look through `IdentityExpr`s and `swift::ide::getBase` also not unwrapping curry thunks. Resolves rdar://81312849
1 parent fc76bf8 commit 784c4a5

File tree

5 files changed

+43
-25
lines changed

5 files changed

+43
-25
lines changed

include/swift/IDE/Utils.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,8 +577,10 @@ ClangNode extensionGetClangNode(const ExtensionDecl *ext);
577577

578578
/// Utility for finding the referenced declaration from a call, which might
579579
/// include a second level of function application for a 'self.' expression,
580-
/// or a curry thunk, etc.
581-
std::pair<Type, ConcreteDeclRef> getReferencedDecl(Expr *expr);
580+
/// or a curry thunk, etc. If \p semantic is true then the underlying semantic
581+
/// expression of \p expr is used.
582+
std::pair<Type, ConcreteDeclRef> getReferencedDecl(Expr *expr,
583+
bool semantic = true);
582584

583585
/// Whether the last expression in \p ExprStack is being called.
584586
bool isBeingCalled(ArrayRef<Expr*> ExprStack);

lib/IDE/SourceEntityWalker.cpp

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,21 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
330330
return { false, E };
331331
}
332332

333+
auto doStopTraversal = [&]() -> std::pair<bool, Expr *> {
334+
Cancelled = true;
335+
return { false, nullptr };
336+
};
337+
338+
// Skip the synthesized curry thunks and just walk over the unwrapped
339+
// expression
340+
if (auto *ACE = dyn_cast<AutoClosureExpr>(E)) {
341+
if (auto *SubExpr = ACE->getUnwrappedCurryThunkExpr()) {
342+
if (!SubExpr->walk(*this))
343+
return doStopTraversal();
344+
return { false, E };
345+
}
346+
}
347+
333348
if (!SEWalker.walkToExprPre(E)) {
334349
return { false, E };
335350
}
@@ -346,30 +361,9 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
346361
return { false, E };
347362
};
348363

349-
auto doStopTraversal = [&]() -> std::pair<bool, Expr *> {
350-
Cancelled = true;
351-
return { false, nullptr };
352-
};
353-
354364
if (auto *CtorRefE = dyn_cast<ConstructorRefCallExpr>(E))
355365
CtorRefs.push_back(CtorRefE);
356366

357-
if (auto *ACE = dyn_cast<AutoClosureExpr>(E)) {
358-
if (auto *SubExpr = ACE->getUnwrappedCurryThunkExpr()) {
359-
if (auto *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
360-
if (!passReference(DRE->getDecl(), DRE->getType(),
361-
DRE->getNameLoc(),
362-
ReferenceMetaData(getReferenceKind(Parent.getAsExpr(), DRE),
363-
OpAccess)))
364-
return doStopTraversal();
365-
366-
return doSkipChildren();
367-
}
368-
}
369-
370-
return { true, E };
371-
}
372-
373367
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
374368
auto *FD = dyn_cast<FuncDecl>(DRE->getDecl());
375369
// Handle implicit callAsFunction reference. An explicit reference will be

lib/IDE/Utils.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1140,7 +1140,11 @@ ClangNode swift::ide::extensionGetClangNode(const ExtensionDecl *ext) {
11401140
return ClangNode();
11411141
}
11421142

1143-
std::pair<Type, ConcreteDeclRef> swift::ide::getReferencedDecl(Expr *expr) {
1143+
std::pair<Type, ConcreteDeclRef> swift::ide::getReferencedDecl(Expr *expr,
1144+
bool semantic) {
1145+
if (semantic)
1146+
expr = expr->getSemanticsProvidingExpr();
1147+
11441148
auto exprTy = expr->getType();
11451149

11461150
// Look through unbound instance member accesses.
@@ -1206,13 +1210,19 @@ Expr *swift::ide::getBase(ArrayRef<Expr *> ExprStack) {
12061210
Expr *CurrentE = ExprStack.back();
12071211
Expr *ParentE = getContainingExpr(ExprStack, 1);
12081212
Expr *Base = nullptr;
1213+
12091214
if (auto DSE = dyn_cast_or_null<DotSyntaxCallExpr>(ParentE))
12101215
Base = DSE->getBase();
12111216
else if (auto MRE = dyn_cast<MemberRefExpr>(CurrentE))
12121217
Base = MRE->getBase();
12131218
else if (auto SE = dyn_cast<SubscriptExpr>(CurrentE))
12141219
Base = SE->getBase();
12151220

1221+
// Look through curry thunks
1222+
if (auto ACE = dyn_cast_or_null<AutoClosureExpr>(Base))
1223+
if (auto *Unwrapped = ACE->getUnwrappedCurryThunkExpr())
1224+
Base = Unwrapped;
1225+
12161226
if (Base) {
12171227
while (auto ICE = dyn_cast<ImplicitConversionExpr>(Base))
12181228
Base = ICE->getSubExpr();

lib/Migrator/APIDiffMigratorPass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
572572
}
573573
return false;
574574
};
575-
if (auto *VD = getReferencedDecl(Call).second.getDecl())
575+
if (auto *VD = getReferencedDecl(Call, /*semantic=*/false).second.getDecl())
576576
if (handleDecl(VD, Call->getSourceRange()))
577577
return true;
578578

test/Index/index_curry_thunk.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s
2+
3+
struct SomeStruct {
4+
func simple(_ someClosure: () -> Void) { }
5+
}
6+
7+
func test(s: SomeStruct) {
8+
s.simple { }
9+
// CHECK: [[@LINE-1]]:5 | instance-method/Swift | simple(_:) | s:14swift_ide_test10SomeStructV6simpleyyyyXEF | Ref,Call,RelRec,RelCall,RelCont | rel: 2
10+
(((s).simple)) { }
11+
// CHECK: [[@LINE-1]]:9 | instance-method/Swift | simple(_:) | s:14swift_ide_test10SomeStructV6simpleyyyyXEF | Ref,Call,RelRec,RelCall,RelCont | rel: 2
12+
}

0 commit comments

Comments
 (0)