mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Sema] Start propagating @_inheritActorContext(always) attribute to closures
This commit is contained in:
@@ -267,7 +267,7 @@ protected:
|
||||
Kind : 2
|
||||
);
|
||||
|
||||
SWIFT_INLINE_BITFIELD(ClosureExpr, AbstractClosureExpr, 1+1+1+1+1+1+1+1,
|
||||
SWIFT_INLINE_BITFIELD(ClosureExpr, AbstractClosureExpr, 1+1+1+1+1+1+1+1+1,
|
||||
/// True if closure parameters were synthesized from anonymous closure
|
||||
/// variables.
|
||||
HasAnonymousClosureVars : 1,
|
||||
@@ -276,9 +276,11 @@ protected:
|
||||
/// on each member reference.
|
||||
ImplicitSelfCapture : 1,
|
||||
|
||||
/// True if this @Sendable async closure parameter should implicitly
|
||||
/// inherit the actor context from where it was formed.
|
||||
/// True if this closure parameter should implicitly inherit the actor
|
||||
/// context from where it was formed.
|
||||
InheritActorContext : 1,
|
||||
/// The kind for inheritance - none or always at the moment.
|
||||
InheritActorContextKind : 1,
|
||||
|
||||
/// True if this closure's actor isolation behavior was determined by an
|
||||
/// \c \@preconcurrency declaration.
|
||||
@@ -4318,6 +4320,7 @@ public:
|
||||
Bits.ClosureExpr.HasAnonymousClosureVars = false;
|
||||
Bits.ClosureExpr.ImplicitSelfCapture = false;
|
||||
Bits.ClosureExpr.InheritActorContext = false;
|
||||
Bits.ClosureExpr.InheritActorContextKind = 0;
|
||||
Bits.ClosureExpr.IsPassedToSendingParameter = false;
|
||||
Bits.ClosureExpr.NoGlobalActorAttribute = false;
|
||||
Bits.ClosureExpr.RequiresDynamicIsolationChecking = false;
|
||||
@@ -4366,8 +4369,29 @@ public:
|
||||
return Bits.ClosureExpr.InheritActorContext;
|
||||
}
|
||||
|
||||
void setInheritsActorContext(bool value = true) {
|
||||
/// Whether this closure should _always_ implicitly inherit the actor context
|
||||
/// regardless of whether the isolation parameter is captured or not.
|
||||
bool alwaysInheritsActorContext() const {
|
||||
if (!inheritsActorContext())
|
||||
return false;
|
||||
return getInheritActorIsolationModifier() ==
|
||||
InheritActorContextModifier::Always;
|
||||
}
|
||||
|
||||
void setInheritsActorContext(bool value = true,
|
||||
InheritActorContextModifier modifier =
|
||||
InheritActorContextModifier::None) {
|
||||
Bits.ClosureExpr.InheritActorContext = value;
|
||||
Bits.ClosureExpr.InheritActorContextKind = uint8_t(modifier);
|
||||
assert((static_cast<InheritActorContextModifier>(
|
||||
Bits.ClosureExpr.InheritActorContextKind) == modifier) &&
|
||||
"not enough bits for modifier");
|
||||
}
|
||||
|
||||
InheritActorContextModifier getInheritActorIsolationModifier() const {
|
||||
assert(inheritsActorContext());
|
||||
return static_cast<InheritActorContextModifier>(
|
||||
Bits.ClosureExpr.InheritActorContextKind);
|
||||
}
|
||||
|
||||
/// Whether the closure's concurrency behavior was determined by an
|
||||
|
||||
@@ -4049,6 +4049,7 @@ struct ParameterListInfo {
|
||||
SmallBitVector propertyWrappers;
|
||||
SmallBitVector implicitSelfCapture;
|
||||
SmallBitVector inheritActorContext;
|
||||
SmallBitVector alwaysInheritActorContext;
|
||||
SmallBitVector variadicGenerics;
|
||||
SmallBitVector sendingParameters;
|
||||
|
||||
@@ -4075,7 +4076,8 @@ public:
|
||||
|
||||
/// Whether the given parameter is a closure that should inherit the
|
||||
/// actor context from the context in which it was created.
|
||||
bool inheritsActorContext(unsigned paramIdx) const;
|
||||
std::pair<bool, InheritActorContextModifier>
|
||||
inheritsActorContext(unsigned paramIdx) const;
|
||||
|
||||
bool isVariadicGenericParameter(unsigned paramIdx) const;
|
||||
|
||||
|
||||
@@ -1378,6 +1378,7 @@ ParameterListInfo::ParameterListInfo(
|
||||
propertyWrappers.resize(params.size());
|
||||
implicitSelfCapture.resize(params.size());
|
||||
inheritActorContext.resize(params.size());
|
||||
alwaysInheritActorContext.resize(params.size());
|
||||
variadicGenerics.resize(params.size());
|
||||
sendingParameters.resize(params.size());
|
||||
|
||||
@@ -1434,8 +1435,13 @@ ParameterListInfo::ParameterListInfo(
|
||||
implicitSelfCapture.set(i);
|
||||
}
|
||||
|
||||
if (param->getAttrs().hasAttribute<InheritActorContextAttr>()) {
|
||||
inheritActorContext.set(i);
|
||||
if (auto *attr =
|
||||
param->getAttrs().getAttribute<InheritActorContextAttr>()) {
|
||||
if (attr->isAlways()) {
|
||||
alwaysInheritActorContext.set(i);
|
||||
} else {
|
||||
inheritActorContext.set(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (param->getInterfaceType()->is<PackExpansionType>()) {
|
||||
@@ -1469,10 +1475,18 @@ bool ParameterListInfo::isImplicitSelfCapture(unsigned paramIdx) const {
|
||||
: false;
|
||||
}
|
||||
|
||||
bool ParameterListInfo::inheritsActorContext(unsigned paramIdx) const {
|
||||
return paramIdx < inheritActorContext.size()
|
||||
? inheritActorContext[paramIdx]
|
||||
: false;
|
||||
std::pair<bool, InheritActorContextModifier>
|
||||
ParameterListInfo::inheritsActorContext(unsigned paramIdx) const {
|
||||
if (paramIdx >= inheritActorContext.size())
|
||||
return std::make_pair(false, InheritActorContextModifier::None);
|
||||
|
||||
if (inheritActorContext[paramIdx])
|
||||
return std::make_pair(true, InheritActorContextModifier::None);
|
||||
|
||||
if (alwaysInheritActorContext[paramIdx])
|
||||
return std::make_pair(true, InheritActorContextModifier::Always);
|
||||
|
||||
return std::make_pair(false, InheritActorContextModifier::None);
|
||||
}
|
||||
|
||||
bool ParameterListInfo::isVariadicGenericParameter(unsigned paramIdx) const {
|
||||
|
||||
@@ -6097,15 +6097,20 @@ static bool hasCurriedSelf(ConstraintSystem &cs, ConcreteDeclRef callee,
|
||||
}
|
||||
|
||||
/// Apply the contextually Sendable flag to the given expression,
|
||||
static void applyContextualClosureFlags(Expr *expr, bool implicitSelfCapture,
|
||||
bool inheritActorContext,
|
||||
bool isPassedToSendingParameter,
|
||||
static void applyContextualClosureFlags(Expr *expr, unsigned paramIdx,
|
||||
const ParameterListInfo ¶mInfo,
|
||||
bool requiresDynamicIsolationChecking,
|
||||
bool isMacroArg) {
|
||||
if (auto closure = dyn_cast<ClosureExpr>(expr)) {
|
||||
closure->setAllowsImplicitSelfCapture(implicitSelfCapture);
|
||||
closure->setInheritsActorContext(inheritActorContext);
|
||||
closure->setIsPassedToSendingParameter(isPassedToSendingParameter);
|
||||
closure->setAllowsImplicitSelfCapture(
|
||||
paramInfo.isImplicitSelfCapture(paramIdx));
|
||||
|
||||
auto [inheritActorContext, modifier] =
|
||||
paramInfo.inheritsActorContext(paramIdx);
|
||||
closure->setInheritsActorContext(inheritActorContext, modifier);
|
||||
|
||||
closure->setIsPassedToSendingParameter(
|
||||
paramInfo.isSendingParameter(paramIdx));
|
||||
closure->setRequiresDynamicIsolationChecking(
|
||||
requiresDynamicIsolationChecking);
|
||||
closure->setIsMacroArgument(isMacroArg);
|
||||
@@ -6113,19 +6118,14 @@ static void applyContextualClosureFlags(Expr *expr, bool implicitSelfCapture,
|
||||
}
|
||||
|
||||
if (auto captureList = dyn_cast<CaptureListExpr>(expr)) {
|
||||
applyContextualClosureFlags(captureList->getClosureBody(),
|
||||
implicitSelfCapture, inheritActorContext,
|
||||
isPassedToSendingParameter,
|
||||
requiresDynamicIsolationChecking,
|
||||
applyContextualClosureFlags(captureList->getClosureBody(), paramIdx,
|
||||
paramInfo, requiresDynamicIsolationChecking,
|
||||
isMacroArg);
|
||||
}
|
||||
|
||||
if (auto identity = dyn_cast<IdentityExpr>(expr)) {
|
||||
applyContextualClosureFlags(identity->getSubExpr(), implicitSelfCapture,
|
||||
inheritActorContext,
|
||||
isPassedToSendingParameter,
|
||||
requiresDynamicIsolationChecking,
|
||||
isMacroArg);
|
||||
applyContextualClosureFlags(identity->getSubExpr(), paramIdx, paramInfo,
|
||||
requiresDynamicIsolationChecking, isMacroArg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6251,19 +6251,13 @@ ArgumentList *ExprRewriter::coerceCallArguments(
|
||||
|
||||
auto applyFlagsToArgument = [¶mInfo,
|
||||
&closuresRequireDynamicIsolationChecking,
|
||||
&locator](
|
||||
unsigned paramIdx, Expr *argument) {
|
||||
&locator](unsigned paramIdx, Expr *argument) {
|
||||
if (!isClosureLiteralExpr(argument))
|
||||
return;
|
||||
|
||||
bool isImplicitSelfCapture = paramInfo.isImplicitSelfCapture(paramIdx);
|
||||
bool inheritsActorContext = paramInfo.inheritsActorContext(paramIdx);
|
||||
bool isPassedToSendingParameter = paramInfo.isSendingParameter(paramIdx);
|
||||
bool isMacroArg = isExpr<MacroExpansionExpr>(locator.getAnchor());
|
||||
|
||||
applyContextualClosureFlags(argument, isImplicitSelfCapture,
|
||||
inheritsActorContext,
|
||||
isPassedToSendingParameter,
|
||||
applyContextualClosureFlags(argument, paramIdx, paramInfo,
|
||||
closuresRequireDynamicIsolationChecking,
|
||||
isMacroArg);
|
||||
};
|
||||
|
||||
@@ -4774,6 +4774,11 @@ ActorIsolation ActorIsolationChecker::determineClosureIsolation(
|
||||
|
||||
case ActorIsolation::ActorInstance: {
|
||||
if (checkIsolatedCapture) {
|
||||
auto *explicitClosure = dyn_cast<ClosureExpr>(closure);
|
||||
// @_inheritActorContext(always) forces the isolation capture.
|
||||
if (explicitClosure && explicitClosure->alwaysInheritsActorContext())
|
||||
return parentIsolation;
|
||||
|
||||
if (auto param = closure->getCaptureInfo().getIsolatedParamCapture())
|
||||
return ActorIsolation::forActorInstanceCapture(param);
|
||||
} else {
|
||||
|
||||
@@ -1210,6 +1210,8 @@ actor MyServer : Server {
|
||||
func acceptAsyncSendableClosure<T>(_: @Sendable () async -> T) { }
|
||||
@available(SwiftStdlib 5.1, *)
|
||||
func acceptAsyncSendableClosureInheriting<T>(@_inheritActorContext _: @Sendable () async -> T) { }
|
||||
@available(SwiftStdlib 5.1, *)
|
||||
func acceptAsyncSendableClosureInheritingAlways<T>(@_inheritActorContext(always) _: @Sendable () async -> T) { }
|
||||
|
||||
@available(SwiftStdlib 5.1, *)
|
||||
extension MyActor {
|
||||
@@ -1237,6 +1239,10 @@ extension MyActor {
|
||||
_ = await synchronous() // expected-warning{{no 'async' operations occur within 'await' expression}}
|
||||
counter += 1 // okay
|
||||
}
|
||||
|
||||
acceptAsyncSendableClosureInheritingAlways {
|
||||
counter += 1 // Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1257,6 +1263,32 @@ func testGlobalActorInheritance() {
|
||||
acceptAsyncSendableClosureInheriting {
|
||||
counter += 1 // ok
|
||||
}
|
||||
|
||||
acceptAsyncSendableClosureInheritingAlways {
|
||||
counter += 1 // ok
|
||||
}
|
||||
}
|
||||
|
||||
@available(SwiftStdlib 5.1, *)
|
||||
func testIsolatedParameter1(_: isolated any Actor, v: inout Int) {
|
||||
acceptAsyncSendableClosureInheriting {
|
||||
v += 1 // expected-warning {{mutable capture of 'inout' parameter 'v' is not allowed in concurrently-executing code}}
|
||||
}
|
||||
|
||||
acceptAsyncSendableClosureInheritingAlways {
|
||||
v += 1 // Ok
|
||||
}
|
||||
}
|
||||
|
||||
@available(SwiftStdlib 5.1, *)
|
||||
func testIsolatedParameter2(_: isolated (any Actor)? = #isolation, v: inout Int) {
|
||||
acceptAsyncSendableClosureInheriting {
|
||||
v += 1 // expected-warning {{mutable capture of 'inout' parameter 'v' is not allowed in concurrently-executing code}}
|
||||
}
|
||||
|
||||
acceptAsyncSendableClosureInheritingAlways {
|
||||
v += 1 // Ok
|
||||
}
|
||||
}
|
||||
|
||||
@available(SwiftStdlib 5.1, *)
|
||||
@@ -1763,4 +1795,4 @@ actor UserDefinedActorSelfDotMethod {
|
||||
// error message changes with InferSendabaleFromCaptures - see actor_isolation_swift6.swift
|
||||
return functionRef // expected-error {{cannot convert return expression of type '(isolated Self) -> () -> ()' to return type '(UserDefinedActorSelfDotMethod) -> @isolated(any) () -> Void'}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user