From 08f108c23b6660685403f02996dbcbd4a1bb1a9c Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Mon, 6 Oct 2025 19:55:35 -0700 Subject: [PATCH] [concurrency] Import getters with completion handlers as nonisolated(nonsending). Specifically, this means importing getters defined via swift_async_name. This just ensures that they are treated just like any other imported objc async function with completion handler. rdar://156985950 --- lib/Sema/TypeCheckConcurrency.cpp | 11 +++-------- test/ClangImporter/objc_async.swift | 6 ++++++ .../clang-importer-sdk/usr/include/ObjCConcurrency.h | 11 +++++++++++ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index e813d4edf700d..83c46014544b5 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -6317,14 +6317,9 @@ computeDefaultInferredActorIsolation(ValueDecl *value) { // Asynchronous variants for functions imported from ObjC are // `nonisolated(nonsending)` by default. - if (value->hasClangNode()) { - if (auto *AFD = dyn_cast(value)) { - if (!isa(AFD->getDeclContext()) && - AFD->getForeignAsyncConvention()) { - return { - {ActorIsolation::forCallerIsolationInheriting(), {}}, nullptr, {}}; - } - } + if (value->hasClangNode() && value->isAsync() && + !isa(value->getDeclContext())) { + return {{ActorIsolation::forCallerIsolationInheriting(), {}}, nullptr, {}}; } // We did not find anything special, return unspecified. diff --git a/test/ClangImporter/objc_async.swift b/test/ClangImporter/objc_async.swift index 480cc9ebcf2a4..b127579ee4d71 100644 --- a/test/ClangImporter/objc_async.swift +++ b/test/ClangImporter/objc_async.swift @@ -404,3 +404,9 @@ extension CoffeeDelegate { return await self.icedMochaServiceGenerateMocha!(NSObject()) } } + +@MainActor +func testGetSendableClasses() async { + let x = ImportObjCAsyncGetter() + _ = await x.sendableClasses +} diff --git a/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h b/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h index 589d1b07185c7..4b9f851e8785a 100644 --- a/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h +++ b/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h @@ -11,6 +11,7 @@ #define NONSENDABLE __attribute__((__swift_attr__("@_nonSendable"))) #define ASSUME_NONSENDABLE_BEGIN _Pragma("clang attribute ASSUME_NONSENDABLE.push (__attribute__((swift_attr(\"@_nonSendable(_assumed)\"))), apply_to = any(objc_interface, record, enum))") #define ASSUME_NONSENDABLE_END _Pragma("clang attribute ASSUME_NONSENDABLE.pop") + #define ASYNC_NAME(NAME) __attribute__((swift_async_name(#NAME))) #else // If we take this #else, we should see minor failures of some subtests, // but not systematic failures of everything that uses this header. @@ -18,6 +19,7 @@ #define NONSENDABLE #define ASSUME_NONSENDABLE_BEGIN #define ASSUME_NONSENDABLE_END + #define ASYNC_NAME(NAME) #endif #define NS_ENUM(_type, _name) enum _name : _type _name; \ @@ -381,4 +383,13 @@ MAIN_ACTOR - (void)loadFloatOrThrowWithCompletionHandler:(void (^)(float, NSError* __nullable)) completionHandler; @end +NONSENDABLE +@interface ImportObjCAsyncGetter : NSObject + +- (void)getSendableClassesWithCompletionHandler: + (void (^SENDABLE)(NSArray *myClasses))handler + ASYNC_NAME(getter:sendableClasses()); + +@end + #pragma clang assume_nonnull end