Skip to content

Commit 5bcb696

Browse files
authored
Merge pull request #78206 from gottesmm/rdar141520344-1
[concurrency] Add support for NonIsolatedAsyncInheritsIsolationFromContext behind a flag
2 parents 8e9f7b6 + 5cca4b9 commit 5bcb696

35 files changed

+773
-57
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ class ActorIsolation {
6969
/// The actor isolation iss statically erased, as for a call to
7070
/// an isolated(any) function. This is not possible for declarations.
7171
Erased,
72+
/// Inherits isolation from the caller of the given function.
73+
///
74+
/// DISCUSSION: This is used for nonisolated asynchronous functions that we
75+
/// want to inherit from their context the context's actor isolation.
76+
CallerIsolationInheriting,
7277
};
7378

7479
private:
@@ -107,6 +112,12 @@ class ActorIsolation {
107112
return ActorIsolation(unsafe ? NonisolatedUnsafe : Nonisolated);
108113
}
109114

115+
static ActorIsolation forCallerIsolationInheriting() {
116+
// NOTE: We do not use parameter indices since the parameter is implicit
117+
// from the perspective of the AST.
118+
return ActorIsolation(CallerIsolationInheriting);
119+
}
120+
110121
static ActorIsolation forActorInstanceSelf(ValueDecl *decl);
111122

112123
/// Create an ActorIsolation appropriate for a type that is self.
@@ -152,8 +163,11 @@ class ActorIsolation {
152163
ActorIsolation::NonisolatedUnsafe))
153164
.Case("global_actor",
154165
std::optional<ActorIsolation>(ActorIsolation::GlobalActor))
155-
.Case("global_actor_unsafe", std::optional<ActorIsolation>(
156-
ActorIsolation::GlobalActor))
166+
.Case("global_actor_unsafe",
167+
std::optional<ActorIsolation>(ActorIsolation::GlobalActor))
168+
.Case("caller_isolation_inheriting",
169+
std::optional<ActorIsolation>(
170+
ActorIsolation::CallerIsolationInheriting))
157171
.Default(std::nullopt);
158172
if (kind == std::nullopt)
159173
return std::nullopt;
@@ -180,8 +194,8 @@ class ActorIsolation {
180194
return parameterIndex;
181195
}
182196

183-
/// Returns true if this actor-instance isolation applies to the self
184-
/// parameter of a method.
197+
/// Returns true if this is an actor-instance isolation that additionally
198+
/// applies to the self parameter of a method.
185199
bool isActorInstanceForSelfParameter() const {
186200
return getActorInstanceParameter() == 0;
187201
}
@@ -198,6 +212,7 @@ class ActorIsolation {
198212
case Unspecified:
199213
case Nonisolated:
200214
case NonisolatedUnsafe:
215+
case CallerIsolationInheriting:
201216
return false;
202217
}
203218
}

include/swift/AST/TypeAttr.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ SIMPLE_SIL_TYPE_ATTR(captures_generics, CapturesGenerics)
111111
SIMPLE_SIL_TYPE_ATTR(moveOnly, MoveOnly)
112112
SIMPLE_SIL_TYPE_ATTR(sil_isolated, SILIsolated)
113113
SIMPLE_SIL_TYPE_ATTR(sil_sending, SILSending)
114+
SIMPLE_SIL_TYPE_ATTR(sil_implicit_leading_param, SILImplicitLeadingParam)
114115

115116
// SIL metatype attributes.
116117
SIMPLE_SIL_TYPE_ATTR(thin, Thin)

include/swift/AST/Types.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class PlaceholderTypeRepr;
8383
enum class ReferenceCounting : uint8_t;
8484
enum class ResilienceExpansion : unsigned;
8585
class SILModule;
86+
class SILFunction;
8687
class SILType;
8788
class SourceLoc;
8889
class TypeAliasDecl;
@@ -4438,6 +4439,16 @@ class SILParameterInfo {
44384439
/// that the parameter must be an Optional actor or something that conforms
44394440
/// to AnyActor.
44404441
Isolated = 0x4,
4442+
4443+
/// Set if the given parameter is an implicit parameter that is not part of
4444+
/// the formal type. These are always located after the return values and
4445+
/// before the main parameters. This is because we want to at the SIL level
4446+
/// generally treat them as normal parameters... but when working with the
4447+
/// AST during lowering, we need to handle ignoring them appropriately.
4448+
///
4449+
/// DISCUSSION: These are enforced by the SIL verifier to always be in
4450+
/// between indirect results and the explicit parameters.
4451+
ImplicitLeading = 0x8,
44414452
};
44424453

