From 0ad8dc95f4179970bd3f7695ce3ce2e201637bd1 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 6 Jan 2026 15:11:13 -0800 Subject: [PATCH] [AST] ASTPrinter: Don't attempt to print `nonisolated(nonsending)` on non-function parameters Don't look through sugar when checking whether to print `nonisolated(nonsending)` in parameter positions, because underlying types would already be marked appropriately and parameters themselves doesn't require the modifier transfer even when the sugar is stripped. Resolves: rdar://167050741 (cherry picked from commit df109f857b45fe680765a33f2d9a5d702593f31c) --- lib/AST/ASTPrinter.cpp | 13 +++--- ...lated_cross_module_with_flag_enabled.swift | 40 +++++++++++++++++++ 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 32581e6e9108c..431476fc80e26 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -3897,12 +3897,6 @@ static bool isEscaping(Type type) { return false; } -static bool isNonisolatedCaller(Type type) { - if (auto *funcTy = type->getAs()) - return funcTy->getIsolation().isNonIsolatedCaller(); - return false; -} - static void printParameterFlags(ASTPrinter &printer, const PrintOptions &options, const ParamDecl *param, @@ -4101,11 +4095,14 @@ void PrintAST::printOneParameter(const ParamDecl *param, !willUseTypeReprPrinting(TheTypeLoc, CurrentType, Options)) { auto type = TheTypeLoc.getType(); + bool isCallerIsolated = false; + if (auto *funcTy = dyn_cast(interfaceTy.getPointer())) + isCallerIsolated = funcTy->getIsolation().isNonIsolatedCaller(); + // We suppress `@escaping` on enum element parameters because it cannot // be written explicitly in this position. printParameterFlags(Printer, Options, param, paramFlags, - isEscaping(type) && !isEnumElement, - isNonisolatedCaller(interfaceTy)); + isEscaping(type) && !isEnumElement, isCallerIsolated); } printTypeLoc(TheTypeLoc, getNonRecursiveOptions(param)); diff --git a/test/Concurrency/attr_execution/nonisolated_cross_module_with_flag_enabled.swift b/test/Concurrency/attr_execution/nonisolated_cross_module_with_flag_enabled.swift index 23561e8427d7e..6f49787ee39f3 100644 --- a/test/Concurrency/attr_execution/nonisolated_cross_module_with_flag_enabled.swift +++ b/test/Concurrency/attr_execution/nonisolated_cross_module_with_flag_enabled.swift @@ -77,6 +77,23 @@ nonisolated public class NoinsolatedClassTest { public func test() async {} } +// CHECK: public typealias F = nonisolated(nonsending) () async -> Swift.Void +public typealias F = () async -> Void +// CHECK: public typealias G = nonisolated(nonsending) () async -> T +public typealias G = () async -> T + +// CHECK: public func testTypeAlias(_: @escaping A.F) +public func testTypeAlias(_: @escaping F) {} + +// CHECK: public struct TestGenericTypeAlias { +// CHECK: public subscript(_: nonisolated(nonsending) () async -> U) -> Swift.Bool { +// CHECK: get +// CHECK: } +// CHECK: } +public struct TestGenericTypeAlias { + public subscript(_: G) -> Bool { false } +} + //--- Client.swift import A @@ -141,3 +158,26 @@ func testWitnessWithNonisolated(t: WitnessTest) async { func testNonisolatedClass(t: NoinsolatedClassTest) async { await t.test() } + +// CHECK-LABEL: sil hidden @$s6Client18testTypeAliasParam1ty1A011TestGenericcD0V_tF : $@convention(thin) (@in_guaranteed TestGenericTypeAlias) -> () +// CHECK: [[CLOSURE:%.*]] = function_ref @$s6Client18testTypeAliasParam1ty1A011TestGenericcD0V_tFyyYaYCcfU_ : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> () +// CHECK: [[THICK_CLOSURE:%.*]] = thin_to_thick_function [[CLOSURE]] to $@async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> () +// CHECK: [[TEST_TYPEALIAS:%.*]] = function_ref @$s1A13testTypeAliasyyyyYaYCcF : $@convention(thin) (@guaranteed @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> ()) -> () +// CHECK: apply [[TEST_TYPEALIAS]]([[THICK_CLOSURE]]) : $@convention(thin) (@guaranteed @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> ()) -> () +// CHECK: [[CLOSURE_2:%.*]] = convert_function {{.*}} to $@noescape @async @callee_guaranteed @substituted <τ_0_0> (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> @out τ_0_0 for +// CHECK: [[SUBSCRIPT:%.*]] = function_ref @$s1A20TestGenericTypeAliasVySbxyYaYCXEcluig : $@convention(method) <τ_0_0> (@guaranteed @noescape @async @callee_guaranteed @substituted <τ_0_0> (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> @out τ_0_0 for <τ_0_0>, @in_guaranteed TestGenericTypeAlias) -> Bool +// CHECK: apply [[SUBSCRIPT]]([[CLOSURE_2]], {{.*}}) : $@convention(method) <τ_0_0> (@guaranteed @noescape @async @callee_guaranteed @substituted <τ_0_0> (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> @out τ_0_0 for <τ_0_0>, @in_guaranteed TestGenericTypeAlias) -> Bool +// CHECK: } // end sil function '$s6Client18testTypeAliasParam1ty1A011TestGenericcD0V_tF' +func testTypeAliasParam(t: TestGenericTypeAlias) { + // CHECK: closure #1 in testTypeAliasParam(t:) + // CHECK: Isolation: caller_isolation_inheriting + // CHECK-LABEL: sil private @$s6Client18testTypeAliasParam1ty1A011TestGenericcD0V_tFyyYaYCcfU_ : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> () + // CHECK: } // end sil function '$s6Client18testTypeAliasParam1ty1A011TestGenericcD0V_tFyyYaYCcfU_' + testTypeAlias { } + + // CHECK: // closure #2 in testTypeAliasParam(t:) + // CHECK: // Isolation: caller_isolation_inheriting + // CHECK-LABEL: sil private @$s6Client18testTypeAliasParam1ty1A011TestGenericcD0V_tFSiyYaYCXEfU0_ : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> Int + // CHECK: } // end sil function '$s6Client18testTypeAliasParam1ty1A011TestGenericcD0V_tFSiyYaYCXEfU0_' + _ = t[{ 42 }] +}