Skip to content

Commit 63bd41d

Browse files
committed
[sending] Enable sending whenever region isolation is enabled and make SE-0430 an upcoming feature.
I also added support for expressing suppressable upcoming features. rdar://128216574 (cherry picked from commit 20a3589)
1 parent a6991b6 commit 63bd41d

16 files changed

+248
-85
lines changed

include/swift/Basic/Features.def

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,21 @@
6969
# endif
7070
#endif
7171

72+
// A feature that's both suppressible and upcoming.
73+
// Delegates to whichever the includer defines.
74+
#ifndef SUPPRESSIBLE_UPCOMING_FEATURE
75+
# if defined(SUPPRESSIBLE_UPCOMING_FEATURE) && \
76+
defined(UPCOMING_FEATURE)
77+
# error ambiguous defines when including Features.def
78+
# elif defined(SUPPRESSIBLE_LANGUAGE_FEATURE)
79+
# define SUPPRESSIBLE_UPCOMING_FEATURE(FeatureName, SENumber, Version) \
80+
SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, #FeatureName)
81+
# else
82+
# define SUPPRESSIBLE_UPCOMING_FEATURE(FeatureName, SENumber, Version) \
83+
UPCOMING_FEATURE(FeatureName, SENumber, Version)
84+
# endif
85+
#endif
86+
7287
#ifndef SUPPRESSIBLE_LANGUAGE_FEATURE
7388
# define SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
7489
LANGUAGE_FEATURE(FeatureName, SENumber, Description)
@@ -198,6 +213,8 @@ UPCOMING_FEATURE(DynamicActorIsolation, 423, 6)
198213
UPCOMING_FEATURE(NonfrozenEnumExhaustivity, 192, 6)
199214
UPCOMING_FEATURE(GlobalActorIsolatedTypesUsability, 0434, 6)
200215
UPCOMING_FEATURE(BorrowingSwitch, 432, 6)
216+
UPCOMING_FEATURE(TransferringArgsAndResults, 430, 6)
217+
SUPPRESSIBLE_UPCOMING_FEATURE(SendingArgsAndResults, 430, 6)
201218

202219
// Swift 7
203220
UPCOMING_FEATURE(ExistentialAny, 335, 7)
@@ -349,16 +366,6 @@ EXPERIMENTAL_FEATURE(FixedArrays, true)
349366
// Group Main Actor Isolation Errors by Scope
350367
EXPERIMENTAL_FEATURE(GroupActorErrors, true)
351368

352-
// Allow for the 'transferring' keyword to be applied to arguments and results.
353-
//
354-
// Enables SendingArgsAndResults as well. After parsing, we just represent this
355-
// as 'sendable' implying that since both are always enabled together, this
356-
// doesn't need to be suppressed.
357-
EXPERIMENTAL_FEATURE(TransferringArgsAndResults, true)
358-
359-
// Allow for the 'sending' keyword to be applied to arguments and results.
360-
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(SendingArgsAndResults, true)
361-
362369
// Enable explicit isolation of closures.
363370
EXPERIMENTAL_FEATURE(ClosureIsolation, true)
364371

@@ -387,5 +394,6 @@ EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE(DebugDescriptionMacro, true)
387394
#undef CONDITIONALLY_SUPPRESSIBLE_EXPERIMENTAL_FEATURE
388395
#undef CONDITIONALLY_SUPPRESSIBLE_LANGUAGE_FEATURE
389396
#undef SUPPRESSIBLE_EXPERIMENTAL_FEATURE
397+
#undef SUPPRESSIBLE_UPCOMING_FEATURE
390398
#undef SUPPRESSIBLE_LANGUAGE_FEATURE
391399
#undef LANGUAGE_FEATURE

include/swift/Option/FrontendOptions.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,16 @@ def disable_strict_concurrency_region_based_isolation : Flag<["-"],
13421342
HelpText<"Disable region based isolation when running with strict concurrency enabled. Only enabled with asserts">,
13431343
Flags<[HelpHidden]>;
13441344