44434454
using Options = OptionSet<Flag>;
@@ -4464,6 +4475,11 @@ class SILParameterInfo {
44644475
///
44654476
/// \c t must refer back to the function type this is a parameter for.
44664477
CanType getArgumentType(SILModule &M, const SILFunctionType *t, TypeExpansionContext context) const;
4478+
4479+
/// Helper function that just grabs the module, type, and context out of \arg
4480+
/// fn and then calls getArgumentType.
4481+
CanType getArgumentType(SILFunction *fn) const;
4482+
44674483
ParameterConvention getConvention() const { return convention; }
44684484
// Does this parameter convention require indirect storage? This reflects a
44694485
// SILFunctionType's formal (immutable) conventions, as opposed to the

include/swift/Basic/Features.def

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,14 +430,18 @@ EXPERIMENTAL_FEATURE(CoroutineAccessorsUnwindOnCallerError, false)
430430
/// modify/read coroutines use the callee-allocated ABI
431431
EXPERIMENTAL_FEATURE(CoroutineAccessorsAllocateInCallee, false)
432432

433-
// When a parameter has unspecified isolation, infer it as main actor isolated.
433+
/// When a parameter has unspecified isolation, infer it as main actor isolated.
434434
EXPERIMENTAL_FEATURE(GenerateForceToMainActorThunks, false)
435435

436436
EXPERIMENTAL_FEATURE(AddressableParameters, true)
437437

438438
/// Allow the @abi attribute.
439439
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(ABIAttribute, true)
440440

441+
/// Functions with nonisolated isolation inherit their isolation from the
442+
/// calling context.
443+
EXPERIMENTAL_FEATURE(NonIsolatedAsyncInheritsIsolationFromContext, false)
444+
441445
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
442446
#undef EXPERIMENTAL_FEATURE
443447
#undef UPCOMING_FEATURE

lib/AST/ASTDumper.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2959,6 +2959,10 @@ class PrintExpr : public ExprVisitor<PrintExpr, void, StringRef>,
29592959
printFlag(true, "dynamically_isolated", CapturesColor);
29602960
break;
29612961

2962+
case ActorIsolation::CallerIsolationInheriting:
2963+
printFlag(true, "isolated_to_caller_isolation", CapturesColor);
2964+
break;
2965+
29622966
case ActorIsolation::ActorInstance:
29632967
printFieldQuoted(isolation.getActorInstance()->printRef(),
29642968
"actor_isolated", CapturesColor);

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7583,6 +7583,11 @@ void SILParameterInfo::print(
75837583
Printer.printLifetimeDependence(*lifetimeDependence);
75847584
}
75857585

7586+
if (options.contains(SILParameterInfo::ImplicitLeading)) {
7587+
options -= SILParameterInfo::ImplicitLeading;
7588+
Printer << "@sil_implicit_leading_param ";
7589+
}
7590+
75867591
// If we did not handle a case in Options, this code was not updated
75877592
// appropriately.
75887593
assert(!bool(options) && "Code not updated for introduced option");

lib/AST/ActorIsolation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,11 @@ bool ActorIsolation::isEqual(const ActorIsolation &lhs,
174174
// to answer.
175175
return false;
176176

177+
case CallerIsolationInheriting:
178+
// This returns false for the same reason as erased. The caller has to check
179+
// against the actual caller isolation.
180+
return false;
181+
177182
case ActorInstance: {
178183
auto *lhsActor = lhs.getActorInstance();
179184
auto *rhsActor = rhs.getActorInstance();

lib/AST/Decl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2708,6 +2708,7 @@ static bool deferMatchesEnclosingAccess(const FuncDecl *defer) {
27082708

27092709
return true;
27102710

2711+
case ActorIsolation::CallerIsolationInheriting:
27112712
case ActorIsolation::ActorInstance:
27122713
case ActorIsolation::Nonisolated:
27132714
case ActorIsolation::Erased: // really can't happen
@@ -11341,6 +11342,7 @@ bool VarDecl::isSelfParamCaptureIsolated() const {
1134111342
case ActorIsolation::NonisolatedUnsafe:
1134211343
case ActorIsolation::GlobalActor:
1134311344
case ActorIsolation::Erased:
11345+
case ActorIsolation::CallerIsolationInheriting:
1134411346
return false;
1134511347

1134611348
case ActorIsolation::ActorInstance:

lib/AST/FeatureSet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ UNINTERESTING_FEATURE(Volatile)
120120
UNINTERESTING_FEATURE(SuppressedAssociatedTypes)
121121
UNINTERESTING_FEATURE(StructLetDestructuring)
122122
UNINTERESTING_FEATURE(MacrosOnImports)
123+
UNINTERESTING_FEATURE(NonIsolatedAsyncInheritsIsolationFromContext)
123124

124125
static bool usesFeatureNonescapableTypes(Decl *decl) {
125126
auto containsNonEscapable =

lib/AST/TypeCheckRequests.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,6 +1856,7 @@ SourceLoc MacroDefinitionRequest::getNearestLoc() const {
18561856

18571857
bool ActorIsolation::requiresSubstitution() const {
18581858
switch (kind) {
1859+
case CallerIsolationInheriting:
18591860
case ActorInstance:
18601861
case Nonisolated:
18611862
case NonisolatedUnsafe:
@@ -1871,6 +1872,7 @@ bool ActorIsolation::requiresSubstitution() const {
18711872
ActorIsolation ActorIsolation::subst(SubstitutionMap subs) const {
18721873
switch (kind) {
18731874
case ActorInstance:
1875+
case CallerIsolationInheriting:
18741876
case Nonisolated:
18751877
case NonisolatedUnsafe:
18761878
case Unspecified:
@@ -1891,6 +1893,11 @@ void ActorIsolation::printForDiagnostics(llvm::raw_ostream &os,
18911893
os << "actor" << (asNoun ? " isolation" : "-isolated");
18921894
break;
18931895

1896+
case ActorIsolation::CallerIsolationInheriting:
1897+
os << "caller isolation inheriting"
1898+
<< (asNoun ? " isolation" : "-isolated");
1899+
break;
1900+
18941901
case ActorIsolation::GlobalActor: {
18951902
if (isMainActor()) {
18961903
os << "main actor" << (asNoun ? " isolation" : "-isolated");
@@ -1927,6 +1934,9 @@ void ActorIsolation::print(llvm::raw_ostream &os) const {
19271934
os << ". name: '" << vd->getBaseIdentifier() << "'";
19281935
}
19291936
return;
1937+
case CallerIsolationInheriting:
1938+
os << "caller_isolation_inheriting";
1939+
return;
19301940
case Nonisolated:
19311941
os << "nonisolated";
19321942
return;
@@ -1951,6 +1961,9 @@ void ActorIsolation::printForSIL(llvm::raw_ostream &os) const {
19511961
case ActorInstance:
19521962
os << "actor_instance";
19531963
return;
1964+
case CallerIsolationInheriting:
1965+
os << "caller_isolation_inheriting";
1966+
return;
19541967
case Nonisolated:
19551968
os << "nonisolated";
19561969
return;
@@ -1996,6 +2009,10 @@ void swift::simple_display(
19962009
}
19972010
break;
19982011

2012+
case ActorIsolation::CallerIsolationInheriting:
2013+
out << "isolated to isolation of caller";
2014+
break;
2015+
19992016
case ActorIsolation::Nonisolated:
20002017
case ActorIsolation::NonisolatedUnsafe:
20012018
out << "nonisolated";

lib/ASTGen/Sources/ASTGen/TypeAttrs.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ extension ASTGenVisitor {
122122
.silUnowned,
123123
.silWeak,
124124
.silSending,
125+
.silImplicitLeadingParam,
125126
.unownedInnerPointer:
126127
break;
127128

lib/IDE/CompletionLookup.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,7 @@ void CompletionLookup::analyzeActorIsolation(
827827
break;
828828
case ActorIsolation::Unspecified:
829829
case ActorIsolation::Nonisolated:
830+
case ActorIsolation::CallerIsolationInheriting:
830831
case ActorIsolation::NonisolatedUnsafe:
831832
return;
832833
}

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ CanSILFunctionType SILFunctionType::getUnsubstitutedType(SILModule &M) const {
108108
getWitnessMethodConformanceOrInvalid());
109109
}
110110

111+
CanType SILParameterInfo::getArgumentType(SILFunction *fn) const {
112+
return getArgumentType(fn->getModule(), fn->getLoweredFunctionType(),
113+
fn->getTypeExpansionContext());
114+
}
115+
111116
CanType SILParameterInfo::getArgumentType(SILModule &M,
112117
const SILFunctionType *t,
113118
TypeExpansionContext context) const {
@@ -1560,6 +1565,7 @@ class DestructureInputs {
15601565
TypeConverter &TC;
15611566
const Conventions &Convs;
15621567
const ForeignInfo &Foreign;
1568+
std::optional<ActorIsolation> IsolationInfo;
15631569
struct ForeignSelfInfo {
15641570
AbstractionPattern OrigSelfParam;
15651571
AnyFunctionType::CanParam SubstSelfParam;
@@ -1572,9 +1578,10 @@ class DestructureInputs {
15721578
public:
15731579
DestructureInputs(TypeExpansionContext expansion, TypeConverter &TC,
15741580
const Conventions &conventions, const ForeignInfo &foreign,
1581+
std::optional<ActorIsolation> isolationInfo,
15751582
SmallVectorImpl<SILParameterInfo> &inputs)
15761583
: expansion(expansion), TC(TC), Convs(conventions), Foreign(foreign),
1577-
Inputs(inputs) {}
1584+
IsolationInfo(isolationInfo), Inputs(inputs) {}
15781585

15791586
void destructure(AbstractionPattern origType,
15801587
CanAnyFunctionType::CanParamArrayRef params,
@@ -1636,6 +1643,23 @@ class DestructureInputs {
16361643
};
16371644
}
16381645

1646+
// If we are an async function that is unspecified or nonisolated, insert an
1647+
// isolated parameter if NonIsolatedAsyncInheritsIsolationFromContext is
1648+
// enabled.
1649+
if (TC.Context.LangOpts.hasFeature(
1650+
Feature::NonIsolatedAsyncInheritsIsolationFromContext) &&
1651+
IsolationInfo &&
1652+
IsolationInfo->getKind() == ActorIsolation::CallerIsolationInheriting &&
1653+
extInfoBuilder.isAsync()) {
1654+
auto actorProtocol = TC.Context.getProtocol(KnownProtocolKind::Actor);
1655+
auto actorType =
1656+
ExistentialType::get(actorProtocol->getDeclaredInterfaceType());
1657+
addParameter(CanType(actorType).wrapInOptionalType(),
1658+
ParameterConvention::Direct_Guaranteed,
1659+
ParameterTypeFlags().withIsolated(true),
1660+
true /*implicit leading parameter*/);
1661+
}
1662+
16391663
// Add any foreign parameters that are positioned at the start
16401664
// of the sequence. visit() will add foreign parameters that are
16411665
// positioned after any parameters it adds.
@@ -1817,7 +1841,7 @@ class DestructureInputs {
18171841
/// Add a parameter that we derived from deconstructing the
18181842
/// formal type.
18191843
void addParameter(CanType loweredType, ParameterConvention convention,
1820-
ParameterTypeFlags origFlags) {
1844+
ParameterTypeFlags origFlags, bool isImplicit = false) {
18211845
SILParameterInfo param(loweredType, convention);
18221846

18231847
if (origFlags.isNoDerivative())
@@ -1826,6 +1850,8 @@ class DestructureInputs {
18261850
param = param.addingOption(SILParameterInfo::Sending);
18271851
if (origFlags.isIsolated())
18281852
param = param.addingOption(SILParameterInfo::Isolated);
1853+
if (isImplicit)
1854+
param = param.addingOption(SILParameterInfo::ImplicitLeading);
18291855

18301856
Inputs.push_back(param);
18311857
maybeAddForeignParameters();
@@ -2465,8 +2491,17 @@ static CanSILFunctionType getSILFunctionType(
24652491
// Destructure the input tuple type.
24662492
SmallVector<SILParameterInfo, 8> inputs;
24672493
{
2494+
std::optional<ActorIsolation> actorIsolation;
2495+
if (constant) {
2496+
if (constant->kind == SILDeclRef::Kind::Deallocator) {
2497+
actorIsolation = ActorIsolation::forNonisolated(false);
2498+
} else {
2499+
actorIsolation =
2500+
getActorIsolationOfContext(constant->getInnermostDeclContext());
2501+
}
2502+
}
24682503
DestructureInputs destructurer(expansionContext, TC, conventions,
2469-
foreignInfo, inputs);
2504+
foreignInfo, actorIsolation, inputs);
24702505
destructurer.destructure(origType, substFnInterfaceType.getParams(),
24712506
extInfoBuilder, unimplementable);
24722507
}
@@ -2554,8 +2589,9 @@ static CanSILFunctionType getSILFunctionTypeForInitAccessor(
25542589
{
25552590
bool unimplementable = false;
25562591
ForeignInfo foreignInfo;
2592+
std::optional<ActorIsolation> actorIsolation; // For now always null.
25572593
DestructureInputs destructurer(context, TC, conventions, foreignInfo,
2558-
inputs);
2594+
actorIsolation, inputs);
25592595
destructurer.destructure(
25602596
origType, substAccessorType.getParams(),
25612597
extInfoBuilder.withRepresentation(SILFunctionTypeRepresentation::Thin),

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7230,22 +7230,30 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
72307230

72317231
void verifyParentFunctionSILFunctionType(CanSILFunctionType FTy) {
72327232
bool foundIsolatedParameter = false;
7233+
bool foundExplicitParameter = false;
7234+
72337235
for (const auto &parameterInfo : FTy->getParameters()) {
7236+
foundExplicitParameter |=
7237+
!parameterInfo.hasOption(SILParameterInfo::ImplicitLeading);
7238+
require(!foundExplicitParameter ||
7239+
!parameterInfo.hasOption(SILParameterInfo::ImplicitLeading),
7240+
"Implicit parameters must be before /all/ explicit parameters");
7241+
72347242
if (parameterInfo.hasOption(SILParameterInfo::Isolated)) {
7235-
auto argType = parameterInfo.getArgumentType(F.getModule(),
7236-
FTy,
7237-
F.getTypeExpansionContext());
7243+
auto argType = parameterInfo.getArgumentType(
7244+
F.getModule(), FTy, F.getTypeExpansionContext());
72387245

72397246
if (argType->isOptional())
72407247
argType = argType->lookThroughAllOptionalTypes()->getCanonicalType();
72417248

72427249
auto genericSig = FTy->getInvocationGenericSignature();
72437250
auto &ctx = F.getASTContext();
72447251
auto *actorProtocol = ctx.getProtocol(KnownProtocolKind::Actor);
7245-
auto *distributedProtocol = ctx.getProtocol(KnownProtocolKind::DistributedActor);
7252+
auto *distributedProtocol =
7253+
ctx.getProtocol(KnownProtocolKind::DistributedActor);
72467254
require(argType->isAnyActorType() ||
7247-
genericSig->requiresProtocol(argType, actorProtocol) ||
7248-
genericSig->requiresProtocol(argType, distributedProtocol),
7255+
genericSig->requiresProtocol(argType, actorProtocol) ||
7256+
genericSig->requiresProtocol(argType, distributedProtocol),
72497257
"Only any actor types can be isolated");
72507258
require(!foundIsolatedParameter, "Two isolated parameters");
72517259
foundIsolatedParameter = true;

0 commit comments

Comments
 (0)