Skip to content

Commit 58826ed

Browse files
authored
Merge pull request #41609 from kavon/downgrade-tres
downgrade actor deinit accesses to warnings in more contexts
2 parents 1da5816 + 8dcb761 commit 58826ed

File tree

3 files changed

+72
-23
lines changed

3 files changed

+72
-23
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4500,9 +4500,10 @@ NOTE(note_distributed_actor_system_conformance_missing_adhoc_requirement,none,
45004500
ERROR(override_implicit_unowned_executor,none,
45014501
"cannot override an actor's 'unownedExecutor' property that wasn't "
45024502
"explicitly defined", ())
4503-
ERROR(actor_isolated_from_deinit,none,
4504-
"actor-isolated %0 %1 can not be referenced from a non-isolated deinit",
4505-
(DescriptiveDeclKind, DeclName))
4503+
ERROR(actor_isolated_from_decl,none,
4504+
"actor-isolated %0 %1 can not be referenced from a non-isolated "
4505+
"%select{deinit|autoclosure|closure}2",
4506+
(DescriptiveDeclKind, DeclName, unsigned))
45064507
ERROR(actor_isolated_non_self_reference,none,
45074508
"actor-isolated %0 %1 can not be "
45084509
"%select{referenced|mutated|used 'inout'}2 "

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2689,6 +2689,52 @@ namespace {
26892689
});
26902690
}
26912691

