Skip to content

Commit 9d111b1

Browse files
committed
Handle function conversions in concurrency checking.
1 parent adc6d1c commit 9d111b1

File tree

4 files changed

+42
-14
lines changed

4 files changed

+42
-14
lines changed

include/swift/AST/Expr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4553,7 +4553,7 @@ class ApplyExpr : public Expr {
45534553
Bits.ApplyExpr.ShouldApplyDistributedThunk = flag;
45544554
}
45554555

4556-
ValueDecl *getCalledValue() const;
4556+
ValueDecl *getCalledValue(bool skipFunctionConversions = false) const;
45574557

45584558
static bool classof(const Expr *E) {
45594559
return E->getKind() >= ExprKind::First_ApplyExpr &&

lib/AST/Expr.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,7 +1413,7 @@ DictionaryExpr *DictionaryExpr::create(ASTContext &C, SourceLoc LBracketLoc,
14131413
Ty);
14141414
}
14151415

1416-
static ValueDecl *getCalledValue(Expr *E) {
1416+
static ValueDecl *getCalledValue(Expr *E, bool skipFunctionConversions) {
14171417
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
14181418
return DRE->getDecl();
14191419

@@ -1422,11 +1422,16 @@ static ValueDecl *getCalledValue(Expr *E) {
14221422

14231423
// Look through SelfApplyExpr.
14241424
if (auto *SAE = dyn_cast<SelfApplyExpr>(E))
1425-
return SAE->getCalledValue();
1425+
return SAE->getCalledValue(skipFunctionConversions);
1426+
1427+
if (skipFunctionConversions) {
1428+
if (auto fnConv = dyn_cast<FunctionConversionExpr>(E))
1429+
return getCalledValue(fnConv->getSubExpr(), skipFunctionConversions);
1430+
}
14261431

14271432
Expr *E2 = E->getValueProvidingExpr();
14281433
if (E != E2)
1429-
return getCalledValue(E2);
1434+
return getCalledValue(E2, skipFunctionConversions);
14301435

14311436
return nullptr;
14321437
}
@@ -1468,8 +1473,8 @@ Expr *DefaultArgumentExpr::getCallerSideDefaultExpr() const {
14681473
new (ctx) ErrorExpr(getSourceRange(), getType()));
14691474
}
14701475

1471-
ValueDecl *ApplyExpr::getCalledValue() const {
1472-
return ::getCalledValue(Fn);
1476+
ValueDecl *ApplyExpr::getCalledValue(bool skipFunctionConversions) const {
1477+
return ::getCalledValue(Fn, skipFunctionConversions);
14731478
}
14741479

14751480
SubscriptExpr::SubscriptExpr(Expr *base, ArgumentList *argList,
@@ -1906,6 +1911,14 @@ Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
19061911
return expr;
19071912
};
19081913

1914+
auto maybeUnwrapConversions = [](Expr *expr) {
1915+
if (auto *covariantReturn = dyn_cast<CovariantReturnConversionExpr>(expr))
1916+
expr = covariantReturn->getSubExpr();
1917+
if (auto *functionConversion = dyn_cast<FunctionConversionExpr>(expr))
1918+
expr = functionConversion->getSubExpr();
1919+
return expr;
1920+
};
1921+
19091922
switch (getThunkKind()) {
19101923
case AutoClosureExpr::Kind::None:
19111924
case AutoClosureExpr::Kind::AsyncLet:
@@ -1916,6 +1929,7 @@ Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
19161929
body = body->getSemanticsProvidingExpr();
19171930
body = maybeUnwrapOpenExistential(body);
19181931
body = maybeUnwrapOptionalEval(body);
1932+
body = maybeUnwrapConversions(body);
19191933

19201934
if (auto *outerCall = dyn_cast<ApplyExpr>(body)) {
19211935
return outerCall->getFn();
@@ -1934,9 +1948,10 @@ Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
19341948
innerBody = innerBody->getSemanticsProvidingExpr();
19351949
innerBody = maybeUnwrapOpenExistential(innerBody);
19361950
innerBody = maybeUnwrapOptionalEval(innerBody);
1937-
1951+
innerBody = maybeUnwrapConversions(innerBody);
19381952
if (auto *outerCall = dyn_cast<ApplyExpr>(innerBody)) {
1939-
if (auto *innerCall = dyn_cast<ApplyExpr>(outerCall->getFn())) {
1953+
auto outerFn = maybeUnwrapConversions(outerCall->getFn());
1954+
if (auto *innerCall = dyn_cast<ApplyExpr>(outerFn)) {
19401955
return innerCall->getFn();
19411956
}
19421957
}

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -489,14 +489,22 @@ static Optional<PartialApplyThunkInfo> decomposePartialApplyThunk(
489489

490490
/// Find the immediate member reference in the given expression.
491491
static Optional<std::pair<ConcreteDeclRef, SourceLoc>>
492-
findMemberReference(Expr *expr) {
492+
findReference(Expr *expr) {
493+
// Look through a function conversion.
494+
if (auto fnConv = dyn_cast<FunctionConversionExpr>(expr))
495+
expr = fnConv->getSubExpr();
496+
493497
if (auto declRef = dyn_cast<DeclRefExpr>(expr))
494498
return std::make_pair(declRef->getDeclRef(), declRef->getLoc());
495499

496500
if (auto otherCtor = dyn_cast<OtherConstructorDeclRefExpr>(expr)) {
497501
return std::make_pair(otherCtor->getDeclRef(), otherCtor->getLoc());
498502
}
499503

504+
Expr *inner = expr->getValueProvidingExpr();
505+
if (inner != expr)
506+
return findReference(inner);
507+
500508
return None;
501509
}
502510

@@ -1828,7 +1836,7 @@ namespace {
18281836
// like based on the original written syntax, e.g., "self.method".
18291837
if (auto partialApply = decomposePartialApplyThunk(
18301838
apply, Parent.getAsExpr())) {
1831-
if (auto memberRef = findMemberReference(partialApply->fn)) {
1839+
if (auto memberRef = findReference(partialApply->fn)) {
18321840
// NOTE: partially-applied thunks are never annotated as
18331841
// implicitly async, regardless of whether they are escaping.
18341842
checkReference(
@@ -1849,7 +1857,7 @@ namespace {
18491857
// NOTE: SelfApplyExpr is a subtype of ApplyExpr
18501858
if (auto call = dyn_cast<SelfApplyExpr>(expr)) {
18511859
Expr *fn = call->getFn()->getValueProvidingExpr();
1852-
if (auto memberRef = findMemberReference(fn)) {
1860+
if (auto memberRef = findReference(fn)) {
18531861
checkReference(
18541862
call->getBase(), memberRef->first, memberRef->second,
18551863
/*partialApply=*/None, call);
@@ -2084,6 +2092,8 @@ namespace {
20842092

20852093
if (auto conversion = dyn_cast<ImplicitConversionExpr>(expr))
20862094
expr = conversion->getSubExpr();
2095+
if (auto fnConv = dyn_cast<FunctionConversionExpr>(expr))
2096+
expr = fnConv->getSubExpr();
20872097
} while (prior != expr);
20882098

20892099
if (auto call = dyn_cast<DotSyntaxCallExpr>(expr)) {
@@ -2360,7 +2370,9 @@ namespace {
23602370
// and the fact that the reference may be just an argument to an apply
23612371
ApplyExpr *apply = applyStack.back();
23622372
Expr *fn = apply->getFn()->getValueProvidingExpr();
2363-
if (auto memberRef = findMemberReference(fn)) {
2373+
if (auto fnConv = dyn_cast<FunctionConversionExpr>(fn))
2374+
fn = fnConv->getSubExpr()->getValueProvidingExpr();
2375+
if (auto memberRef = findReference(fn)) {
23642376
auto concDecl = memberRef->first;
23652377
if (decl == concDecl.getDecl() && !apply->isImplicitlyAsync()) {
23662378

@@ -2478,7 +2490,8 @@ namespace {
24782490

24792491
// If we are not in an asynchronous context, complain.
24802492
if (!getDeclContext()->isAsyncContext()) {
2481-
if (auto calleeDecl = apply->getCalledValue()) {
2493+
if (auto calleeDecl = apply->getCalledValue(
2494+
/*skipFunctionConversions=*/true)) {
24822495
ctx.Diags.diagnose(
24832496
apply->getLoc(), diag::actor_isolated_call_decl,
24842497
*unsatisfiedIsolation,

lib/Sema/TypeCheckEffects.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2857,7 +2857,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
28572857
if (call && call->isImplicitlyAsync()) {
28582858
// Emit a tailored note if the call is implicitly async, meaning the
28592859
// callee is isolated to an actor.
2860-
auto callee = call->getCalledValue();
2860+
auto callee = call->getCalledValue(/*skipFunctionConversions=*/true);
28612861
if (callee) {
28622862
Ctx.Diags.diagnose(diag.expr.getStartLoc(), diag::actor_isolated_sync_func,
28632863
callee->getDescriptiveKind(), callee->getName());

0 commit comments

Comments
 (0)