Skip to content

Commit 3cb9bb8

Browse files
hborlaHolly Borla
authored andcommitted
[Concurrency] Serialize default argument isolation.
1 parent 7f11947 commit 3cb9bb8

13 files changed

+187
-77
lines changed

include/swift/AST/Decl.h

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1973,15 +1973,6 @@ class PatternBindingEntry {
19731973
SourceRange getOriginalInitRange() const;
19741974
void setInit(Expr *E);
19751975

1976-
/// Get the required actor isolation for evaluating the initializer
1977-
/// expression synchronously (if there is one).
1978-
///
1979-
/// If this pattern binding entry is for a stored instance property, the
1980-
/// initializer can only be used in an `init` that meets the required
1981-
/// isolation; otherwise, the property must be explicitly initialized in
1982-
/// the `init`.
1983-
ActorIsolation getInitializerIsolation() const;
1984-
19851976
/// Gets the text of the initializer expression, stripping out inactive
19861977
/// branches of any #ifs inside the expression.
19871978
StringRef getInitStringRepresentation(SmallVectorImpl<char> &scratch) const;
@@ -2235,10 +2226,6 @@ class PatternBindingDecl final : public Decl,
22352226
getMutablePatternList()[i].setOriginalInit(E);
22362227
}
22372228

2238-
ActorIsolation getInitializerIsolation(unsigned i) const {
2239-
return getPatternList()[i].getInitializerIsolation();
2240-
}
2241-
22422229
Pattern *getPattern(unsigned i) const {
22432230
return getPatternList()[i].getPattern();
22442231
}
@@ -5986,6 +5973,19 @@ class VarDecl : public AbstractStorageDecl {
59865973
return getParentExecutableInitializer() != nullptr;
59875974
}
59885975

