diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index cc2ff618ad269..507a4f1aa6f18 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -5130,6 +5130,13 @@ getIsolationFromWitnessedRequirements(ValueDecl *value) { if (dc->getSelfProtocolDecl()) return std::nullopt; + // Prevent isolation inference from requirements if the conforming type + // has an explicit `nonisolated` attribute. + if (auto *NTD = dc->getSelfNominalTypeDecl()) { + if (NTD->getAttrs().hasAttribute()) + return std::nullopt; + } + // Walk through each of the conformances in this context, collecting any // requirements that have actor isolation. auto conformances = idc->getLocalConformances( // note this diff --git a/test/Concurrency/nonisolated_rules.swift b/test/Concurrency/nonisolated_rules.swift index d252131755bf7..04d9de4a10a27 100644 --- a/test/Concurrency/nonisolated_rules.swift +++ b/test/Concurrency/nonisolated_rules.swift @@ -142,6 +142,34 @@ nonisolated class K: GloballyIsolated { } } +@MainActor +protocol GloballyIsolatedWithRequirements { + var x: NonSendable { get set } // expected-note {{property declared here}} + func test() // expected-note {{calls to instance method 'test()' from outside of its actor context are implicitly asynchronous}} +} + +nonisolated class K2: GloballyIsolatedWithRequirements { + var x: NonSendable + + func test() {} + + func testNonWitness() {} + + init(x: NonSendable) { + self.x = x // okay + test() // okay + testNonWitness() // okay + } + + func test(t: T, s: K2) { + _ = s.x // okay + _ = t.x // expected-error {{main actor-isolated property 'x' can not be referenced from a nonisolated context}} + + s.test() // okay + t.test() // expected-error {{call to main actor-isolated instance method 'test()' in a synchronous nonisolated context}} + } +} + // MARK: - Storage of non-Sendable class KlassA {