Skip to content

Commit 6191425

Browse files
committed
[Concurrency] Try harder to downgrade preconcurrency errors to warnings in
Swift 5 mode. When you annotate a ValueDecl with `@preconcurrency`, the compiler should allow concurrency violations by downgrading errors in the actor isolation checker to warnings in Swift 5 mode. Previously, the actor isolation checker only checked whether the caller's context was preconcurrency when deciding to downgrade, so referencing preconcurrency declarations directly remained errors. Preconcurrency was also dropped when computing actor isolation for declarations imported from clang, which are always preconcurrency. (cherry picked from commit 57214ce)
1 parent ebb99cd commit 6191425

File tree

6 files changed

+37
-10
lines changed

6 files changed

+37
-10
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2932,12 +2932,14 @@ namespace {
29322932
// we're in an asynchronous context.
29332933
if (requiresAsync && !getDeclContext()->isAsyncContext()) {
29342934
if (calleeDecl) {
2935+
auto preconcurrency = getContextIsolation().preconcurrency() ||
2936+
calleeDecl->preconcurrency();
29352937
ctx.Diags.diagnose(
29362938
apply->getLoc(), diag::actor_isolated_call_decl,
29372939
*unsatisfiedIsolation,
29382940
calleeDecl,
29392941
getContextIsolation())
2940-
.warnUntilSwiftVersionIf(getContextIsolation().preconcurrency(), 6);
2942+
.warnUntilSwiftVersionIf(preconcurrency, 6);
29412943
calleeDecl->diagnose(diag::actor_isolated_sync_func, calleeDecl);
29422944
} else {
29432945
ctx.Diags.diagnose(
@@ -3573,7 +3575,8 @@ getIsolationFromAttributes(const Decl *decl, bool shouldDiagnose = true,
35733575
isUnsafe = true;
35743576

35753577
return ActorIsolation::forGlobalActor(
3576-
globalActorType->mapTypeOutOfContext(), isUnsafe);
3578+
globalActorType->mapTypeOutOfContext(), isUnsafe)
3579+
.withPreconcurrency(decl->preconcurrency());
35773580
}
35783581

35793582
llvm_unreachable("Forgot about an attribute?");
@@ -5446,7 +5449,8 @@ static ActorIsolation getActorIsolationForReference(
54465449
return closure->isIsolatedByPreconcurrency();
54475450
})) {
54485451
declIsolation = ActorIsolation::forGlobalActor(
5449-
declIsolation.getGlobalActor(), /*unsafe=*/false);
5452+
declIsolation.getGlobalActor(), /*unsafe=*/false)
5453+
.withPreconcurrency(declIsolation.preconcurrency());
54505454
} else {
54515455
declIsolation = ActorIsolation::forUnspecified();
54525456
}
@@ -5713,7 +5717,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
57135717
Options options = llvm::None;
57145718

57155719
// Note if the reference originates from a @preconcurrency-isolated context.
5716-
if (contextIsolation.preconcurrency())
5720+
if (contextIsolation.preconcurrency() || declIsolation.preconcurrency())
57175721
options |= Flags::Preconcurrency;
57185722

57195723
// If the declaration isn't asynchronous, promote to async.

test/ClangImporter/objc_async.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ class MyButton : NXButton {
210210
}
211211

212212
@SomeGlobalActor func testOther() {
213-
onButtonPress() // expected-error{{call to main actor-isolated instance method 'onButtonPress()' in a synchronous global actor 'SomeGlobalActor'-isolated context}}
213+
onButtonPress() // expected-warning{{call to main actor-isolated instance method 'onButtonPress()' in a synchronous global actor 'SomeGlobalActor'-isolated context}}
214214
}
215215

216216
func test() {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -I %S/Inputs/custom-modules %s -verify -strict-concurrency=complete -parse-as-library
2+
3+
// REQUIRES: objc_interop
4+
// REQUIRES: concurrency
5+
// REQUIRES: asserts
6+
7+
import Foundation
8+
import ObjCConcurrency
9+
10+
// expected-note@+1 2{{add '@MainActor' to make global function 'unsatisfiedPreconcurrencyIsolation(view:)' part of global actor 'MainActor'}}
11+
func unsatisfiedPreconcurrencyIsolation(view: MyView) {
12+
// expected-warning@+1 {{call to main actor-isolated instance method 'display()' in a synchronous nonisolated context}}
13+
view.display()
14+
15+
// expected-warning@+1 {{main actor-isolated property 'isVisible' can not be referenced from a non-isolated context}}
16+
_ = view.isVisible
17+
}

test/Concurrency/preconcurrency_typealias.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ struct Outer {
2020

2121
func test() {
2222
var _: Outer.FN = {
23-
f() // expected-complete-sns-error {{call to main actor-isolated global function 'f()' in a synchronous nonisolated context}}
23+
f() // expected-complete-sns-warning {{call to main actor-isolated global function 'f()' in a synchronous nonisolated context}}
2424
}
2525

2626
var _: FN = {
27-
f() // expected-complete-sns-error {{call to main actor-isolated global function 'f()' in a synchronous nonisolated context}}
27+
f() // expected-complete-sns-warning {{call to main actor-isolated global function 'f()' in a synchronous nonisolated context}}
2828
print("Hello")
2929
}
3030

@@ -39,11 +39,11 @@ func test() {
3939
@available(SwiftStdlib 5.1, *)
4040
func testAsync() async {
4141
var _: Outer.FN = {
42-
f() // expected-error{{call to main actor-isolated global function 'f()' in a synchronous nonisolated context}}
42+
f() // expected-warning{{call to main actor-isolated global function 'f()' in a synchronous nonisolated context}}
4343
}
4444

4545
var _: FN = {
46-
f() // expected-error{{call to main actor-isolated global function 'f()' in a synchronous nonisolated context}}
46+
f() // expected-warning{{call to main actor-isolated global function 'f()' in a synchronous nonisolated context}}
4747
print("Hello")
4848
}
4949

test/Concurrency/predates_concurrency.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func testCalls(x: X) {
9797
})
9898

9999
onMainActorAlways() // okay with minimal/targeted concurrency. Not ok with complete.
100-
// expected-complete-sns-error @-1 {{call to main actor-isolated global function 'onMainActorAlways()' in a synchronous nonisolated context}}
100+
// expected-complete-sns-warning @-1 {{call to main actor-isolated global function 'onMainActorAlways()' in a synchronous nonisolated context}}
101101

102102
// Ok with minimal/targeted concurrency, Not ok with complete.
103103
let _: () -> Void = onMainActorAlways // expected-complete-sns-warning {{converting function value of type '@MainActor () -> ()' to '() -> Void' loses global actor 'MainActor'}}

test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,4 +327,10 @@ UI_ACTOR
327327
- (void)icedMochaService:(NSObject *)mochaService generateMochaWithCompletion:(void (^)(NSObject *_Nullable ingredient1, NSObject *ingredient2, NSObject *ingredient3))completionHandler;
328328
@end
329329

330+
MAIN_ACTOR
331+
@interface MyView : NSObject
332+
- (void)display;
333+
@property(readonly) BOOL isVisible;
334+
@end
335+
330336
#pragma clang assume_nonnull end

0 commit comments

Comments
 (0)