5976+
/// Get the required actor isolation for evaluating the initializer
5977+
/// expression synchronously (if there is one).
5978+
///
5979+
/// If this VarDecl is a stored instance property, the initializer
5980+
/// can only be used in an `init` that meets the required isolation.
5981+
/// Otherwise, the property must be explicitly initialized in the `init`.
5982+
///
5983+
/// If this is a ParamDecl, the initializer isolation is required at
5984+
/// the call-site in order to use the default argument for this parameter.
5985+
/// If the required isolation is not met, an argument must be written
5986+
/// explicitly at the call-site.
5987+
ActorIsolation getInitializerIsolation() const;
5988+
59895989
// Return whether this VarDecl has an initial value, either by checking
59905990
// if it has an initializer in its parent pattern binding or if it has
59915991
// the @_hasInitialValue attribute.
@@ -6428,11 +6428,6 @@ class ParamDecl : public VarDecl {
64286428
/// at the call site in order to have the correct context information.
64296429
Expr *getTypeCheckedDefaultExpr() const;
64306430

6431-
/// The actor isolation required of the caller in order to use the
6432-
/// default argument for this parameter. If the required isolation is
6433-
/// not met, an argument must be written explicitly at the call-site.
6434-
ActorIsolation getDefaultArgumentIsolation() const;
6435-
64366431
/// Retrieve the potentially un-type-checked default argument expression for
64376432
/// this parameter, which can be queried for information such as its source
64386433
/// range and textual representation. Returns \c nullptr if there is no

include/swift/AST/TypeCheckRequests.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2938,7 +2938,7 @@ class DefaultArgumentTypeRequest
29382938
/// default initializer expression.
29392939
class DefaultInitializerIsolation
29402940
: public SimpleRequest<DefaultInitializerIsolation,
2941-
ActorIsolation(Initializer *, Expr *),
2941+
ActorIsolation(VarDecl *),
29422942
RequestFlags::Cached> {
29432943
public:
29442944
using SimpleRequest::SimpleRequest;
@@ -2947,8 +2947,7 @@ class DefaultInitializerIsolation
29472947
friend SimpleRequest;
29482948

29492949
ActorIsolation evaluate(Evaluator &evaluator,
2950-
Initializer *init,
2951-
Expr *initExpr) const;
2950+
VarDecl *) const;
29522951

29532952
public:
29542953
bool isCached() const { return true; }

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ SWIFT_REQUEST(TypeChecker, DefaultArgumentExprRequest,
6363
SWIFT_REQUEST(TypeChecker, DefaultArgumentTypeRequest,
6464
Type(ParamDecl *), SeparatelyCached, NoLocationInfo)
6565
SWIFT_REQUEST(TypeChecker, DefaultInitializerIsolation,
66-
ActorIsolation(Initializer *, Expr *),
66+
ActorIsolation(VarDecl *),
6767
Cached, NoLocationInfo)
6868
SWIFT_REQUEST(TypeChecker, DefaultArgumentInitContextRequest,
6969
Initializer *(ParamDecl *), SeparatelyCached, NoLocationInfo)

lib/AST/Decl.cpp

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,20 +1976,6 @@ void PatternBindingEntry::setInit(Expr *E) {
19761976
PatternFlags::IsText);
19771977
}
19781978

1979-
ActorIsolation PatternBindingEntry::getInitializerIsolation() const {
1980-
if (!isInitialized())
1981-
return ActorIsolation::forUnspecified();
1982-
1983-
auto *dc = cast<Initializer>(getInitContext());
1984-
auto &ctx = dc->getASTContext();
1985-
auto *initExpr = getExecutableInit();
1986-
1987-
return evaluateOrDefault(
1988-
ctx.evaluator,
1989-
DefaultInitializerIsolation{dc, initExpr},
1990-
ActorIsolation::forNonisolated());
1991-
}
1992-
19931979
VarDecl *PatternBindingEntry::getAnchoringVarDecl() const {
19941980
SmallVector<VarDecl *, 8> variables;
19951981
getPattern()->collectVariables(variables);
@@ -7141,6 +7127,14 @@ Expr *VarDecl::getParentExecutableInitializer() const {
71417127
return nullptr;
71427128
}
71437129

7130+
ActorIsolation VarDecl::getInitializerIsolation() const {
7131+
auto *mutableThis = const_cast<VarDecl *>(this);
7132+
return evaluateOrDefault(
7133+
getASTContext().evaluator,
7134+
DefaultInitializerIsolation{mutableThis},
7135+
ActorIsolation::forUnspecified());
7136+
}
7137+
71447138
SourceRange VarDecl::getSourceRange() const {
71457139
if (auto Param = dyn_cast<ParamDecl>(this))
71467140
return Param->getSourceRange();
@@ -8277,34 +8271,6 @@ Type ParamDecl::getTypeOfDefaultExpr() const {
82778271
return Type();
82788272
}
82798273

8280-
ActorIsolation ParamDecl::getDefaultArgumentIsolation() const {
8281-
// If this parameter corresponds to a stored property for a
8282-
// memberwise initializer, the default argument is the default
8283-
// initializer expression.
8284-
auto *var = getStoredProperty();
8285-
if (var && !var->isInvalid()) {
8286-
// FIXME: Force computation of property wrapper initializers.
8287-
if (auto *wrapped = var->getOriginalWrappedProperty())
8288-
(void)wrapped->getPropertyWrapperInitializerInfo();
8289-
8290-
auto *pbd = var->getParentPatternBinding();
8291-
auto i = pbd->getPatternEntryIndexForVarDecl(var);
8292-
return var->getParentPatternBinding()->getInitializerIsolation(i);
8293-
}
8294-
8295-
if (!hasDefaultExpr())
8296-
return ActorIsolation::forUnspecified();
8297-
8298-
auto &ctx = getASTContext();
8299-
auto *dc = getDefaultArgumentInitContext();
8300-
auto *initExpr = getTypeCheckedDefaultExpr();
8301-
8302-
return evaluateOrDefault(
8303-
ctx.evaluator,
8304-
DefaultInitializerIsolation{dc, initExpr},
8305-
ActorIsolation::forNonisolated());
8306-
}
8307-
83088274
void ParamDecl::setDefaultExpr(Expr *E, bool isTypeChecked) {
83098275
if (!DefaultValueAndFlags.getPointer()) {
83108276
if (!E) return;

lib/AST/Expr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,8 +1608,7 @@ Expr *DefaultArgumentExpr::getCallerSideDefaultExpr() const {
16081608

16091609
ActorIsolation
16101610
DefaultArgumentExpr::getRequiredIsolation() const {
1611-
auto *param = getParamDecl();
1612-
return param->getDefaultArgumentIsolation();
1611+
return getParamDecl()->getInitializerIsolation();
16131612
}
16141613

16151614
ValueDecl *ApplyExpr::getCalledValue(bool skipFunctionConversions) const {

lib/SILGen/SILGenConstructor.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1547,7 +1547,8 @@ void SILGenFunction::emitMemberInitializer(DeclContext *dc, VarDecl *selfDecl,
15471547
// initializer from being evaluated synchronously (or propagating required
15481548
// isolation through closure bodies), then the default value cannot be used
15491549
// and the member must be explicitly initialized in the constructor.
1550-
auto requiredIsolation = field->getInitializerIsolation(i);
1550+
auto *var = field->getAnchoringVarDecl(i);
1551+
auto requiredIsolation = var->getInitializerIsolation();
15511552
auto contextIsolation = getActorIsolationOfContext(dc);
15521553
switch (requiredIsolation) {
15531554
// 'nonisolated' expressions can be evaluated from anywhere

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,7 @@ static void checkDefaultArguments(ParameterList *params) {
10691069
for (auto *param : *params) {
10701070
auto ifacety = param->getInterfaceType();
10711071
auto *expr = param->getTypeCheckedDefaultExpr();
1072-
(void)param->getDefaultArgumentIsolation();
1072+
(void)param->getInitializerIsolation();
10731073

10741074
if (!ifacety->hasPlaceholder()) {
10751075
continue;
@@ -1158,12 +1158,43 @@ Expr *DefaultArgumentExprRequest::evaluate(Evaluator &evaluator,
11581158

11591159
ActorIsolation
11601160
DefaultInitializerIsolation::evaluate(Evaluator &evaluator,
1161-
Initializer *init,
1162-
Expr *initExpr) const {
1163-
if (!init || !initExpr)
1161+
VarDecl *var) const {
1162+
if (var->isInvalid())
11641163
return ActorIsolation::forUnspecified();
11651164

1166-
return computeRequiredIsolation(init, initExpr);
1165+
Initializer *dc = nullptr;
1166+
Expr *initExpr = nullptr;
1167+
1168+
if (auto *pbd = var->getParentPatternBinding()) {
1169+
if (!var->isParentInitialized())
1170+
return ActorIsolation::forUnspecified();
1171+
1172+
auto i = pbd->getPatternEntryIndexForVarDecl(var);
1173+
dc = cast<Initializer>(pbd->getInitContext(i));
1174+
initExpr = var->getParentInitializer();
1175+
} else if (auto *param = dyn_cast<ParamDecl>(var)) {
1176+
// If this parameter corresponds to a stored property for a
1177+
// memberwise initializer, the default argument is the default
1178+
// initializer expression.
1179+
if (auto *property = param->getStoredProperty()) {
1180+
// FIXME: Force computation of property wrapper initializers.
1181+
if (auto *wrapped = property->getOriginalWrappedProperty())
1182+
(void)property->getPropertyWrapperInitializerInfo();
1183+
1184+
return property->getInitializerIsolation();
1185+
}
1186+
1187+
if (!param->hasDefaultExpr())
1188+
return ActorIsolation::forUnspecified();
1189+
1190+
dc = param->getDefaultArgumentInitContext();
1191+
initExpr = param->getTypeCheckedDefaultExpr();
1192+
}
1193+
1194+
if (!dc || !initExpr)
1195+
return ActorIsolation::forUnspecified();
1196+
1197+
return computeRequiredIsolation(dc, initExpr);
11671198
}
11681199

11691200
Type DefaultArgumentTypeRequest::evaluate(Evaluator &evaluator,
@@ -2476,7 +2507,11 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
24762507
PBD->getInitContext(i));
24772508
if (initContext) {
24782509
TypeChecker::contextualizeInitializer(initContext, init);
2479-
(void)PBD->getInitializerIsolation(i);
2510+
if (auto *singleVar = PBD->getSingleVar()) {
2511+
(void)singleVar->getInitializerIsolation();
2512+
} else {
2513+
computeRequiredIsolation(initContext, init);
2514+
}
24802515
TypeChecker::checkInitializerEffects(initContext, init);
24812516
}
24822517
}

lib/Sema/TypeCheckStorage.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3226,7 +3226,7 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator,
32263226
// synthesize a computed property for '$foo'.
32273227
Expr *projectedValueInit = nullptr;
32283228
if (auto *projection = var->getPropertyWrapperProjectionVar()) {
3229-
auto *pbd = createPBD(projection);
3229+
createPBD(projection);
32303230

32313231
if (var->hasExternalPropertyWrapper()) {
32323232
// Projected-value initialization is currently only supported for parameters.
@@ -3240,7 +3240,7 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator,
32403240
// Check initializer effects.
32413241
auto *initContext = new (ctx) PropertyWrapperInitializer(
32423242
dc, param, PropertyWrapperInitializer::Kind::ProjectedValue);
3243-
(void)pbd->getInitializerIsolation(0);
3243+
(void)projection->getInitializerIsolation();
32443244
TypeChecker::checkInitializerEffects(initContext, projectedValueInit);
32453245
}
32463246
}

lib/Serialization/Deserialization.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,22 @@ getActualDefaultArgKind(uint8_t raw) {
455455
return llvm::None;
456456
}
457457

458+
static llvm::Optional<swift::ActorIsolation::Kind>
459+
getActualActorIsolationKind(uint8_t raw) {
460+
switch (static_cast<serialization::ActorIsolation>(raw)) {
461+
#define CASE(X) \
462+
case serialization::ActorIsolation::X: \
463+
return swift::ActorIsolation::Kind::X;
464+
CASE(Unspecified)
465+
CASE(ActorInstance)
466+
CASE(Nonisolated)
467+
CASE(GlobalActor)
468+
CASE(GlobalActorUnsafe)
469+
#undef CASE
470+
}
471+
return llvm::None;
472+
}
473+
458474
static llvm::Optional<StableSerializationPath::ExternalPath::ComponentKind>
459475
getActualClangDeclPathComponentKind(uint64_t raw) {
460476
switch (static_cast<serialization::ClangDeclPathComponentKind>(raw)) {
@@ -3764,14 +3780,18 @@ class DeclDeserializer {
37643780
bool isCompileTimeConst;
37653781
uint8_t rawDefaultArg;
37663782
TypeID defaultExprType;
3783+
uint8_t rawDefaultArgIsolation;
3784+
TypeID globalActorTypeID;
37673785

37683786
decls_block::ParamLayout::readRecord(scratch, argNameID, paramNameID,
37693787
contextID, rawSpecifier,
37703788
interfaceTypeID, isIUO, isVariadic,
37713789
isAutoClosure, isIsolated,
37723790
isCompileTimeConst,
37733791
rawDefaultArg,
3774-
defaultExprType);
3792+
defaultExprType,
3793+
rawDefaultArgIsolation,
3794+
globalActorTypeID);
37753795

37763796
auto argName = MF.getIdentifier(argNameID);
37773797
auto paramName = MF.getIdentifier(paramNameID);
@@ -3816,6 +3836,29 @@ class DeclDeserializer {
38163836
if (auto exprType = MF.getType(defaultExprType))
38173837
param->setDefaultExprType(exprType);
38183838

3839+
auto isoKind = *getActualActorIsolationKind(rawDefaultArgIsolation);
3840+
auto globalActor = MF.getType(globalActorTypeID);
3841+
ActorIsolation isolation;
3842+
switch (isoKind) {
3843+
case ActorIsolation::Unspecified:
3844+
case ActorIsolation::Nonisolated:
3845+
isolation = ActorIsolation::forUnspecified();
3846+
break;
3847+
3848+
case ActorIsolation::GlobalActor:
3849+
case ActorIsolation::GlobalActorUnsafe:
3850+
isolation = ActorIsolation::forGlobalActor(
3851+
globalActor, isoKind == ActorIsolation::GlobalActorUnsafe);
3852+
break;
3853+
3854+
case ActorIsolation::ActorInstance:
3855+
llvm_unreachable("default arg cannot be actor instance isolated");
3856+
}
3857+
3858+
ctx.evaluator.cacheOutput(
3859+
DefaultInitializerIsolation{param},
3860+
std::move(isolation));
3861+
38193862
if (!blobData.empty())
38203863
param->setDefaultValueStringRepresentation(blobData);
38213864
}

lib/Serialization/ModuleFormat.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 810; // access enforcement
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 811; // default argument isolation
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -526,6 +526,17 @@ enum class DefaultArgumentKind : uint8_t {
526526
};
527527
using DefaultArgumentField = BCFixed<4>;
528528

529+
/// These IDs must \em not be renumbered or reordered without incrementing
530+
/// the module version.
531+
enum class ActorIsolation : uint8_t {
532+
Unspecified = 0,
533+
ActorInstance,
534+
Nonisolated,
535+
GlobalActor,
536+
GlobalActorUnsafe
537+
};
538+
using ActorIsolationField = BCFixed<3>;
539+
529540
// These IDs must \em not be renumbered or reordered without incrementing
530541
// the module version.
531542
enum LibraryKind : uint8_t {
@@ -1568,6 +1579,8 @@ namespace decls_block {
15681579
BCFixed<1>, // isCompileTimeConst?
15691580
DefaultArgumentField, // default argument kind
15701581
TypeIDField, // default argument type
1582+
ActorIsolationField, // default argument isolation
1583+
TypeIDField, // global actor isolation
15711584
BCBlob // default argument text
15721585
>;
15731586

0 commit comments

Comments
 (0)