Skip to content

Commit db69307

Browse files
committed
[Concurrency] Serialize default argument isolation.
(cherry picked from commit 3cb9bb8)
1 parent 453585d commit db69307

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
@@ -1955,15 +1955,6 @@ class PatternBindingEntry {
19551955
SourceRange getOriginalInitRange() const;
19561956
void setInit(Expr *E);
19571957

1958-
/// Get the required actor isolation for evaluating the initializer
1959-
/// expression synchronously (if there is one).
1960-
///
1961-
/// If this pattern binding entry is for a stored instance property, the
1962-
/// initializer can only be used in an `init` that meets the required
1963-
/// isolation; otherwise, the property must be explicitly initialized in
1964-
/// the `init`.
1965-
ActorIsolation getInitializerIsolation() const;
1966-
19671958
/// Gets the text of the initializer expression, stripping out inactive
19681959
/// branches of any #ifs inside the expression.
19691960
StringRef getInitStringRepresentation(SmallVectorImpl<char> &scratch) const;
@@ -2212,10 +2203,6 @@ class PatternBindingDecl final : public Decl,
22122203
getMutablePatternList()[i].setOriginalInit(E);
22132204
}
22142205

2215-
ActorIsolation getInitializerIsolation(unsigned i) const {
2216-
return getPatternList()[i].getInitializerIsolation();
2217-
}
2218-
22192206
Pattern *getPattern(unsigned i) const {
22202207
return getPatternList()[i].getPattern();
22212208
}
@@ -5948,6 +5935,19 @@ class VarDecl : public AbstractStorageDecl {
59485935
return getParentExecutableInitializer() != nullptr;
59495936
}
59505937

5938+
/// Get the required actor isolation for evaluating the initializer
5939+
/// expression synchronously (if there is one).
5940+
///
5941+
/// If this VarDecl is a stored instance property, the initializer
5942+
/// can only be used in an `init` that meets the required isolation.
5943+
/// Otherwise, the property must be explicitly initialized in the `init`.
5944+
///
5945+
/// If this is a ParamDecl, the initializer isolation is required at
5946+
/// the call-site in order to use the default argument for this parameter.
5947+
/// If the required isolation is not met, an argument must be written
5948+
/// explicitly at the call-site.
5949+
ActorIsolation getInitializerIsolation() const;
5950+
59515951
// Return whether this VarDecl has an initial value, either by checking
59525952
// if it has an initializer in its parent pattern binding or if it has
59535953
// the @_hasInitialValue attribute.
@@ -6390,11 +6390,6 @@ class ParamDecl : public VarDecl {
63906390
/// at the call site in order to have the correct context information.
63916391
Expr *getTypeCheckedDefaultExpr() const;
63926392

6393-
/// The actor isolation required of the caller in order to use the
6394-
/// default argument for this parameter. If the required isolation is
6395-
/// not met, an argument must be written explicitly at the call-site.
6396-
ActorIsolation getDefaultArgumentIsolation() const;
6397-
63986393
/// Retrieve the potentially un-type-checked default argument expression for
63996394
/// this parameter, which can be queried for information such as its source
64006395
/// 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
@@ -2915,7 +2915,7 @@ class DefaultArgumentTypeRequest
29152915
/// default initializer expression.
29162916
class DefaultInitializerIsolation
29172917
: public SimpleRequest<DefaultInitializerIsolation,
2918-
ActorIsolation(Initializer *, Expr *),
2918+
ActorIsolation(VarDecl *),
29192919
RequestFlags::Cached> {
29202920
public:
29212921
using SimpleRequest::SimpleRequest;
@@ -2924,8 +2924,7 @@ class DefaultInitializerIsolation
29242924
friend SimpleRequest;
29252925

29262926
ActorIsolation evaluate(Evaluator &evaluator,
2927-
Initializer *init,
2928-
Expr *initExpr) const;
2927+
VarDecl *) const;
29292928

29302929
public:
29312930
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
@@ -1953,20 +1953,6 @@ void PatternBindingEntry::setInit(Expr *E) {
19531953
PatternFlags::IsText);
19541954
}
19551955