2692+
static bool isStoredProperty(ValueDecl const *member) {
2693+
if (auto *var = dyn_cast<VarDecl>(member))
2694+
if (var->hasStorage() && var->isInstanceMember())
2695+
return true;
2696+
return false;
2697+
}
2698+
2699+
/// an ad-hoc check specific to member isolation checking.
2700+
static bool memberAccessWasAllowedInSwift5(DeclContext const *refCxt,
2701+
ValueDecl const *member,
2702+
SourceLoc memberLoc) {
2703+
// no need for this in Swift 6+
2704+
if (refCxt->getASTContext().isSwiftVersionAtLeast(6))
2705+
return false;
2706+
2707+
// In Swift 5, we were allowing all members to be referenced from a
2708+
// deinit, nested within a wide variety of contexts.
2709+
if (auto oldFn = isActorInitOrDeInitContext(refCxt)) {
2710+
if (isa<DestructorDecl>(oldFn) && member->isInstanceMember()) {
2711+
auto &diags = refCxt->getASTContext().Diags;
2712+
2713+
// if the context in which we consider the access matches between
2714+
// old and new, and its a stored property, then skip the warning
2715+
// because it will still be allowed in Swift 6.
2716+
if (!(refCxt == oldFn && isStoredProperty(member))) {
2717+
unsigned cxtKind = 0; // deinit
2718+
2719+
// try to get a better name for this context.
2720+
if (isa<AutoClosureExpr>(refCxt)) {
2721+
cxtKind = 1;
2722+
} else if (isa<AbstractClosureExpr>(refCxt)) {
2723+
cxtKind = 2;
2724+
}
2725+
2726+
diags.diagnose(memberLoc, diag::actor_isolated_from_decl,
2727+
member->getDescriptiveKind(),
2728+
member->getName(),
2729+
cxtKind).warnUntilSwiftVersion(6);
2730+
}
2731+
return true;
2732+
}
2733+
}
2734+
2735+
return false;
2736+
}
2737+
26922738
/// To support flow-isolation, some member accesses in inits / deinits
26932739
/// must be permitted, despite the isolation of 'self' not being
26942740
/// correct in Sema.
@@ -2700,7 +2746,7 @@ namespace {
27002746
///
27012747
/// \returns true iff the member access is permitted in Sema because it will
27022748
/// be verified later by flow-isolation.
2703-
bool checkedByFlowIsolation(DeclContext const *refCxt,
2749+
static bool checkedByFlowIsolation(DeclContext const *refCxt,
27042750
ReferencedActor &baseActor,
27052751
ValueDecl const *member,
27062752
SourceLoc memberLoc) {
@@ -2719,7 +2765,7 @@ namespace {
27192765
while (true) {
27202766
fnDecl = dyn_cast_or_null<AbstractFunctionDecl>(refCxt->getAsDecl());
27212767
if (!fnDecl)
2722-
return false;
2768+
break;
27232769

27242770
// go up one level if this context is a defer.
27252771
if (auto *d = dyn_cast<FuncDecl>(fnDecl)) {
@@ -2731,25 +2777,15 @@ namespace {
27312777
break;
27322778
}
27332779

2780+
if (memberAccessWasAllowedInSwift5(refCxt, member, memberLoc))
2781+
return true; // then permit it now.
2782+
27342783
if (!usesFlowSensitiveIsolation(fnDecl))
27352784
return false;
27362785

27372786
// Stored properties are definitely OK.
2738-
if (auto *var = dyn_cast<VarDecl>(member))
2739-
if (var->hasStorage() && var->isInstanceMember())
2740-
return true;
2741-
2742-
// In Swift 5, we were allowing all members to be referenced from a
2743-
// deinit, but that will not be valid in Swift 6+, so warn about it.
2744-
if (!refCxt->getASTContext().isSwiftVersionAtLeast(6)) {
2745-
if (isa<DestructorDecl>(fnDecl) && member->isInstanceMember()) {
2746-
auto &diags = refCxt->getASTContext().Diags;
2747-
diags.diagnose(memberLoc, diag::actor_isolated_from_deinit,
2748-
member->getDescriptiveKind(),
2749-
member->getName()).warnUntilSwiftVersion(6);
2787+
if (isStoredProperty(member))
27502788
return true;
2751-
}
2752-
}
27532789

27542790
return false;
27552791
}

test/Concurrency/actor_isolation.swift

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ extension SomeClassInActor.ID {
811811
// ----------------------------------------------------------------------
812812
@available(SwiftStdlib 5.1, *)
813813
actor SomeActorWithInits {
814-
var mutableState: Int = 17 // expected-note 3 {{mutation of this property is only permitted within the actor}}
814+
var mutableState: Int = 17 // expected-note 2 {{mutation of this property is only permitted within the actor}}
815815
var otherMutableState: Int
816816
let nonSendable: SomeClass
817817

@@ -911,16 +911,16 @@ actor SomeActorWithInits {
911911

912912
let _ = {
913913
defer {
914-
isolated() // expected-error{{actor-isolated instance method 'isolated()' can not be referenced from a non-isolated context}}
915-
mutableState += 1 // expected-error{{actor-isolated property 'mutableState' can not be mutated from a non-isolated context}}
914+
isolated() // expected-warning{{actor-isolated instance method 'isolated()' can not be referenced from a non-isolated closure; this is an error in Swift 6}}
915+
mutableState += 1 // expected-warning{{actor-isolated property 'mutableState' can not be referenced from a non-isolated closure; this is an error in Swift 6}}
916916
nonisolated()
917917
}
918918
nonisolated()
919919
}()
920920
}
921921

922922

923-
func isolated() { } // expected-note 8 {{calls to instance method 'isolated()' from outside of its actor context are implicitly asynchronous}}
923+
func isolated() { } // expected-note 7 {{calls to instance method 'isolated()' from outside of its actor context are implicitly asynchronous}}
924924
nonisolated func nonisolated() {}
925925
}
926926

@@ -1344,3 +1344,15 @@ final class MainActorInit: Sendable {
13441344

13451345
func f() {}
13461346
}
1347+
1348+
actor DunkTracker {
1349+
private var lebron: Int?
1350+
private var curry: Int?
1351+
1352+
deinit {
1353+
// expected-warning@+1 {{actor-isolated property 'curry' can not be referenced from a non-isolated autoclosure; this is an error in Swift 6}}
1354+
if lebron != nil || curry != nil {
1355+
1356+
}
1357+
}
1358+
}

0 commit comments

Comments
 (0)