Skip to content

Commit 33cfbbd

Browse files
committed
[Concurrency] Don't diagnose missing "self." in async let autoclosures.
1 parent 58b590a commit 33cfbbd

File tree

9 files changed

+36
-11
lines changed

9 files changed

+36
-11
lines changed

include/swift/AST/Expr.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3903,7 +3903,10 @@ class AutoClosureExpr : public AbstractClosureExpr {
39033903

39043904
// An autoclosure with type (Self) -> (Args...) -> Result. Formed from type
39053905
// checking a partial application.
3906-
DoubleCurryThunk = 2
3906+
DoubleCurryThunk = 2,
3907+
3908+
// An autoclosure with type () -> Result that was formed for an async let.
3909+
AsyncLet = 3,
39073910
};
39083911

39093912
AutoClosureExpr(Expr *Body, Type ResultTy, unsigned Discriminator,

include/swift/Sema/ConstraintSystem.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4373,7 +4373,8 @@ class ConstraintSystem {
43734373
/// Build implicit autoclosure expression wrapping a given expression.
43744374
/// Given expression represents computed result of the closure.
43754375
Expr *buildAutoClosureExpr(Expr *expr, FunctionType *closureType,
4376-
bool isDefaultWrappedValue = false);
4376+
bool isDefaultWrappedValue = false,
4377+
bool isAsyncLetWrapper = false);
43774378

43784379
/// Builds a type-erased return expression that can be used in dynamic
43794380
/// replacement.

lib/AST/Expr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,6 +2031,7 @@ Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
20312031

20322032
switch (getThunkKind()) {
20332033
case AutoClosureExpr::Kind::None:
2034+
case AutoClosureExpr::Kind::AsyncLet:
20342035
break;
20352036

20362037
case AutoClosureExpr::Kind::SingleCurryThunk: {

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,8 +447,15 @@ bool SILDeclRef::isTransparent() const {
447447

448448
if (hasAutoClosureExpr()) {
449449
auto *ace = getAutoClosureExpr();
450-
if (ace->getThunkKind() == AutoClosureExpr::Kind::None)
450+
switch (ace->getThunkKind()) {
451+
case AutoClosureExpr::Kind::None:
451452
return true;
453+
454+
case AutoClosureExpr::Kind::AsyncLet:
455+
case AutoClosureExpr::Kind::DoubleCurryThunk:
456+
case AutoClosureExpr::Kind::SingleCurryThunk:
457+
break;
458+
}
452459
}
453460

454461
if (hasDecl()) {

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7900,7 +7900,9 @@ static Expr *wrapAsyncLetInitializer(
79007900
// child task.
79017901
auto closureType = FunctionType::get({ }, initializerType, extInfo);
79027902
ASTContext &ctx = dc->getASTContext();
7903-
Expr *autoclosureExpr = cs.buildAutoClosureExpr(initializer, closureType);
7903+
Expr *autoclosureExpr = cs.buildAutoClosureExpr(
7904+
initializer, closureType, /*isDefaultWrappedValue=*/false,
7905+
/*isAsyncLetWrapper=*/true);
79047906

79057907
// Call the autoclosure so that the AST types line up. SILGen will ignore the
79067908
// actual calls and translate them into a different mechanism.

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4662,7 +4662,8 @@ ConstraintSystem::isConversionEphemeral(ConversionRestrictionKind conversion,
46624662

46634663
Expr *ConstraintSystem::buildAutoClosureExpr(Expr *expr,
46644664
FunctionType *closureType,
4665-
bool isDefaultWrappedValue) {
4665+
bool isDefaultWrappedValue,
4666+
bool isAsyncLetWrapper) {
46664667
auto &Context = DC->getASTContext();
46674668
bool isInDefaultArgumentContext = false;
46684669
if (auto *init = dyn_cast<Initializer>(DC)) {
@@ -4684,6 +4685,9 @@ Expr *ConstraintSystem::buildAutoClosureExpr(Expr *expr,
46844685

46854686
closure->setParameterList(ParameterList::createEmpty(Context));
46864687

4688+
if (isAsyncLetWrapper)
4689+
closure->setThunkKind(AutoClosureExpr::Kind::AsyncLet);
4690+
46874691
Expr *result = closure;
46884692

46894693
if (!newClosureType->isEqual(closureType)) {

lib/Sema/MiscDiagnostics.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,8 +1495,16 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
14951495
const AbstractClosureExpr *CE) {
14961496
// If the closure's type was inferred to be noescape, then it doesn't
14971497
// need qualification.
1498-
return !AnyFunctionRef(const_cast<AbstractClosureExpr *>(CE))
1499-
.isKnownNoEscape();
1498+
if (AnyFunctionRef(const_cast<AbstractClosureExpr *>(CE))
1499+
.isKnownNoEscape())
1500+
return false;
1501+
1502+
if (auto autoclosure = dyn_cast<AutoClosureExpr>(CE)) {
1503+
if (autoclosure->getThunkKind() == AutoClosureExpr::Kind::AsyncLet)
1504+
return false;
1505+
}
1506+
1507+
return true;
15001508
}
15011509

15021510

lib/Sema/TypeCheckEffects.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,15 +1638,16 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
16381638
scope.enterSubFunction();
16391639
scope.resetCoverageForAutoclosureBody();
16401640

1641-
// Curry thunks aren't actually a call to the asynchronous function.
1642-
// Assume that async is covered in such contexts.
16431641
switch (E->getThunkKind()) {
16441642
case AutoClosureExpr::Kind::DoubleCurryThunk:
16451643
case AutoClosureExpr::Kind::SingleCurryThunk:
1644+
// Curry thunks aren't actually a call to the asynchronous function.
1645+
// Assume that async is covered in such contexts.
16461646
Flags.set(ContextFlags::IsAsyncCovered);
16471647
break;
16481648

16491649
case AutoClosureExpr::Kind::None:
1650+
case AutoClosureExpr::Kind::AsyncLet:
16501651
break;
16511652
}
16521653

test/Concurrency/async_let_isolation.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ actor class MyActor {
1616

1717
async let z = synchronous()
1818
// expected-error @-1{{actor-isolated instance method 'synchronous()' is unsafe to reference in code that may execute concurrently}}
19-
// FIXME: expected-error @-2{{call to method 'synchronous' in closure requires explicit use of 'self' to make capture semantics explicit}}
20-
// FIXME: expected-note @-3{{reference 'self.' explicitly}}
2119

2220
var localText = text // expected-note{{var declared here}}
2321
async let w = localText.removeLast()

0 commit comments

Comments
 (0)