Skip to content

Commit a7c6a1a

Browse files
committed
Eliminate circular references while checking property wrapper isolation
1 parent 614dcfc commit a7c6a1a

File tree

4 files changed

+78
-36
lines changed

4 files changed

+78
-36
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2398,47 +2398,47 @@ ActorIsolation ActorIsolationRequest::evaluate(
23982398
return getActorIsolation(accessor->getStorage());
23992399
}
24002400

2401-
if (shouldInferAttributeInContext(value->getDeclContext())) {
2402-
if (auto var = dyn_cast<VarDecl>(value)) {
2403-
// If this is a variable with a property wrapper, infer from the property
2404-
// wrapper's wrappedValue.
2405-
if (auto wrapperInfo = var->getAttachedPropertyWrapperTypeInfo(0)) {
2406-
if (auto wrappedValue = wrapperInfo.valueVar) {
2407-
if (auto isolation = getActorIsolation(wrappedValue))
2408-
return inferredIsolation(isolation, /*propagateUnsafe=*/true);
2409-
}
2410-
}
2411-
2412-
// If this is the backing storage for a property wrapper, infer from the
2413-
// type of the outermost property wrapper.
2414-
if (auto originalVar = var->getOriginalWrappedProperty(
2415-
PropertyWrapperSynthesizedPropertyKind::Backing)) {
2416-
if (auto backingType =
2417-
originalVar->getPropertyWrapperBackingPropertyType()) {
2418-
if (auto backingNominal = backingType->getAnyNominal()) {
2419-
if (!isa<ClassDecl>(backingNominal) ||
2420-
!cast<ClassDecl>(backingNominal)->isActor()) {
2421-
if (auto isolation = getActorIsolation(backingNominal))
2422-
return inferredIsolation(isolation, /*propagateUnsafe=*/true);
2423-
}
2401+
if (auto var = dyn_cast<VarDecl>(value)) {
2402+
// If this is a variable with a property wrapper, infer from the property
2403+
// wrapper's wrappedValue.
2404+
if (auto wrapperInfo = var->getAttachedPropertyWrapperTypeInfo(0)) {
2405+
if (auto wrappedValue = wrapperInfo.valueVar) {
2406+
if (auto isolation = getActorIsolation(wrappedValue))
2407+
return inferredIsolation(isolation, /*propagateUnsafe=*/true);
2408+
}
2409+
}
2410+
2411+
// If this is the backing storage for a property wrapper, infer from the
2412+
// type of the outermost property wrapper.
2413+
if (auto originalVar = var->getOriginalWrappedProperty(
2414+
PropertyWrapperSynthesizedPropertyKind::Backing)) {
2415+
if (auto backingType =
2416+
originalVar->getPropertyWrapperBackingPropertyType()) {
2417+
if (auto backingNominal = backingType->getAnyNominal()) {
2418+
if (!isa<ClassDecl>(backingNominal) ||
2419+
!cast<ClassDecl>(backingNominal)->isActor()) {
2420+
if (auto isolation = getActorIsolation(backingNominal))
2421+
return inferredIsolation(isolation, /*propagateUnsafe=*/true);
24242422
}
24252423
}
24262424
}
2425+
}
24272426

2428-
// If this is the projected property for a property wrapper, infer from
2429-
// the property wrapper's projectedValue.
2430-
if (auto originalVar = var->getOriginalWrappedProperty(
2431-
PropertyWrapperSynthesizedPropertyKind::Projection)) {
2432-
if (auto wrapperInfo =
2433-
originalVar->getAttachedPropertyWrapperTypeInfo(0)) {
2434-
if (auto projectedValue = wrapperInfo.projectedValueVar) {
2435-
if (auto isolation = getActorIsolation(projectedValue))
2436-
return inferredIsolation(isolation, /*propagateUnsafe=*/true);
2437-
}
2427+
// If this is the projected property for a property wrapper, infer from
2428+
// the property wrapper's projectedValue.
2429+
if (auto originalVar = var->getOriginalWrappedProperty(
2430+
PropertyWrapperSynthesizedPropertyKind::Projection)) {
2431+
if (auto wrapperInfo =
2432+
originalVar->getAttachedPropertyWrapperTypeInfo(0)) {
2433+
if (auto projectedValue = wrapperInfo.projectedValueVar) {
2434+
if (auto isolation = getActorIsolation(projectedValue))
2435+
return inferredIsolation(isolation, /*propagateUnsafe=*/true);
24382436
}
24392437
}
24402438
}
2439+
}
24412440

2441+
if (shouldInferAttributeInContext(value->getDeclContext())) {
24422442
// If the declaration witnesses a protocol requirement that is isolated,
24432443
// use that.
24442444
if (auto witnessedIsolation = getIsolationFromWitnessedRequirements(value)) {
@@ -2615,6 +2615,13 @@ static bool shouldDiagnoseExistingDataRaces(const DeclContext *dc) {
26152615
// features.
26162616
if (func->getAttrs().hasAttribute<AsyncHandlerAttr>())
26172617
return true;
2618+
2619+
// If we're in an accessor declaration, also check the storage
2620+
// declaration.
2621+
if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
2622+
if (getIsolationFromAttributes(accessor->getStorage()))
2623+
return true;
2624+
}
26182625
}
26192626
}
26202627

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1766,6 +1766,29 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
17661766
});
17671767
}
17681768

1769+
/// If the given pattern binding has a property wrapper, check the
1770+
/// isolation and effects of the backing storage initializer.
1771+
void checkPropertyWrapperBackingInitializer(PatternBindingDecl *PBD) {
1772+
auto singleVar = PBD->getSingleVar();
1773+
if (!singleVar)
1774+
return;
1775+
1776+
if (!singleVar->hasAttachedPropertyWrapper())
1777+
return;
1778+
1779+
auto backingInfo = singleVar->getPropertyWrapperBackingPropertyInfo();
1780+
if (!backingInfo)
1781+
return;
1782+
1783+
auto backingPBD = backingInfo.backingVar->getParentPatternBinding();
1784+
if (!backingPBD)
1785+
return;
1786+
1787+
if (auto initializer = backingInfo.getInitFromWrappedValue()) {
1788+
checkPropertyWrapperActorIsolation(backingPBD, initializer);
1789+
TypeChecker::checkPropertyWrapperEffects(backingPBD, initializer);
1790+
}
1791+
}
17691792

17701793
void visitPatternBindingDecl(PatternBindingDecl *PBD) {
17711794
DeclContext *DC = PBD->getDeclContext();
@@ -1913,6 +1936,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
19131936
}
19141937
}
19151938
}
1939+
1940+
checkPropertyWrapperBackingInitializer(PBD);
19161941
}
19171942

19181943
void visitSubscriptDecl(SubscriptDecl *SD) {

lib/Sema/TypeCheckStorage.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2528,8 +2528,6 @@ static void typeCheckSynthesizedWrapperInitializer(
25282528
dyn_cast_or_null<Initializer>(pbd->getInitContext(i))) {
25292529
TypeChecker::contextualizeInitializer(initializerContext, initializer);
25302530
}
2531-
checkPropertyWrapperActorIsolation(pbd, initializer);
2532-
TypeChecker::checkPropertyWrapperEffects(pbd, initializer);
25332531
}
25342532

25352533
static PropertyWrapperMutability::Value
@@ -2875,6 +2873,8 @@ PropertyWrapperBackingPropertyInfoRequest::evaluate(Evaluator &evaluator,
28752873
// Check initializer effects.
28762874
auto *initContext = new (ctx) PropertyWrapperInitializer(
28772875
dc, param, PropertyWrapperInitializer::Kind::WrappedValue);
2876+
TypeChecker::contextualizeInitializer(initContext, wrappedValueInit);
2877+
checkInitializerActorIsolation(initContext, wrappedValueInit);
28782878
TypeChecker::checkInitializerEffects(initContext, wrappedValueInit);
28792879
} else {
28802880
typeCheckSynthesizedWrapperInitializer(

test/Concurrency/global_actor_inference.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ func barSync() {
243243
struct WrapperOnActor<Wrapped> {
244244
@actorIndependent(unsafe) private var stored: Wrapped
245245

246-
init(wrappedValue: Wrapped) {
246+
@actorIndependent init(wrappedValue: Wrapped) {
247247
stored = wrappedValue
248248
}
249249

@@ -336,6 +336,16 @@ actor WrapperActorBad2<Wrapped> {
336336
}
337337
}
338338

339+
actor ActorWithWrapper {
340+
@WrapperOnActor var synced: Int = 0
341+
// expected-note@-1 3{{mutable state is only available within the actor instance}}
342+
func f() {
343+
_ = synced // expected-error{{'synced' isolated to global actor}}
344+
_ = $synced // expected-error{{'$synced' isolated to global actor}}
345+
_ = _synced // expected-error{{'_synced' isolated to global actor}}
346+
}
347+
}
348+
339349
// ----------------------------------------------------------------------
340350
// Unsafe global actors
341351
// ----------------------------------------------------------------------

0 commit comments

Comments
 (0)