1345+
def disable_transferring_args_and_results_with_region_isolation : Flag<["-"],
1346+
"disable-transferring-args-and-results-with-region-based-isolation">,
1347+
HelpText<"Disable transferring args and results when region based isolation is enabled. Only enabled with asserts">,
1348+
Flags<[HelpHidden]>;
1349+
1350+
def disable_sending_args_and_results_with_region_isolation : Flag<["-"],
1351+
"disable-sending-args-and-results-with-region-based-isolation">,
1352+
HelpText<"Disable sending args and results when region based isolation is enabled. Only enabled with asserts">,
1353+
Flags<[HelpHidden]>;
1354+
13451355
def no_scanner_module_validation: Flag<["-"], "no-scanner-module-validation">,
13461356
HelpText<"Do not validate binary modules in scanner and delegate the validation to swift-frontend">;
13471357
def module_load_mode: Separate<["-"], "module-load-mode">,

lib/ASTGen/Sources/ASTGen/SourceFile.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ extension Parser.ExperimentalFeatures {
6060
mapFeature(.DoExpressions, to: .doExpressions)
6161
mapFeature(.NonescapableTypes, to: .nonescapableTypes)
6262
mapFeature(.TransferringArgsAndResults, to: .transferringArgsAndResults)
63+
mapFeature(.SendingArgsAndResults, to: .sendingArgsAndResults)
6364
}
6465
}
6566

lib/DriverTool/sil_opt_main.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,17 @@ struct SILOptOptions {
539539
llvm::cl::opt<bool>(
540540
"disable-region-based-isolation-with-strict-concurrency",
541541
llvm::cl::init(false));
542+
543+
llvm::cl::opt<bool>
544+
DisableTransferringArgsAndResultsWithRegionBasedIsolation = llvm::cl::opt<
545+
bool>(
546+
"disable-transferring-args-and-results-with-region-based-isolation",
547+
llvm::cl::init(false));
548+
549+
llvm::cl::opt<bool> DisableSendingArgsAndResultsWithRegionBasedIsolation =
550+
llvm::cl::opt<bool>(
551+
"disable-sending-args-and-results-with-region-based-isolation",
552+
llvm::cl::init(false));
542553
};
543554

544555
/// Regular expression corresponding to the value given in one of the
@@ -712,6 +723,14 @@ int sil_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
712723
}
713724
}
714725

726+
if (Invocation.getLangOptions().hasFeature(Feature::RegionBasedIsolation)) {
727+
if (!options.DisableTransferringArgsAndResultsWithRegionBasedIsolation)
728+
Invocation.getLangOptions().enableFeature(
729+
Feature::TransferringArgsAndResults);
730+
if (!options.DisableSendingArgsAndResultsWithRegionBasedIsolation)
731+
Invocation.getLangOptions().enableFeature(Feature::SendingArgsAndResults);
732+
}
733+
715734
if (Invocation.getLangOptions().hasFeature(
716735
Feature::TransferringArgsAndResults)) {
717736
Invocation.getLangOptions().enableFeature(Feature::SendingArgsAndResults);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,23 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
10691069
Opts.enableFeature(Feature::RegionBasedIsolation);
10701070
}
10711071

1072+
// Enable TransferringArgsAndResults/SendingArgsAndResults whenever
1073+
// RegionIsolation is enabled.
1074+
if (Opts.hasFeature(Feature::RegionBasedIsolation)) {
1075+
bool enableTransferringArgsAndResults = true;
1076+
bool enableSendingArgsAndResults = true;
1077+
#ifndef NDEBUG
1078+
enableTransferringArgsAndResults = !Args.hasArg(
1079+
OPT_disable_transferring_args_and_results_with_region_isolation);
1080+
enableSendingArgsAndResults = !Args.hasArg(
1081+
OPT_disable_sending_args_and_results_with_region_isolation);
1082+
#endif
1083+
if (enableTransferringArgsAndResults)
1084+
Opts.enableFeature(Feature::TransferringArgsAndResults);
1085+
if (enableSendingArgsAndResults)
1086+
Opts.enableFeature(Feature::SendingArgsAndResults);
1087+
}
1088+
10721089
// Enable SendingArgsAndResults whenever TransferringArgsAndResults is
10731090
// enabled.
10741091
//

