Skip to content

Commit 3149d6d

Browse files
committed
IDE: Preparations for Sema building curry thunks
1 parent f994334 commit 3149d6d

File tree

3 files changed

+70
-20
lines changed

3 files changed

+70
-20
lines changed

include/swift/AST/Expr.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,12 @@ class alignas(8) Expr {
284284
Discriminator : 16
285285
);
286286

287+
SWIFT_INLINE_BITFIELD(AutoClosureExpr, AbstractClosureExpr, 1,
288+
/// True if this autoclosure was built for a function conversion, and
289+
/// not an actual @autoclosure parameter.
290+
IsThunk : 1
291+
);
292+
287293
SWIFT_INLINE_BITFIELD(ClosureExpr, AbstractClosureExpr, 1,
288294
/// True if closure parameters were synthesized from anonymous closure
289295
/// variables.
@@ -3762,6 +3768,16 @@ class AutoClosureExpr : public AbstractClosureExpr {
37623768
Discriminator, Parent) {
37633769
if (Body != nullptr)
37643770
setBody(Body);
3771+
3772+
Bits.AutoClosureExpr.IsThunk = false;
3773+
}
3774+
3775+
bool isThunk() const {
3776+
return Bits.AutoClosureExpr.IsThunk;
3777+
}
3778+
3779+
void setIsThunk(bool isThunk) {
3780+
Bits.AutoClosureExpr.IsThunk = isThunk;
37653781
}
37663782

37673783
SourceRange getSourceRange() const;

lib/IDE/CodeCompletion.cpp

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,57 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
12641264
/// to the \c Consumer.
12651265
bool DeliveredResults = false;
12661266

1267+
std::pair<Type, ConcreteDeclRef> getReferencedDecl(Expr *expr) {
1268+
auto exprTy = ParsedExpr->getType();
1269+
1270+
// Look through unbound instance member accesses.
1271+
if (auto *dotSyntaxExpr = dyn_cast<DotSyntaxBaseIgnoredExpr>(expr))
1272+
expr = dotSyntaxExpr->getRHS();
1273+
1274+
// Look through the 'self' application.
1275+
if (auto *selfApplyExpr = dyn_cast<SelfApplyExpr>(expr))
1276+
expr = selfApplyExpr->getFn();
1277+
1278+
// Look through curry thunks.
1279+
if (auto *closure = dyn_cast<AutoClosureExpr>(expr)) {
1280+
if (closure->isThunk()) {
1281+
auto *body = closure->getSingleExpressionBody();
1282+
if (isa<AutoClosureExpr>(body) &&
1283+
closure->getParameters()->size() == 1)
1284+
expr = closure->getSingleExpressionBody();
1285+
}
1286+
}
1287+
1288+
if (auto *closure = dyn_cast<AutoClosureExpr>(expr)) {
1289+
if (closure->isThunk()) {
1290+
auto *body = closure->getSingleExpressionBody();
1291+
body = body->getSemanticsProvidingExpr();
1292+
if (auto *outerCall = dyn_cast<ApplyExpr>(body)) {
1293+
if (auto *innerCall = dyn_cast<ApplyExpr>(outerCall->getFn())) {
1294+
if (auto *declRef = dyn_cast<DeclRefExpr>(innerCall->getFn())) {
1295+
expr = declRef;
1296+
}
1297+
}
1298+
}
1299+
}
1300+
}
1301+
1302+
// If this is an IUO result, unwrap the optional type.
1303+
auto refDecl = expr->getReferencedDecl();
1304+
if (!refDecl) {
1305+
if (auto *applyExpr = dyn_cast<ApplyExpr>(expr)) {
1306+
auto fnDecl = applyExpr->getFn()->getReferencedDecl();
1307+
if (auto *func = fnDecl.getDecl()) {
1308+
if (func->isImplicitlyUnwrappedOptional()) {
1309+
if (auto objectTy = exprTy->getOptionalObjectType())
1310+
exprTy = objectTy;
1311+
}
1312+
}
1313+
}
1314+
}
1315+
1316+
return std::make_pair(exprTy, refDecl);
1317+
}
12671318

12681319
Optional<std::pair<Type, ConcreteDeclRef>> typeCheckParsedExpr() {
12691320
assert(ParsedExpr && "should have an expression");
@@ -1279,24 +1330,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
12791330
// typecheck again. rdar://21466394
12801331
if (CheckKind == CompletionTypeCheckKind::Normal &&
12811332
ParsedExpr->getType() && !ParsedExpr->getType()->is<ErrorType>()) {
1282-
auto refDecl = ParsedExpr->getReferencedDecl();
1283-
auto exprTy = ParsedExpr->getType();
1284-
if (!refDecl) {
1285-
// FIXME: do this in the not-already-type-checked branch too?
1286-
if (auto *apply = dyn_cast<SelfApplyExpr>(ParsedExpr)) {
1287-
refDecl = apply->getFn()->getReferencedDecl();
1288-
} else if (auto *apply = dyn_cast<ApplyExpr>(ParsedExpr)) {
1289-
// If this is an IUO, use the underlying non-optional type instead
1290-
auto fnDecl = apply->getFn()->getReferencedDecl();
1291-
if (auto FD = fnDecl.getDecl()) {
1292-
if (FD->isImplicitlyUnwrappedOptional()) {
1293-
if (auto OT = exprTy->getOptionalObjectType())
1294-
exprTy = OT;
1295-
}
1296-
}
1297-
}
1298-
}
1299-
return std::make_pair(exprTy, refDecl);
1333+
return getReferencedDecl(ParsedExpr);
13001334
}
13011335

13021336
ConcreteDeclRef ReferencedDecl = nullptr;

lib/Index/Index.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,10 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
362362
}
363363

364364
void handleMemberwiseInitRefs(Expr *E) {
365-
if (!isa<ConstructorRefCallExpr>(E))
365+
if (!isa<ApplyExpr>(E))
366366
return;
367367

368-
auto *DeclRef = dyn_cast<DeclRefExpr>(cast<ConstructorRefCallExpr>(E)->getFn());
368+
auto *DeclRef = dyn_cast<DeclRefExpr>(cast<ApplyExpr>(E)->getFn());
369369
if (!DeclRef || !isMemberwiseInit(DeclRef->getDecl()))
370370
return;
371371

0 commit comments

Comments
 (0)