Skip to content

Commit cf0457d

Browse files
committed
[concurrency] Make captured self in a closure show up as an @sil_isolated parameter in the closure's function signature.
This ensures that when region isolation is enabled, we can begin properly modeling when a closure should not be allowed to be isolated. In the next commit, I am going to loosen this and we should be able to pass in actors outside of methods without the closure being afflicted with "actor derived-ness".
1 parent 2a78ce8 commit cf0457d

File tree

2 files changed

+46
-16
lines changed

2 files changed

+46
-16
lines changed

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,9 +1917,11 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
19171917
// signature from the AST for that.
19181918
auto origGenericSig = function.getAnyFunctionRef()->getGenericSignature();
19191919
auto loweredCaptures = TC.getLoweredLocalCaptures(function);
1920+
auto *isolatedParam = loweredCaptures.getIsolatedParamCapture();
19201921

19211922
for (auto capture : loweredCaptures.getCaptures()) {
19221923
if (capture.isDynamicSelfMetadata()) {
1924+
assert(!isolatedParam);
19231925
ParameterConvention convention = ParameterConvention::Direct_Unowned;
19241926
auto dynamicSelfInterfaceType =
19251927
loweredCaptures.getDynamicSelfType()->mapTypeOutOfContext();
@@ -1935,6 +1937,7 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
19351937
}
19361938

19371939
if (capture.isOpaqueValue()) {
1940+
assert(!isolatedParam);
19381941
OpaqueValueExpr *opaqueValue = capture.getOpaqueValue();
19391942
auto canType = opaqueValue->getType()->mapTypeOutOfContext()
19401943
->getReducedType(origGenericSig);
@@ -1955,13 +1958,17 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
19551958
continue;
19561959
}
19571960

1958-
auto *VD = capture.getDecl();
1959-
auto type = VD->getInterfaceType();
1961+
auto *varDecl = capture.getDecl();
1962+
auto type = varDecl->getInterfaceType();
19601963
auto canType = type->getReducedType(origGenericSig);
19611964

1965+
auto options = SILParameterInfo::Options();
1966+
if (isolatedParam == varDecl)
1967+
options |= SILParameterInfo::Isolated;
1968+
19621969
// If we're capturing a parameter pack, wrap it in a tuple.
19631970
if (isa<PackExpansionType>(canType)) {
1964-
assert(!cast<ParamDecl>(VD)->supportsMutation() &&
1971+
assert(!cast<ParamDecl>(varDecl)->supportsMutation() &&
19651972
"Cannot capture a pack as an lvalue");
19661973

19671974
SmallVector<TupleTypeElt, 1> elts;
@@ -1983,7 +1990,7 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
19831990
} else {
19841991
convention = ParameterConvention::Direct_Guaranteed;
19851992
}
1986-
SILParameterInfo param(loweredTy.getASTType(), convention);
1993+
SILParameterInfo param(loweredTy.getASTType(), convention, options);
19871994
inputs.push_back(param);
19881995
break;
19891996
}
@@ -1995,10 +2002,10 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
19952002
.getLoweredType();
19962003
// Lvalues are captured as a box that owns the captured value.
19972004
auto boxTy = TC.getInterfaceBoxTypeForCapture(
1998-
VD, minimalLoweredTy.getASTType(),
2005+
varDecl, minimalLoweredTy.getASTType(),
19992006
/*mutable*/ true);
20002007
auto convention = ParameterConvention::Direct_Guaranteed;
2001-
auto param = SILParameterInfo(boxTy, convention);
2008+
auto param = SILParameterInfo(boxTy, convention, options);
20022009
inputs.push_back(param);
20032010
break;
20042011
}
@@ -2009,30 +2016,30 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
20092016
TypeExpansionContext::minimal())
20102017
.getLoweredType();
20112018
// Lvalues are captured as a box that owns the captured value.
2012-
auto boxTy =
2013-
TC.getInterfaceBoxTypeForCapture(VD, minimalLoweredTy.getASTType(),
2014-
/*mutable*/ false);
2019+
auto boxTy = TC.getInterfaceBoxTypeForCapture(
2020+
varDecl, minimalLoweredTy.getASTType(),
2021+
/*mutable*/ false);
20152022
auto convention = ParameterConvention::Direct_Guaranteed;
2016-
auto param = SILParameterInfo(boxTy, convention);
2023+
auto param = SILParameterInfo(boxTy, convention, options);
20172024
inputs.push_back(param);
20182025
break;
20192026
}
20202027
case CaptureKind::StorageAddress: {
20212028
// Non-escaping lvalues are captured as the address of the value.
20222029
SILType ty = loweredTy.getAddressType();
2023-
auto param =
2024-
SILParameterInfo(ty.getASTType(),
2025-
ParameterConvention::Indirect_InoutAliasable);
2030+
auto param = SILParameterInfo(
2031+
ty.getASTType(), ParameterConvention::Indirect_InoutAliasable,
2032+
options);
20262033
inputs.push_back(param);
20272034
break;
20282035
}
20292036
case CaptureKind::Immutable: {
20302037
// 'let' constants that are address-only are captured as the address of
20312038
// the value and will be consumed by the closure.
20322039
SILType ty = loweredTy.getAddressType();
2033-
auto param =
2034-
SILParameterInfo(ty.getASTType(),
2035-
ParameterConvention::Indirect_In_Guaranteed);
2040+
auto param = SILParameterInfo(ty.getASTType(),
2041+
ParameterConvention::Indirect_In_Guaranteed,
2042+
options);
20362043
inputs.push_back(param);
20372044
break;
20382045
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-swift-frontend -emit-silgen %s -module-name test -swift-version 5 | %FileCheck %s
2+
3+
// REQUIRES: concurrency
4+
5+
class NonSendableKlass {}
6+
7+
func useValue<T>(_ t: T) {}
8+
9+
@MainActor func transferToMain<T>(_ t: T) async {}
10+
11+
actor MyActor {
12+
var ns = NonSendableKlass()
13+
14+
// CHECK-LABEL: sil hidden [ossa] @$s4test7MyActorC19passSelfIntoClosureyyYaF : $@convention(method) @async (@sil_isolated @guaranteed MyActor) -> () {
15+
// CHECK: bb0([[ARG:%.*]] : @guaranteed $
16+
// CHECK: [[COPY:%.*]] = copy_value [[ARG]]
17+
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{.*}}([[COPY]]) : $@convention(thin) (@sil_isolated @guaranteed MyActor) -> ()
18+
// CHECK: } // end sil function '$s4test7MyActorC19passSelfIntoClosureyyYaF'
19+
func passSelfIntoClosure() async {
20+
let closure = { useValue(self.ns) }
21+
await transferToMain(closure)
22+
}
23+
}

0 commit comments

Comments
 (0)