Skip to content

Commit 367e5e2

Browse files
authored
Merge pull request swiftlang#80329 from xedin/execution-caller-func-to-parameter-isolation-func
[CSSimplify] Allow conversion from caller isolated to parameter isola…
2 parents dccbcf3 + cdae26a commit 367e5e2

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

lib/Sema/CSSimplify.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -3267,6 +3267,21 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
32673267
SmallVector<AnyFunctionType::Param, 8> func2Params;
32683268
func2Params.append(func2->getParams().begin(), func2->getParams().end());
32693269

3270+
// Support conversion from `@execution(caller)` to a function type
3271+
// with an isolated parameter.
3272+
if (subKind == ConstraintKind::Subtype &&
3273+
func1->getIsolation().isNonIsolatedCaller() &&
3274+
func2->getIsolation().isParameter()) {
3275+
// `@execution(caller)` function gets an implicit isolation parameter
3276+
// introduced during SILGen and thunk is going to forward an isolation
3277+
// from the caller to it.
3278+
// Let's remove the isolated parameter from consideration, function
3279+
// types have to match on everything else.
3280+
llvm::erase_if(func2Params, [](const AnyFunctionType::Param &param) {
3281+
return param.isIsolated();
3282+
});
3283+
}
3284+
32703285
// Add a very narrow exception to SE-0110 by allowing functions that
32713286
// take multiple arguments to be passed as an argument in places
32723287
// that expect a function that takes a single tuple (of the same

test/Concurrency/attr_execution/conversions.swift

+16-1
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,26 @@ func testUpcast(arr: [@execution(caller) () async -> Void]) {
4444
}
4545

4646
// Isolated parameter
47-
func testParameterIsolation(fn: @escaping (isolated (any Actor)?) async -> Void) {
47+
func testParameterIsolation(fn: @escaping (isolated (any Actor)?) async -> Void, caller: @escaping @execution(caller) (String) async -> Void) {
4848
let _: @execution(caller) () async -> Void = fn
4949
// expected-error@-1 {{cannot convert value of type '(isolated (any Actor)?) async -> Void' to specified type '@execution(caller) () async -> Void'}}
5050
let _: @execution(concurrent) () async -> Void = fn
5151
// expected-error@-1 {{cannot convert value of type '(isolated (any Actor)?) async -> Void' to specified type '() async -> Void'}}
52+
53+
let _: (isolated (any Actor)?) async -> Void = callerTest // Ok
54+
let _: (isolated (any Actor)?) -> Void = callerTest
55+
// expected-error@-1 {{invalid conversion from 'async' function of type '@execution(caller) () async -> ()' to synchronous function type '(isolated (any Actor)?) -> Void'}}
56+
let _: (isolated (any Actor)?) async -> Void = concurrentTest
57+
// expected-error@-1 {{cannot convert value of type '() async -> ()' to specified type '(isolated (any Actor)?) async -> Void'}}
58+
let _: (isolated (any Actor)?, Int) async -> Void = callerTest
59+
// expected-error@-1 {{cannot convert value of type '@execution(caller) () async -> ()' to specified type '(isolated (any Actor)?, Int) async -> Void'}}
60+
61+
let _: (String, isolated any Actor) async -> Void = caller // Ok
62+
let _: (isolated (any Actor)?, String) async -> Void = caller // Ok
63+
64+
let _: (Int, isolated any Actor) async -> Void = { @execution(caller) x in } // Ok
65+
let _: (Int, isolated any Actor) async -> Void = { @execution(caller) (x: Int) in } // Ok
66+
let _: (isolated any Actor, Int, String) async -> Void = { @execution(caller) (x: Int, _: String) in } // Ok
5267
}
5368

5469
// Non-conversion situations

0 commit comments

Comments
 (0)