1956-
ActorIsolation PatternBindingEntry::getInitializerIsolation() const {
1957-
if (!isInitialized())
1958-
return ActorIsolation::forUnspecified();
1959-
1960-
auto *dc = cast<Initializer>(getInitContext());
1961-
auto &ctx = dc->getASTContext();
1962-
auto *initExpr = getExecutableInit();
1963-
1964-
return evaluateOrDefault(
1965-
ctx.evaluator,
1966-
DefaultInitializerIsolation{dc, initExpr},
1967-
ActorIsolation::forNonisolated());
1968-
}
1969-
19701956
VarDecl *PatternBindingEntry::getAnchoringVarDecl() const {
19711957
SmallVector<VarDecl *, 8> variables;
19721958
getPattern()->collectVariables(variables);
@@ -7060,6 +7046,14 @@ Expr *VarDecl::getParentExecutableInitializer() const {
70607046
return nullptr;
70617047
}
70627048

7049+
ActorIsolation VarDecl::getInitializerIsolation() const {
7050+
auto *mutableThis = const_cast<VarDecl *>(this);
7051+
return evaluateOrDefault(
7052+
getASTContext().evaluator,
7053+
DefaultInitializerIsolation{mutableThis},
7054+
ActorIsolation::forUnspecified());
7055+
}
7056+
70637057
SourceRange VarDecl::getSourceRange() const {
70647058
if (auto Param = dyn_cast<ParamDecl>(this))
70657059
return Param->getSourceRange();
@@ -8172,34 +8166,6 @@ Type ParamDecl::getTypeOfDefaultExpr() const {
81728166
return Type();
81738167
}
81748168

8175-
ActorIsolation ParamDecl::getDefaultArgumentIsolation() const {
8176-
// If this parameter corresponds to a stored property for a
8177-
// memberwise initializer, the default argument is the default
8178-
// initializer expression.
8179-
auto *var = getStoredProperty();
8180-
if (var && !var->isInvalid()) {
8181-
// FIXME: Force computation of property wrapper initializers.
8182-
if (auto *wrapped = var->getOriginalWrappedProperty())
8183-
(void)wrapped->getPropertyWrapperInitializerInfo();
8184-
8185-
auto *pbd = var->getParentPatternBinding();
8186-
auto i = pbd->getPatternEntryIndexForVarDecl(var);
8187-
return var->getParentPatternBinding()->getInitializerIsolation(i);
8188-
}
8189-
8190-
if (!hasDefaultExpr())
8191-
return ActorIsolation::forUnspecified();
8192-
8193-
auto &ctx = getASTContext();
8194-
auto *dc = getDefaultArgumentInitContext();
8195-
auto *initExpr = getTypeCheckedDefaultExpr();
8196-
8197-
return evaluateOrDefault(
8198-
ctx.evaluator,
8199-
DefaultInitializerIsolation{dc, initExpr},
8200-
ActorIsolation::forNonisolated());
8201-
}
8202-
82038169
void ParamDecl::setDefaultExpr(Expr *E, bool isTypeChecked) {
82048170
if (!DefaultValueAndFlags.getPointer()) {
82058171
if (!E) return;

lib/AST/Expr.cpp

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

16041604
ActorIsolation
16051605
DefaultArgumentExpr::getRequiredIsolation() const {
1606-
auto *param = getParamDecl();
1607-
return param->getDefaultArgumentIsolation();
1606+
return getParamDecl()->getInitializerIsolation();
16081607
}
16091608

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

lib/SILGen/SILGenConstructor.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1531,7 +1531,8 @@ void SILGenFunction::emitMemberInitializer(DeclContext *dc, VarDecl *selfDecl,
15311531
// initializer from being evaluated synchronously (or propagating required
15321532
// isolation through closure bodies), then the default value cannot be used
15331533
// and the member must be explicitly initialized in the constructor.
1534-
auto requiredIsolation = field->getInitializerIsolation(i);
1534+
auto *var = field->getAnchoringVarDecl(i);
1535+
auto requiredIsolation = var->getInitializerIsolation();
15351536
auto contextIsolation = getActorIsolationOfContext(dc);
15361537
switch (requiredIsolation) {
15371538
// '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
@@ -3210,7 +3210,7 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator,
32103210
// synthesize a computed property for '$foo'.
32113211
Expr *projectedValueInit = nullptr;
32123212
if (auto *projection = var->getPropertyWrapperProjectionVar()) {
3213-
auto *pbd = createPBD(projection);
3213+
createPBD(projection);
32143214

32153215
if (var->hasExternalPropertyWrapper()) {
32163216
// Projected-value initialization is currently only supported for parameters.
@@ -3224,7 +3224,7 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator,
32243224
// Check initializer effects.
32253225
auto *initContext = new (ctx) PropertyWrapperInitializer(
32263226
dc, param, PropertyWrapperInitializer::Kind::ProjectedValue);
3227-
(void)pbd->getInitializerIsolation(0);
3227+
(void)projection->getInitializerIsolation();
32283228
TypeChecker::checkInitializerEffects(initContext, projectedValueInit);
32293229
}
32303230
}

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)) {
@@ -3756,14 +3772,18 @@ class DeclDeserializer {
37563772
bool isCompileTimeConst;
37573773
uint8_t rawDefaultArg;
37583774
TypeID defaultExprType;
3775+
uint8_t rawDefaultArgIsolation;
3776+
TypeID globalActorTypeID;
37593777

37603778
decls_block::ParamLayout::readRecord(scratch, argNameID, paramNameID,
37613779
contextID, rawSpecifier,
37623780
interfaceTypeID, isIUO, isVariadic,
37633781
isAutoClosure, isIsolated,
37643782
isCompileTimeConst,
37653783
rawDefaultArg,
3766-
defaultExprType);
3784+
defaultExprType,
3785+
rawDefaultArgIsolation,
3786+
globalActorTypeID);
37673787

37683788
auto argName = MF.getIdentifier(argNameID);
37693789
auto paramName = MF.getIdentifier(paramNameID);
@@ -3808,6 +3828,29 @@ class DeclDeserializer {
38083828
if (auto exprType = MF.getType(defaultExprType))
38093829
param->setDefaultExprType(exprType);
38103830

3831+
auto isoKind = *getActualActorIsolationKind(rawDefaultArgIsolation);
3832+
auto globalActor = MF.getType(globalActorTypeID);
3833+
ActorIsolation isolation;
3834+
switch (isoKind) {
3835+
case ActorIsolation::Unspecified:
3836+
case ActorIsolation::Nonisolated:
3837+
isolation = ActorIsolation::forUnspecified();
3838+
break;
3839+
3840+
case ActorIsolation::GlobalActor:
3841+
case ActorIsolation::GlobalActorUnsafe:
3842+
isolation = ActorIsolation::forGlobalActor(
3843+
globalActor, isoKind == ActorIsolation::GlobalActorUnsafe);
3844+
break;
3845+
3846+
case ActorIsolation::ActorInstance:
3847+
llvm_unreachable("default arg cannot be actor instance isolated");
3848+
}
3849+
3850+
ctx.evaluator.cacheOutput(
3851+
DefaultInitializerIsolation{param},
3852+
std::move(isolation));
3853+
38113854
if (!blobData.empty())
38123855
param->setDefaultValueStringRepresentation(blobData);
38133856
}

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 = 804; // embedded swift modules
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 805; // default argument isolation
6262

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

525+
/// These IDs must \em not be renumbered or reordered without incrementing
526+
/// the module version.
527+
enum class ActorIsolation : uint8_t {
528+
Unspecified = 0,
529+
ActorInstance,
530+
Nonisolated,
531+
GlobalActor,
532+
GlobalActorUnsafe
533+
};
534+
using ActorIsolationField = BCFixed<3>;
535+
525536
// These IDs must \em not be renumbered or reordered without incrementing
526537
// the module version.
527538
enum LibraryKind : uint8_t {
@@ -1561,6 +1572,8 @@ namespace decls_block {
15611572
BCFixed<1>, // isCompileTimeConst?
15621573
DefaultArgumentField, // default argument kind
15631574
TypeIDField, // default argument type
1575+
ActorIsolationField, // default argument isolation
1576+
TypeIDField, // global actor isolation
15641577
BCBlob // default argument text
15651578
>;
15661579

0 commit comments

Comments
 (0)