Skip to content

Commit fdd619b

Browse files
committed
Handle function conversions in concurrency checking.
1 parent 0674058 commit fdd619b

File tree

4 files changed

+34
-13
lines changed

4 files changed

+34
-13
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: 14 additions & 6 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,
@@ -1909,6 +1914,8 @@ Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
19091914
auto maybeUnwrapConversions = [](Expr *expr) {
19101915
if (auto *covariantReturn = dyn_cast<CovariantReturnConversionExpr>(expr))
19111916
expr = covariantReturn->getSubExpr();
1917+
if (auto *functionConversion = dyn_cast<FunctionConversionExpr>(expr))
1918+
expr = functionConversion->getSubExpr();
19121919
return expr;
19131920
};
19141921

@@ -1944,7 +1951,8 @@ Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
19441951
innerBody = maybeUnwrapConversions(innerBody);
19451952

19461953
if (auto *outerCall = dyn_cast<ApplyExpr>(innerBody)) {
1947-
if (auto *innerCall = dyn_cast<ApplyExpr>(outerCall->getFn())) {
1954+
auto outerFn = maybeUnwrapConversions(outerCall->getFn());
1955+
if (auto *innerCall = dyn_cast<ApplyExpr>(outerFn)) {
19481956
return innerCall->getFn();
19491957
}
19501958
}

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

@@ -1878,7 +1886,7 @@ namespace {
18781886
// like based on the original written syntax, e.g., "self.method".
18791887
if (auto partialApply = decomposePartialApplyThunk(
18801888
apply, Parent.getAsExpr())) {
1881-
if (auto memberRef = findMemberReference(partialApply->fn)) {
1889+
if (auto memberRef = findReference(partialApply->fn)) {
18821890
// NOTE: partially-applied thunks are never annotated as
18831891
// implicitly async, regardless of whether they are escaping.
18841892
checkReference(
@@ -1899,7 +1907,7 @@ namespace {
18991907
// NOTE: SelfApplyExpr is a subtype of ApplyExpr
19001908
if (auto call = dyn_cast<SelfApplyExpr>(expr)) {
19011909
Expr *fn = call->getFn()->getValueProvidingExpr();
1902-
if (auto memberRef = findMemberReference(fn)) {
1910+
if (auto memberRef = findReference(fn)) {
19031911
checkReference(
19041912
call->getBase(), memberRef->first, memberRef->second,
19051913
/*partialApply=*/None, call);
@@ -2134,6 +2142,8 @@ namespace {
21342142

21352143
if (auto conversion = dyn_cast<ImplicitConversionExpr>(expr))
21362144
expr = conversion->getSubExpr();
2145+
if (auto fnConv = dyn_cast<FunctionConversionExpr>(expr))
2146+
expr = fnConv->getSubExpr();
21372147
} while (prior != expr);
21382148

21392149
if (auto call = dyn_cast<DotSyntaxCallExpr>(expr)) {
@@ -2410,7 +2420,9 @@ namespace {
24102420
// and the fact that the reference may be just an argument to an apply
24112421
ApplyExpr *apply = applyStack.back();
24122422
Expr *fn = apply->getFn()->getValueProvidingExpr();
2413-
if (auto memberRef = findMemberReference(fn)) {
2423+
if (auto fnConv = dyn_cast<FunctionConversionExpr>(fn))
2424+
fn = fnConv->getSubExpr()->getValueProvidingExpr();
2425+
if (auto memberRef = findReference(fn)) {
24142426
auto concDecl = memberRef->first;
24152427
if (decl == concDecl.getDecl() && !apply->isImplicitlyAsync()) {
24162428

@@ -2528,7 +2540,8 @@ namespace {
25282540

25292541
// If we are not in an asynchronous context, complain.
25302542
if (!getDeclContext()->isAsyncContext()) {
2531-
if (auto calleeDecl = apply->getCalledValue()) {
2543+
if (auto calleeDecl = apply->getCalledValue(
2544+
/*skipFunctionConversions=*/true)) {
25322545
ctx.Diags.diagnose(
25332546
apply->getLoc(), diag::actor_isolated_call_decl,
25342547
*unsatisfiedIsolation,

lib/Sema/TypeCheckEffects.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2876,7 +2876,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
28762876
if (call && call->isImplicitlyAsync()) {
28772877
// Emit a tailored note if the call is implicitly async, meaning the
28782878
// callee is isolated to an actor.
2879-
auto callee = call->getCalledValue();
2879+
auto callee = call->getCalledValue(/*skipFunctionConversions=*/true);
28802880
if (callee) {
28812881
Ctx.Diags.diagnose(diag.expr.getStartLoc(), diag::actor_isolated_sync_func,
28822882
callee->getDescriptiveKind(), callee->getName());

0 commit comments

Comments
 (0)