mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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:
@@ -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;
|
||||
}
|
||||
|
||||
23
test/SILGen/isolated_self_capture.swift
Normal file
23
test/SILGen/isolated_self_capture.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user