Skip to content

Commit 5fb314b

Browse files
committed
At the SIL level, allow synchronous functions to be nonisolated(nonsending).
1 parent 74496ea commit 5fb314b

File tree

5 files changed

+65
-14
lines changed

5 files changed

+65
-14
lines changed

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,11 @@ class Conventions {
12611261

12621262
ConventionsKind getKind() const { return kind; }
12631263

1264+
bool hasCallerIsolationParameter() const {
1265+
return kind == ConventionsKind::Default ||
1266+
kind == ConventionsKind::Deallocator;
1267+
}
1268+
12641269
virtual ParameterConvention
12651270
getIndirectParameter(unsigned index,
12661271
const AbstractionPattern &type,
@@ -1700,14 +1705,10 @@ class DestructureInputs {
17001705
};
17011706
}
17021707

1703-
// If we are an async function that is unspecified or nonisolated, insert an
1704-
// isolated parameter if NonisolatedNonsendingByDefault is enabled.
1705-
//
1706-
// NOTE: The parameter is not inserted for async functions imported
1707-
// from ObjC because they are handled in a special way that doesn't
1708-
// require it.
1708+
// If the function has nonisolated(nonsending) isolation, insert the
1709+
// implicit isolation parameter.
17091710
if (IsolationInfo && IsolationInfo->isCallerIsolationInheriting() &&
1710-
extInfoBuilder.isAsync() && !Foreign.async) {
1711+
Convs.hasCallerIsolationParameter()) {
17111712
auto actorProtocol = TC.Context.getProtocol(KnownProtocolKind::Actor);
17121713
auto actorType =
17131714
ExistentialType::get(actorProtocol->getDeclaredInterfaceType());

lib/SILGen/SILGenConcurrency.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ void SILGenFunction::emitExpectedExecutorProlog() {
190190
}
191191

192192
case ActorIsolation::CallerIsolationInheriting:
193-
assert(F.isAsync());
193+
assert(F.isAsync() || F.isDefer());
194194
setExpectedExecutorForParameterIsolation(*this, actorIsolation);
195195
break;
196196

@@ -255,7 +255,7 @@ void SILGenFunction::emitExpectedExecutorProlog() {
255255
RegularLocation::getDebugOnlyLocation(F.getLocation(), getModule()),
256256
executor,
257257
/*mandatory*/ false);
258-
} else {
258+
} else if (wantDataRaceChecks) {
259259
// For a synchronous function, check that we're on the same executor.
260260
// Note: if we "know" that the code is completely Sendable-safe, this
261261
// is unnecessary. The type checker will need to make this determination.

lib/SILGen/SILGenExpr.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2950,12 +2950,22 @@ SILGenFunction::emitApplyOfDefaultArgGenerator(SILLocation loc,
29502950
ResultPlanBuilder::computeResultPlan(*this, calleeTypeInfo, loc, C);
29512951
ArgumentScope argScope(*this, loc);
29522952

2953-
SmallVector<ManagedValue, 4> captures;
2953+
SmallVector<ManagedValue, 4> args;
2954+
2955+
// Add the implicit leading isolation argument for a
2956+
// nonisolated(nonsending) default argument generator.
2957+
if (fnType->maybeGetIsolatedParameter()) {
2958+
auto executor = emitExpectedExecutor(loc);
2959+
args.push_back(emitActorInstanceIsolation(
2960+
loc, executor, executor.getType().getASTType()));
2961+
}
2962+
2963+
// If there are captures, those come at the end.
29542964
emitCaptures(loc, generator, CaptureEmission::ImmediateApplication,
2955-
captures);
2965+
args);
29562966

29572967
return emitApply(std::move(resultPtr), std::move(argScope), loc, fnRef, subs,
2958-
captures, calleeTypeInfo, ApplyOptions(), C, std::nullopt);
2968+
args, calleeTypeInfo, ApplyOptions(), C, std::nullopt);
29592969
}
29602970

