Skip to content

Commit 88e37b2

Browse files
committed
[Concurrency] Downgrade missing 'await' errors to warnings when referencing
preconcurrency declarations.
1 parent e6ec9b0 commit 88e37b2

File tree

3 files changed

+30
-7
lines changed

3 files changed

+30
-7
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,22 @@ class AbstractFunction {
365365
return decomposeFunction(fn);
366366
}
367367

368+
bool isPreconcurrency() const {
369+
switch (getKind()) {
370+
case Kind::Closure: {
371+
auto *closure = dyn_cast<ClosureExpr>(getClosure());
372+
return closure && closure->isIsolatedByPreconcurrency();
373+
}
374+
375+
case Kind::Function:
376+
return getActorIsolation(getFunction()).preconcurrency();
377+
378+
case Kind::Opaque:
379+
case Kind::Parameter:
380+
return false;
381+
}
382+
}
383+
368384
static AbstractFunction decomposeFunction(Expr *fn) {
369385
assert(fn->getValueProvidingExpr() == fn);
370386

@@ -1054,8 +1070,11 @@ class ApplyClassifier {
10541070
}
10551071

10561072
/// Whether a missing 'await' error on accessing an async var should be
1057-
/// downgraded to a warning. This is only the case for synchronous access
1058-
/// to isolated global or static 'let' variables.
1073+
/// downgraded to a warning.
1074+
///
1075+
/// Missing 'await' errors are downgraded for synchronous access to isolated
1076+
/// global or static 'let' variables, which was previously accepted in
1077+
/// compiler versions before 5.10, or for declarations marked preconcurrency.
10591078
bool downgradeAsyncAccessToWarning(Decl *decl) {
10601079
if (auto *var = dyn_cast<VarDecl>(decl)) {
10611080
ActorReferenceResult::Options options = llvm::None;
@@ -1067,7 +1086,7 @@ class ApplyClassifier {
10671086
}
10681087
}
10691088

1070-
return false;
1089+
return decl->preconcurrency();
10711090
}
10721091

10731092
Classification classifyLookup(LookupExpr *E) {
@@ -1192,6 +1211,10 @@ class ApplyClassifier {
11921211
ctx, E->isImplicitlyAsync().has_value(), E->implicitlyThrows(),
11931212
PotentialEffectReason::forApply());
11941213

1214+
// Downgrade missing 'await' errors for preconcurrency references.
1215+
result.setDowngradeToWarning(
1216+
result.hasAsync() && fnRef.isPreconcurrency());
1217+
11951218
auto classifyApplyEffect = [&](EffectKind kind) {
11961219
if (!fnType->hasEffect(kind) &&
11971220
!(kind == EffectKind::Async && E->isImplicitlyAsync()) &&

test/Concurrency/global_actor_from_ordinary_context.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class Sub: Super {
154154

155155
func g2() {
156156
Task.detached {
157-
self.f() // expected-error{{expression is 'async' but is not marked with 'await'}}
157+
self.f() // expected-warning{{expression is 'async' but is not marked with 'await'}}
158158
// expected-note@-1{{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
159159
}
160160
}

test/Concurrency/predates_concurrency.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,14 @@ func testCalls(x: X) {
108108
}
109109

110110
func testCallsWithAsync() async {
111-
onMainActorAlways() // expected-error{{expression is 'async' but is not marked with 'await'}}
111+
onMainActorAlways() // expected-warning{{expression is 'async' but is not marked with 'await'}}
112112
// expected-note@-1{{calls to global function 'onMainActorAlways()' from outside of its actor context are implicitly asynchronous}}
113113

114114
let _: () -> Void = onMainActorAlways // expected-warning {{converting function value of type '@MainActor () -> ()' to '() -> Void' loses global actor 'MainActor'}}
115115

116-
let c = MyModelClass() // expected-error{{expression is 'async' but is not marked with 'await'}}
116+
let c = MyModelClass() // expected-warning{{expression is 'async' but is not marked with 'await'}}
117117
// expected-note@-1{{calls to initializer 'init()' from outside of its actor context are implicitly asynchronous}}
118-
c.f() // expected-error{{expression is 'async' but is not marked with 'await'}}
118+
c.f() // expected-warning{{expression is 'async' but is not marked with 'await'}}
119119
// expected-note@-1{{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
120120
}
121121

0 commit comments

Comments
 (0)