[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".
This commit is contained in:
Michael Gottesman
2024-02-29 20:19:33 -08:00
parent 2a78ce8522
commit 2e4fad37a1
2 changed files with 44 additions and 16 deletions

View File

@@ -1917,6 +1917,7 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
// signature from the AST for that.
auto origGenericSig = function.getAnyFunctionRef()->getGenericSignature();
auto loweredCaptures = TC.getLoweredLocalCaptures(function);
auto *isolatedParam = loweredCaptures.getIsolatedParamCapture();
for (auto capture : loweredCaptures.getCaptures()) {
if (capture.isDynamicSelfMetadata()) {
@@ -1955,13 +1956,17 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
continue;
}
auto *VD = capture.getDecl();
auto type = VD->getInterfaceType();
auto *varDecl = capture.getDecl();
auto type = varDecl->getInterfaceType();
auto canType = type->getReducedType(origGenericSig);
auto options = SILParameterInfo::Options();
if (isolatedParam == varDecl)
options |= SILParameterInfo::Isolated;
// If we're capturing a parameter pack, wrap it in a tuple.
if (isa<PackExpansionType>(canType)) {
assert(!cast<ParamDecl>(VD)->supportsMutation() &&
assert(!cast<ParamDecl>(varDecl)->supportsMutation() &&
"Cannot capture a pack as an lvalue");
SmallVector<TupleTypeElt, 1> elts;
@@ -1983,7 +1988,7 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
} else {
convention = ParameterConvention::Direct_Guaranteed;
}
SILParameterInfo param(loweredTy.getASTType(), convention);
SILParameterInfo param(loweredTy.getASTType(), convention, options);
inputs.push_back(param);
break;
}
@@ -1995,10 +2000,10 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
.getLoweredType();
// Lvalues are captured as a box that owns the captured value.
auto boxTy = TC.getInterfaceBoxTypeForCapture(
VD, minimalLoweredTy.getASTType(),
varDecl, minimalLoweredTy.getASTType(),
/*mutable*/ true);
auto convention = ParameterConvention::Direct_Guaranteed;
auto param = SILParameterInfo(boxTy, convention);
auto param = SILParameterInfo(boxTy, convention, options);
inputs.push_back(param);
break;
}
@@ -2009,20 +2014,20 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
TypeExpansionContext::minimal())
.getLoweredType();
// Lvalues are captured as a box that owns the captured value.
auto boxTy =
TC.getInterfaceBoxTypeForCapture(VD, minimalLoweredTy.getASTType(),
/*mutable*/ false);
auto boxTy = TC.getInterfaceBoxTypeForCapture(
varDecl, minimalLoweredTy.getASTType(),
/*mutable*/ false);
auto convention = ParameterConvention::Direct_Guaranteed;
auto param = SILParameterInfo(boxTy, convention);
auto param = SILParameterInfo(boxTy, convention, options);
inputs.push_back(param);
break;
}
case CaptureKind::StorageAddress: {
// Non-escaping lvalues are captured as the address of the value.
SILType ty = loweredTy.getAddressType();
auto param =
SILParameterInfo(ty.getASTType(),
ParameterConvention::Indirect_InoutAliasable);
auto param = SILParameterInfo(
ty.getASTType(), ParameterConvention::Indirect_InoutAliasable,
options);
inputs.push_back(param);
break;
}
@@ -2030,9 +2035,9 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
// 'let' constants that are address-only are captured as the address of
// the value and will be consumed by the closure.
SILType ty = loweredTy.getAddressType();
auto param =
SILParameterInfo(ty.getASTType(),
ParameterConvention::Indirect_In_Guaranteed);
auto param = SILParameterInfo(ty.getASTType(),
ParameterConvention::Indirect_In_Guaranteed,
options);
inputs.push_back(param);
break;
}

View File

@@ -0,0 +1,23 @@
// RUN: %target-swift-frontend -emit-silgen %s -module-name test -swift-version 5 | %FileCheck %s
// REQUIRES: concurrency
class NonSendableKlass {}
func useValue<T>(_ t: T) {}
@MainActor func transferToMain<T>(_ t: T) async {}
actor MyActor {
var ns = NonSendableKlass()
// CHECK-LABEL: sil hidden [ossa] @$s4test7MyActorC19passSelfIntoClosureyyYaF : $@convention(method) @async (@sil_isolated @guaranteed MyActor) -> () {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $
// CHECK: [[COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{.*}}([[COPY]]) : $@convention(thin) (@sil_isolated @guaranteed MyActor) -> ()
// CHECK: } // end sil function '$s4test7MyActorC19passSelfIntoClosureyyYaF'
func passSelfIntoClosure() async {
let closure = { useValue(self.ns) }
await transferToMain(closure)
}
}