Skip to content

Commit f2fff10

Browse files
committed
SIL: Synchronous local functions don't need to capture the isolation parameter
Also, move this rule from the computation of lowered captures in SIL, to the computation of AST captures in Sema. This allows us to correctly handle the case where an async function nests inside a sync function. It also removes a special case that was added recently to cope with a generic `self` type. Fixes rdar://129366819.
1 parent 3436c49 commit f2fff10

File tree

4 files changed

+40
-29
lines changed

4 files changed

+40
-29
lines changed

lib/SIL/IR/TypeLowering.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4485,26 +4485,6 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
44854485
PrettyStackTraceAnyFunctionRef("lowering local captures", curFn);
44864486
collectCaptures(curFn.getCaptureInfo());
44874487

4488-
if (auto *afd = curFn.getAbstractFunctionDecl()) {
4489-
// If a local function inherits isolation from the enclosing context,
4490-
// make sure we capture the isolated parameter, if we haven't already.
4491-
if (afd->isLocalCapture()) {
4492-
auto actorIsolation = getActorIsolation(afd);
4493-
if (actorIsolation.getKind() == ActorIsolation::ActorInstance) {
4494-
if (auto *var = actorIsolation.getActorInstance()) {
4495-
assert(isa<ParamDecl>(var));
4496-
recordCapture(CapturedValue(var, 0, afd->getLoc()));
4497-
if (var->getInterfaceType()->hasTypeParameter()) {
4498-
// If the isolated parameter is of a generic (actor)
4499-
// type, we need to treat as if the local function is
4500-
// generic.
4501-
capturesGenericParams = true;
4502-
}
4503-
}
4504-
}
4505-
}
4506-
}
4507-
45084488
// A function's captures also include its default arguments, because
45094489
// when we reference a function we don't track which default arguments
45104490
// are referenced too.

lib/SILOptimizer/Utils/SILIsolationInfo.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -892,10 +892,9 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) {
892892
}
893893

894894
// Otherwise, if we do not have an isolated argument and are not in an
895-
// alloactor, then we might be isolated via global isolation.
895+
// allocator, then we might be isolated via global isolation.
896896
if (auto functionIsolation = fArg->getFunction()->getActorIsolation()) {
897897
if (functionIsolation.isActorIsolated()) {
898-
assert(functionIsolation.isGlobalActor());
899898
if (functionIsolation.isGlobalActor()) {
900899
return SILIsolationInfo::getGlobalActorIsolated(
901900
fArg, functionIsolation.getGlobalActor());

lib/Sema/TypeCheckCaptures.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,9 @@ class FindCapturedVars : public ASTWalker {
234234

235235
// Visit the type of the capture, if it isn't a class reference, since
236236
// we'd need the metadata to do so.
237-
if (VD->hasInterfaceType()
238-
&& (!ObjC
237+
if (!ObjC
239238
|| !isa<VarDecl>(VD)
240-
|| !cast<VarDecl>(VD)->getTypeInContext()->hasRetainablePointerRepresentation()))
239+
|| !cast<VarDecl>(VD)->getTypeInContext()->hasRetainablePointerRepresentation())
241240
checkType(VD->getInterfaceType(), VD->getLoc());
242241
}
243242

@@ -752,6 +751,18 @@ CaptureInfo CaptureInfoRequest::evaluate(Evaluator &evaluator,
752751
finder.checkType(type, AFD->getLoc());
753752
}
754753

754+
if (AFD->isLocalCapture() && AFD->hasAsync()) {
755+
// If a local function inherits isolation from the enclosing context,
756+
// make sure we capture the isolated parameter, if we haven't already.
757+
auto actorIsolation = getActorIsolation(AFD);
758+
if (actorIsolation.getKind() == ActorIsolation::ActorInstance) {
759+
if (auto *var = actorIsolation.getActorInstance()) {
760+
assert(isa<ParamDecl>(var));
761+
finder.addCapture(CapturedValue(var, 0, AFD->getLoc()));
762+
}
763+
}
764+
}
765+
755766
// Extensions of generic ObjC functions can't use generic parameters from
756767
// their context.
757768
if (finder.hasGenericParamCaptures()) {

test/SILGen/local_function_isolation.swift

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,32 @@ func test() async {}
5959
// local/nested function.
6060
actor GenericActor<K> {
6161
var i: Int = 0
62-
private func outerFunc() {
63-
func accessSelf() -> Int {
64-
// CHECK-LABEL: sil private [ossa] @$s24local_function_isolation12GenericActorC9outerFunc33_7B9E2B75110B8600A136A469D51CAF2BLLyyF10accessSelfL_SiylF : $@convention(thin) <K> (@sil_isolated @guaranteed GenericActor<K>) -> Int {
62+
func outerFunc() async {
63+
func accessSelf() async -> Int {
64+
// CHECK-LABEL: sil private [ossa] @$s24local_function_isolation12GenericActorC9outerFuncyyYaF10accessSelfL_SiyYalF : $@convention(thin) @async <K> (@sil_isolated @guaranteed GenericActor<K>) -> Int {
6565
return 0
6666
}
67-
print(accessSelf())
67+
await print(accessSelf())
6868
}
6969
}
70+
71+
// Make sure defer doesn't capture anything.
72+
actor DeferInsideInitActor {
73+
init(foo: ()) async throws {
74+
// CHECK-LABEL: sil private [ossa] @$s24local_function_isolation20DeferInsideInitActorC3fooACyt_tYaKcfc6$deferL_yyF : $@convention(thin) () -> () {
75+
defer {}
76+
try self.init()
77+
}
78+
}
79+
80+
actor NestedAsyncInSyncActor {
81+
public func outer() async {
82+
// CHECK-LABEL: sil private [ossa] @$s24local_function_isolation22NestedAsyncInSyncActorC5outeryyYaF6middleL_yyF : $@convention(thin) (@sil_isolated @guaranteed NestedAsyncInSyncActor) -> () {
83+
func middle() {
84+
// CHECK-LABEL: sil private [ossa] @$s24local_function_isolation22NestedAsyncInSyncActorC5outeryyYaF6middleL_yyF5innerL_yyYaF : $@convention(thin) @async (@sil_isolated @guaranteed NestedAsyncInSyncActor) -> () {
85+
func inner() async {}
86+
_ = inner
87+
}
88+
_ = middle
89+
}
90+
}

0 commit comments

Comments
 (0)