Skip to content

Commit c3ea303

Browse files
committed
[AST] Fix printing of nonisolated(nonsending) in parameter type positions
Printing shouldn't rely on parameter declaration bit because it only works in cases when there is an explicit `nonisolated(nonsending)` modifier on the type. Always print `nonisolated(nonsending)` before `sending`, `@escaping` and other declaration attributes/modifiers to avoid parsing issues. Resolves: rdar://164267736
1 parent 22ca80e commit c3ea303

File tree

3 files changed

+56
-17
lines changed

3 files changed

+56
-17
lines changed

include/swift/AST/PrintOptions.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,11 @@ struct ShouldPrintChecker {
127127

128128
/// Type-printing options which should only be applied to the outermost
129129
/// type.
130-
enum class NonRecursivePrintOption: uint32_t {
130+
enum class NonRecursivePrintOption : uint32_t {
131131
/// Print `Optional<T>` as `T!`.
132132
ImplicitlyUnwrappedOptional = 1 << 0,
133+
/// Avoid printing `nonisolated(nonsending)` modifier.
134+
SkipNonisolatedNonsending = 1 << 1,
133135
};
134136
using NonRecursivePrintOptions = OptionSet<NonRecursivePrintOption>;
135137

lib/AST/ASTPrinter.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ static NonRecursivePrintOptions getNonRecursiveOptions(const ValueDecl *D) {
229229
NonRecursivePrintOptions options;
230230
if (D->isImplicitlyUnwrappedOptional())
231231
options |= NonRecursivePrintOption::ImplicitlyUnwrappedOptional;
232+
if (isa<ParamDecl>(D))
233+
options |= NonRecursivePrintOption::SkipNonisolatedNonsending;
232234
return options;
233235
}
234236

@@ -3895,6 +3897,12 @@ static bool isEscaping(Type type) {
38953897
return false;
38963898
}
38973899

3900+
static bool isNonisolatedCaller(Type type) {
3901+
if (auto *funcTy = type->getAs<AnyFunctionType>())
3902+
return funcTy->getIsolation().isNonIsolatedCaller();
3903+
return false;
3904+
}
3905+
38983906
static void printParameterFlags(ASTPrinter &printer,
38993907
const PrintOptions &options,
39003908
const ParamDecl *param,
@@ -4077,17 +4085,6 @@ void PrintAST::printOneParameter(const ParamDecl *param,
40774085

40784086
auto interfaceTy = param->getInterfaceType();
40794087

4080-
// If type of this parameter is isolated to a caller, let's
4081-
// strip the isolation from the type to avoid printing it as
4082-
// part of the function type because that would break ordering
4083-
// between specifiers and attributes.
4084-
if (param->isCallerIsolated()) {
4085-
if (auto *funcTy = dyn_cast<AnyFunctionType>(interfaceTy.getPointer())) {
4086-
interfaceTy =
4087-
funcTy->withIsolation(FunctionTypeIsolation::forNonIsolated());
4088-
}
4089-
}
4090-
40914088
TypeLoc TheTypeLoc;
40924089
if (auto *repr = param->getTypeRepr()) {
40934090
TheTypeLoc = TypeLoc(repr, interfaceTy);
@@ -4108,7 +4105,7 @@ void PrintAST::printOneParameter(const ParamDecl *param,
41084105
// be written explicitly in this position.
41094106
printParameterFlags(Printer, Options, param, paramFlags,
41104107
isEscaping(type) && !isEnumElement,
4111-
param->isCallerIsolated());
4108+
isNonisolatedCaller(interfaceTy));
41124109
}
41134110

41144111
printTypeLoc(TheTypeLoc, getNonRecursiveOptions(param));
@@ -6629,7 +6626,8 @@ class TypePrinter : public TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
66296626
visit(staticSelfT);
66306627
}
66316628

6632-
void printFunctionExtInfo(AnyFunctionType *fnType) {
6629+
void printFunctionExtInfo(AnyFunctionType *fnType,
6630+
NonRecursivePrintOptions nrOptions) {
66336631
if (!fnType->hasExtInfo()) {
66346632
Printer << "@_NO_EXTINFO ";
66356633
return;
@@ -6686,6 +6684,9 @@ class TypePrinter : public TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
66866684
break;
66876685

66886686
case FunctionTypeIsolation::Kind::NonIsolatedNonsending:
6687+
if (nrOptions & NonRecursivePrintOption::SkipNonisolatedNonsending)
6688+
break;
6689+
66896690
Printer << "nonisolated(nonsending) ";
66906691
break;
66916692
}
@@ -6938,7 +6939,7 @@ class TypePrinter : public TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
69386939
Printer.printStructurePost(PrintStructureKind::FunctionType);
69396940
};
69406941

6941-
printFunctionExtInfo(T);
6942+
printFunctionExtInfo(T, nrOptions);
69426943

69436944
// If we're stripping argument labels from types, do it when printing.
69446945
visitAnyFunctionTypeParams(T->getParams(), /*printLabels*/ false,
@@ -6996,7 +6997,7 @@ class TypePrinter : public TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
69966997
Printer.printStructurePost(PrintStructureKind::FunctionType);
69976998
};
69986999

6999-
printFunctionExtInfo(T);
7000+
printFunctionExtInfo(T, nrOptions);
70007001
printGenericSignature(T->getGenericSignature(),
70017002
PrintAST::PrintParams |
70027003
PrintAST::defaultGenericRequirementFlags(Options));

test/Concurrency/attr_execution/nonisolated_cross_module_with_flag_enabled.swift

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
// RUN: -emit-module-path %t/A.swiftmodule \
1111
// RUN: -emit-module-interface-path %t/A.swiftinterface
1212

13+
// RUN: %FileCheck %t/src/A.swift --input-file %t/A.swiftinterface
14+
1315
// RUN: %target-swift-typecheck-module-from-interface(%t/A.swiftinterface) -module-name A
1416

1517
// Build the client using module
@@ -22,9 +24,22 @@
2224

2325
//--- A.swift
2426
@MainActor
25-
2627
public final class Test {
28+
// CHECK: nonisolated(nonsending) final public func test() async
2729
public nonisolated func test() async {}
30+
31+
// CHECK: @_Concurrency.MainActor final public func compute(callback: nonisolated(nonsending) @escaping @Sendable () async -> Swift.Void)
32+
public func compute(callback: @escaping @Sendable () async -> Void) {}
33+
}
34+
35+
public struct InferenceTest {
36+
// CHECK: nonisolated(nonsending) public func infersAttr() async
37+
public func infersAttr() async {}
38+
39+
// CHECK: public func testNested(callback: @escaping (nonisolated(nonsending) @Sendable () async -> Swift.Void) -> Swift.Void)
40+
public func testNested(callback: @escaping (@Sendable () async -> Void) -> Void) {}
41+
// CHECK: public func testNested(dict: [Swift.String : (nonisolated(nonsending) () async -> Swift.Void)?])
42+
public func testNested(dict: [String: (() async -> Void)?]) {}
2843
}
2944

3045
//--- Client.swift
@@ -42,3 +57,24 @@ import A
4257
func test(t: Test) async {
4358
await t.test() // Ok
4459
}
60+
61+
// CHECK-LABEL: sil hidden @$s6Client16testWithCallback1ty1A4TestC_tYaF : $@convention(thin) @async (@guaranteed Test) -> ()
62+
// CHECK: function_ref @$s1A4TestC7compute8callbackyyyYaYbYCc_tF : $@convention(method) (@guaranteed @Sendable @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> (), @guaranteed Test) -> ()
63+
// CHECK: } // end sil function '$s6Client16testWithCallback1ty1A4TestC_tYaF'
64+
@MainActor
65+
func testWithCallback(t: Test) async {
66+
t.compute(callback: {})
67+
}
68+
69+
// CHECK-LABEL: sil hidden @$s6Client13testInference1ty1A0C4TestV_tYaF : $@convention(thin) @async (@in_guaranteed InferenceTest) -> ()
70+
// CHECK: function_ref @$s1A13InferenceTestV10infersAttryyYaF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor, @in_guaranteed InferenceTest) -> ()
71+
// CHECK: function_ref @$s1A13InferenceTestV10testNested8callbackyyyyYaYbYCXEc_tF : $@convention(method) (@guaranteed @callee_guaranteed (@guaranteed @noescape @Sendable @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor) -> ()) -> (), @in_guaranteed InferenceTest) -> ()
72+
// CHECK: function_ref @$s1A13InferenceTestV10testNested4dictySDySSyyYaYCcSgG_tF : $@convention(method) (@guaranteed Dictionary<String, Optional<nonisolated(nonsending) () async -> ()>>, @in_guaranteed InferenceTest) -> ()
73+
// CHECK: } // end sil function '$s6Client13testInference1ty1A0C4TestV_tYaF'
74+
@MainActor
75+
func testInference(t: InferenceTest) async {
76+
await t.infersAttr()
77+
78+
t.testNested { _ in }
79+
t.testNested(dict: [:])
80+
}

0 commit comments

Comments
 (0)