From 6561476059148622031a1387deb823d812c0e250 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 19 May 2025 15:25:06 -0700 Subject: [PATCH] [Concurrency] Infer `@preconcurrency @MainActor` in default main actor mode for language modes < 6 `@MainActor` errors are hard errors, even in minimal concurrency checking in Swift 5 mode. When users set the default isolation to main actor, we should infer `@preconcurrency @MainActor` in language modes < 6 to get the right diagnostic staging behavior. Resolves: rdar://151029517 --- lib/Sema/TypeCheckConcurrency.cpp | 9 ++++++-- .../assume_mainactor_typechecker_errors.swift | 22 ++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index fb10cf82419e4..9cfa1bab09005 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -5818,8 +5818,13 @@ computeDefaultInferredActorIsolation(ValueDecl *value) { if (isa(value) || isa(value) || isa(value) || isa(value) || isa(value)) { - return { - {{ActorIsolation::forGlobalActor(globalActor), {}}, nullptr, {}}}; + // Preconcurrency here is used to stage the diagnostics + // when users select `@MainActor` default isolation with + // non-strict concurrency modes (pre Swift 6). + auto isolation = + ActorIsolation::forGlobalActor(globalActor) + .withPreconcurrency(!ctx.LangOpts.isSwiftVersionAtLeast(6)); + return {{{isolation, {}}, nullptr, {}}}; } } diff --git a/test/Concurrency/assume_mainactor_typechecker_errors.swift b/test/Concurrency/assume_mainactor_typechecker_errors.swift index 7ca7f42af09c6..7baa104171024 100644 --- a/test/Concurrency/assume_mainactor_typechecker_errors.swift +++ b/test/Concurrency/assume_mainactor_typechecker_errors.swift @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend -swift-version 6 -emit-sil -default-isolation MainActor %s -verify +// RUN: %target-swift-frontend -swift-version 5 -emit-sil -default-isolation MainActor %s -verify -verify-additional-prefix swift5- +// RUN: %target-swift-frontend -swift-version 6 -emit-sil -default-isolation MainActor %s -verify -verify-additional-prefix swift6- // READ THIS! This test is meant to check the specific isolation when // `-default-isolation` is set to `MainActor` in combination with validating @@ -7,13 +8,16 @@ // Fake Sendable Data class SendableData : @unchecked Sendable {} +// expected-swift5-note@-1 {{calls to initializer 'init()' from outside of its actor context are implicitly asynchronous}} nonisolated func getDataFromSocket() -> SendableData { SendableData() } +// expected-swift5-warning@-1 {{call to main actor-isolated initializer 'init()' in a synchronous nonisolated context; this is an error in the Swift 6 language mode}} -class Klass { // expected-note 3 {{}} +class Klass { // expected-swift5-note 3 {{}} expected-swift6-note 3 {{}} let s = SendableData() + // expected-swift5-note@-1 2 {{}} - init() { s = SendableData() } + init() { s = SendableData() } // expected-swift5-error {{immutable value 'self.s' may only be initialized once}} init(_ s: SendableData) {} func doSomething() {} @@ -50,9 +54,15 @@ func unspecifiedFunctionTest2() async { nonisolated func nonisolatedFunctionTest() async { let k = await StructContainingKlass() - await unspecifiedAsync(k.k) // expected-error {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} - await nonisolatedAsync(k.k) // expected-error {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} - await mainActorAsync(k.k) // expected-error {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} + await unspecifiedAsync(k.k) + // expected-swift5-warning@-1 {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} + // expected-swift6-error@-2 {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} + await nonisolatedAsync(k.k) + // expected-swift5-warning@-1 {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} + // expected-swift6-error@-2 {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} + await mainActorAsync(k.k) + // expected-swift5-warning@-1 {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} + // expected-swift6-error@-2 {{non-sendable type 'Klass' of property 'k' cannot exit main actor-isolated context}} } func testTask() async {