test/Concurrency/async_let_isolation.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -disable-region-based-isolation-with-strict-concurrency
2-
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=targeted -disable-region-based-isolation-with-strict-concurrency
3-
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -disable-region-based-isolation-with-strict-concurrency
1+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -verify-additional-prefix without-transferring-
2+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=targeted -verify-additional-prefix without-transferring-
3+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -disable-region-based-isolation-with-strict-concurrency -verify-additional-prefix without-transferring- -disable-transferring-args-and-results-with-region-based-isolation -disable-sending-args-and-results-with-region-based-isolation
4+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -disable-transferring-args-and-results-with-region-based-isolation -disable-sending-args-and-results-with-region-based-isolation -verify-additional-prefix without-transferring-
45
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete
56

67
// REQUIRES: concurrency
@@ -21,7 +22,7 @@ actor MyActor {
2122
async let z = synchronous()
2223

2324
var localText = text
24-
async let w = localText.removeLast() // expected-warning{{mutation of captured var 'localText' in concurrently-executing code}}
25+
async let w = localText.removeLast() // expected-without-transferring-warning {{mutation of captured var 'localText' in concurrently-executing code}}
2526

2627
_ = await x
2728
_ = await y

test/Concurrency/global_actor_function_types.swift

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1-
// RUN: %target-typecheck-verify-swift -disable-availability-checking
2-
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify
3-
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=targeted
4-
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -verify-additional-prefix complete-tns-
5-
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -enable-upcoming-feature RegionBasedIsolation -verify-additional-prefix complete-tns-
1+
// Typecheck.
2+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -verify-additional-prefix without-transferring-
3+
4+
// Emit SIL with minimal strict concurrency.
5+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -verify-additional-prefix without-transferring-
6+
7+
// Emit SIL with targeted concurrency.
8+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=targeted -verify-additional-prefix without-transferring-
9+
10+
// Emit SIL with strict concurrency + region based isolation but without transferring.
11+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -verify-additional-prefix complete-tns- -verify-additional-prefix without-transferring- -disable-transferring-args-and-results-with-region-based-isolation -disable-sending-args-and-results-with-region-based-isolation
12+
13+
// Emit SIL with strict concurrency + region based isolation + transferring
14+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -verify-additional-prefix complete-tns-
615

716
// REQUIRES: concurrency
817
// REQUIRES: asserts
@@ -323,7 +332,7 @@ func stripActor(_ expr: @Sendable @autoclosure () -> (() -> ())) async {
323332

324333
// NOTE: this warning is correct, but is only being caught by TypeCheckConcurrency's extra check.
325334
@MainActor func exampleWhereConstraintSolverHasWrongDeclContext_v2() async -> Int {
326-
async let a: () = noActor(mainActorFn) // expected-warning {{converting function value of type '@MainActor () -> ()' to '() -> ()' loses global actor 'MainActor'}}
335+
async let a: () = noActor(mainActorFn) // expected-without-transferring-warning {{converting function value of type '@MainActor () -> ()' to '() -> ()' loses global actor 'MainActor'}}
327336
await a
328337
}
329338

test/Concurrency/issue-57376.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
// RUN: %target-swift-frontend -disable-availability-checking -strict-concurrency=targeted %s -emit-sil -o /dev/null -verify -verify-additional-prefix targeted-and-complete-
2-
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -verify-additional-prefix targeted-and-complete-
32

43
// NOTE: We test separately with region isolation and region isolation +
54
// sending args and results since the semantics when sending args and
65
// results are enabled is different since async let in such a case takes a
76
// non-Sendable closure whose captures are transferred in while without it, we
87
// leave the async let closure as sendable and use sema level checking.
9-
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -enable-upcoming-feature RegionBasedIsolation -verify-additional-prefix tns- -verify-additional-prefix no-transferring-tns-
10-
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -enable-upcoming-feature RegionBasedIsolation -enable-experimental-feature TransferringArgsAndResults -verify-additional-prefix tns- -verify-additional-prefix transferring-tns-
8+
9+
// No transferring.
10+
//
11+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -verify-additional-prefix tns- -verify-additional-prefix no-transferring-tns- -disable-transferring-args-and-results-with-region-based-isolation -disable-sending-args-and-results-with-region-based-isolation
12+
13+
// With transferring.
14+
//
15+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -verify-additional-prefix tns- -verify-additional-prefix transferring-tns-
1116

1217
// REQUIRES: concurrency
1318
// REQUIRES: asserts
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -enable-upcoming-feature SendingArgsAndResults -swift-version 5 -enable-library-evolution -module-name test -emit-module -o %t/test.swiftmodule -emit-module-interface-path - %s | %FileCheck %s
4+
5+
public class NonSendableKlass {}
6+
7+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
8+
// CHECK-NEXT: public func transferArgTest(_ x: sending test.NonSendableKlass)
9+
// CHECK-NEXT: #else
10+
// CHECK-NEXT: public func transferArgTest(_ x: test.NonSendableKlass)
11+
// CHECK-NEXT: #endif
12+
public func transferArgTest(_ x: sending NonSendableKlass) {}
13+
14+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
15+
// CHECK-NEXT: public func transferResultTest() -> sending test.NonSendableKlass
16+
// CHECK-NEXT: #else
17+
// CHECK-NEXT: public func transferResultTest() -> test.NonSendableKlass
18+
// CHECK-NEXT: #endif
19+
public func transferResultTest() -> sending NonSendableKlass { fatalError() }
20+
21+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
22+
// CHECK-NEXT: public func transferArgAndResultTest(_ x: test.NonSendableKlass, _ y: sending test.NonSendableKlass, _ z: test.NonSendableKlass) -> sending test.NonSendableKlass
23+
// CHECK-NEXT: #else
24+
// CHECK-NEXT: public func transferArgAndResultTest(_ x: test.NonSendableKlass, _ y: test.NonSendableKlass, _ z: test.NonSendableKlass) -> test.NonSendableKlass
25+
// CHECK-NEXT: #endif
26+
public func transferArgAndResultTest(_ x: NonSendableKlass, _ y: sending NonSendableKlass, _ z: NonSendableKlass) -> sending NonSendableKlass { fatalError() }
27+
28+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
29+
// CHECK-NEXT: public func argEmbeddedInType(_ fn: (sending test.NonSendableKlass) -> ())
30+
// CHECK-NEXT: #else
31+
// CHECK-NEXT: public func argEmbeddedInType(_ fn: (test.NonSendableKlass) -> ())
32+
// CHECK-NEXT: #endif
33+
public func argEmbeddedInType(_ fn: (sending NonSendableKlass) -> ()) {}
34+
35+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
36+
// CHECK-NEXT: public func resultEmbeddedInType(_ fn: () -> sending test.NonSendableKlass)
37+
// CHECK-NEXT: #else
38+
// CHECK-NEXT: public func resultEmbeddedInType(_ fn: () -> test.NonSendableKlass)
39+
// CHECK-NEXT: #endif
40+
public func resultEmbeddedInType(_ fn: () -> sending NonSendableKlass) {}
41+
42+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
43+
// CHECK-NEXT: public func argAndResultEmbeddedInType(_ fn: (test.NonSendableKlass, sending test.NonSendableKlass, test.NonSendableKlass) -> sending test.NonSendableKlass)
44+
// CHECK-NEXT: #else
45+
// CHECK-NEXT: public func argAndResultEmbeddedInType(_ fn: (test.NonSendableKlass, test.NonSendableKlass, test.NonSendableKlass) -> test.NonSendableKlass)
46+
// CHECK-NEXT: #endif
47+
public func argAndResultEmbeddedInType(_ fn: (NonSendableKlass, sending NonSendableKlass, NonSendableKlass) -> sending NonSendableKlass) {}
48+
49+
public class TestInKlass {
50+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
51+
// CHECK-NEXT: public func testKlassArg(_ x: sending test.NonSendableKlass)
52+
// CHECK-NEXT: #else
53+
// CHECK-NEXT: public func testKlassArg(_ x: test.NonSendableKlass)
54+
// CHECK-NEXT: #endif
55+
public func testKlassArg(_ x: sending NonSendableKlass) { fatalError() }
56+
57+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
58+
// CHECK-NEXT: public func testKlassResult() -> sending test.NonSendableKlass
59+
// CHECK-NEXT: #else
60+
// CHECK-NEXT: public func testKlassResult() -> test.NonSendableKlass
61+
// CHECK-NEXT: #endif
62+
public func testKlassResult() -> sending NonSendableKlass { fatalError() }
63+
64+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
65+
// CHECK-NEXT: public func testKlassArgAndResult(_ x: test.NonSendableKlass, _ y: sending test.NonSendableKlass, z: test.NonSendableKlass) -> sending test.NonSendableKlass
66+
// CHECK-NEXT: #else
67+
// CHECK-NEXT: public func testKlassArgAndResult(_ x: test.NonSendableKlass, _ y: test.NonSendableKlass, z: test.NonSendableKlass) -> test.NonSendableKlass
68+
// CHECK-NEXT: #endif
69+
public func testKlassArgAndResult(_ x: NonSendableKlass, _ y: sending NonSendableKlass, z: NonSendableKlass) -> sending NonSendableKlass { fatalError() }
70+
}
71+
72+
public struct TestInStruct {
73+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
74+
// CHECK-NEXT: public func testKlassArg(_ x: sending test.NonSendableKlass)
75+
// CHECK-NEXT: #else
76+
// CHECK-NEXT: public func testKlassArg(_ x: test.NonSendableKlass)
77+
// CHECK-NEXT: #endif
78+
public func testKlassArg(_ x: sending NonSendableKlass) { fatalError() }
79+
80+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
81+
// CHECK-NEXT: public func testKlassResult() -> sending test.NonSendableKlass
82+
// CHECK-NEXT: #else
83+
// CHECK-NEXT: public func testKlassResult() -> test.NonSendableKlass
84+
// CHECK-NEXT: #endif
85+
public func testKlassResult() -> sending NonSendableKlass { fatalError() }
86+
87+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
88+
// CHECK-NEXT: public func testKlassArgAndResult(_ x: test.NonSendableKlass, _ y: sending test.NonSendableKlass, z: test.NonSendableKlass) -> sending test.NonSendableKlass
89+
// CHECK-NEXT: #else
90+
// CHECK-NEXT: public func testKlassArgAndResult(_ x: test.NonSendableKlass, _ y: test.NonSendableKlass, z: test.NonSendableKlass) -> test.NonSendableKlass
91+
// CHECK-NEXT: #endif
92+
public func testKlassArgAndResult(_ x: NonSendableKlass, _ y: sending NonSendableKlass, z: NonSendableKlass) -> sending NonSendableKlass { fatalError() }
93+
}

test/Concurrency/transfernonsendable.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -transfer-non-sendable -enable-upcoming-feature RegionBasedIsolation -enable-experimental-feature TransferringArgsAndResults -strict-concurrency=complete %s -o /dev/null -verify
1+
// RUN: %target-sil-opt -transfer-non-sendable -enable-upcoming-feature RegionBasedIsolation -enable-upcoming-feature TransferringArgsAndResults -strict-concurrency=complete %s -o /dev/null -verify
22

33
// REQUIRES: concurrency
44
// REQUIRES: asserts

0 commit comments

Comments
 (0)