29612971
RValue SILGenFunction::emitApplyOfStoredPropertyInitializer(

test/SILGen/isolated_default_arguments.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ func main_actor_int_pair() -> (Int, Int) {
2828
return (0,0)
2929
}
3030

31+
func make_int(isolated isolation: (any Actor)? = #isolation) -> Int {
32+
return 0
33+
}
34+
3135
// This test breaks because the intermediate argument is `nil`, which
3236
// we treat as non-isolated.
3337
@MainActor
@@ -121,3 +125,39 @@ func tupleIsolatedDefaultArg(x: (Int,Int) = main_actor_int_pair(),
121125
func testTupleIsolatedDefaultArg() async {
122126
await tupleIsolatedDefaultArg(y: 0)
123127
}
128+
129+
// When a function is caller-isolated, its default argument generators
130+
// should probably also be caller-isolated and forward their isolation
131+
// properly when #isolation is used. Currently, however, that's not what
132+
// we're doing, so test for the current behavior.
133+
134+
nonisolated(nonsending)
135+
func callerIsolatedDefaultArg(x: Int = make_int()) async {}
136+
137+
@MainActor
138+
func useCallerIsolatedDefaultArg() async {
139+
await callerIsolatedDefaultArg()
140+
}
141+
142+
// Check that the default argument generator isn't caller-isolated.
143+
// CHECK-LABEL: // default argument 0 of test.callerIsolatedDefaultArg
144+
// CHECK-NEXT: // Isolation: unspecified
145+
// CHECK-NEXT: sil hidden [ossa] @$s4test24callerIsolatedDefaultArg1xySi_tYaFfA_ :
146+
// CHECK: bb0:
147+
// Check that we provide a nil isolation for #isolation
148+
// CHECK-NEXT: [[NIL_ISOLATION:%.*]] = enum $Optional<any Actor>, #Optional.none
149+
// CHECK-NEXT: // function_ref test.make_int
150+
// CHECK-NEXT: [[FN:%.*]] = function_ref @$s4test8make_int8isolatedSiScA_pSg_tF :
151+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]([[NIL_ISOLATION]])
152+
// CHECK-NEXT: return [[RESULT]]
153+
154+
// Check that we pass the right isolation to the generator.
155+
// CHECK-LABEL: sil hidden [ossa] @$s4test27useCallerIsolatedDefaultArgyyYaF :
156+
// Get the main actor reference.
157+
// CHECK: [[GET_MAIN_ACTOR:%.*]] = function_ref @$sScM6sharedScMvgZ :
158+
// CHECK-NEXT: [[T0:%.*]] = apply [[GET_MAIN_ACTOR]](
159+
// CHECK-NEXT: [[MAIN_ACTOR:%.*]] = begin_borrow [[T0]]
160+
// Call the accessor.
161+
// CHECK: // function_ref default argument 0 of
162+
// CHECK-NEXT: [[GEN:%.*]] = function_ref @$s4test24callerIsolatedDefaultArg1xySi_tYaFfA_ :
163+
// CHECK-NEXT: [[ARG:%.*]] = apply [[GEN]]()

test/SILGen/objc_async_from_swift.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ func testAutoclosureInStaticMethod() {
466466
//
467467
// Get standard.
468468
// CHECK: [[METATYPE:%.*]] = metatype $@objc_metatype SlowServer.Type
469-
// CHECK: [[GET_STANDARD_FUNC:%.*]] = objc_method %1 : $@objc_metatype SlowServer.Type, #SlowServer.standard!getter.foreign : (SlowServer.Type) -> () -> SlowServer, $@convention(objc_method) (@objc_metatype SlowServer.Type) -> @autoreleased SlowServer
469+
// CHECK: [[GET_STANDARD_FUNC:%.*]] = objc_method [[METATYPE]] : $@objc_metatype SlowServer.Type, #SlowServer.standard!getter.foreign : (SlowServer.Type) -> () -> SlowServer, $@convention(objc_method) (@objc_metatype SlowServer.Type) -> @autoreleased SlowServer
470470
// CHECK: [[STANDARD:%.*]] = apply [[GET_STANDARD_FUNC]]([[METATYPE]])
471471
//
472472
// Then grab value.
@@ -592,7 +592,7 @@ func testAutoclosureInStaticMethod() {
592592
//
593593
// Get standard.
594594
// CHECK: [[METATYPE:%.*]] = metatype $@objc_metatype SlowServer.Type
595-
// CHECK: [[GET_STANDARD_FUNC:%.*]] = objc_method %1 : $@objc_metatype SlowServer.Type, #SlowServer.standard!getter.foreign : (SlowServer.Type) -> () -> SlowServer, $@convention(objc_method) (@objc_metatype SlowServer.Type) -> @autoreleased SlowServer
595+
// CHECK: [[GET_STANDARD_FUNC:%.*]] = objc_method [[METATYPE]] : $@objc_metatype SlowServer.Type, #SlowServer.standard!getter.foreign : (SlowServer.Type) -> () -> SlowServer, $@convention(objc_method) (@objc_metatype SlowServer.Type) -> @autoreleased SlowServer
596596
// CHECK: [[STANDARD:%.*]] = apply [[GET_STANDARD_FUNC]]([[METATYPE]])
597597
//
598598
// Then grab value.

0 commit comments

Comments
 (0)