Skip to content

Commit 5ecfe2a

Browse files
authored
Merge pull request #41305 from kavon/deinit-isolation-warnonly
2 parents 05da933 + a70ed0f commit 5ecfe2a

File tree

4 files changed

+51
-5
lines changed

4 files changed

+51
-5
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4486,7 +4486,9 @@ NOTE(note_distributed_actor_system_conformance_missing_adhoc_requirement,none,
44864486
ERROR(override_implicit_unowned_executor,none,
44874487
"cannot override an actor's 'unownedExecutor' property that wasn't "
44884488
"explicitly defined", ())
4489-
4489+
ERROR(actor_isolated_from_deinit,none,
4490+
"actor-isolated %0 %1 can not be referenced from a non-isolated deinit",
4491+
(DescriptiveDeclKind, DeclName))
44904492
ERROR(actor_isolated_non_self_reference,none,
44914493
"actor-isolated %0 %1 can not be "
44924494
"%select{referenced|mutated|used 'inout'}2 "

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2687,12 +2687,14 @@ namespace {
26872687
/// \param refCxt the context in which the member reference happens.
26882688
/// \param baseActor the actor referenced in the base of the member access.
26892689
/// \param member the declaration corresponding to the accessed member.
2690+
/// \param memberLoc the source location of the reference to the member.
26902691
///
26912692
/// \returns true iff the member access is permitted in Sema because it will
26922693
/// be verified later by flow-isolation.
26932694
bool checkedByFlowIsolation(DeclContext const *refCxt,
26942695
ReferencedActor &baseActor,
2695-
ValueDecl const *member) {
2696+
ValueDecl const *member,
2697+
SourceLoc memberLoc) {
26962698

26972699
// base of member reference must be `self`
26982700
if (!baseActor.isActorSelf())
@@ -2728,6 +2730,18 @@ namespace {
27282730
if (var->hasStorage() && var->isInstanceMember())
27292731
return true;
27302732

2733+
// In Swift 5, we were allowing all members to be referenced from a
2734+
// deinit, but that will not be valid in Swift 6+, so warn about it.
2735+
if (!refCxt->getASTContext().isSwiftVersionAtLeast(6)) {
2736+
if (isa<DestructorDecl>(fnDecl) && member->isInstanceMember()) {
2737+
auto &diags = refCxt->getASTContext().Diags;
2738+
diags.diagnose(memberLoc, diag::actor_isolated_from_deinit,
2739+
member->getDescriptiveKind(),
2740+
member->getName()).warnUntilSwiftVersion(6);
2741+
return true;
2742+
}
2743+
}
2744+
27312745
return false;
27322746
}
27332747

@@ -2831,7 +2845,7 @@ namespace {
28312845
// access an isolated member on `self`. If that case applies, then we
28322846
// can skip checking.
28332847
if (checkedByFlowIsolation(getDeclContext(), isolatedActor,
2834-
member))
2848+
member, memberLoc))
28352849
return false;
28362850

28372851
// An escaping partial application of something that is part of

test/Concurrency/actor_isolation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,7 @@ actor SomeActorWithInits {
904904
let _ = self.nonSendable // OK only through typechecking, not SIL.
905905

906906
defer {
907-
isolated() // expected-error{{actor-isolated instance method 'isolated()' can not be referenced from a non-isolated context}}
907+
isolated() // expected-warning{{actor-isolated instance method 'isolated()' can not be referenced from a non-isolated deinit; this is an error in Swift 6}}
908908
mutableState += 1 // okay
909909
nonisolated()
910910
}
@@ -920,7 +920,7 @@ actor SomeActorWithInits {
920920
}
921921

922922

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

test/Concurrency/flow_isolation.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,7 @@ actor EscapeArtist {
584584
actor Ahmad {
585585
nonisolated func f() {}
586586
var prop: Int = 0
587+
var computedProp: Int { 10 }
587588

588589
init(v1: Void) {
589590
Task.detached { self.f() } // expected-note {{after making a copy of 'self', only non-isolated properties of 'self' can be accessed from this init}}
@@ -596,6 +597,14 @@ actor Ahmad {
596597
f()
597598
prop += 1 // expected-warning {{cannot access property 'prop' here in non-isolated initializer; this is an error in Swift 6}}
598599
}
600+
601+
deinit {
602+
// expected-warning@+2 {{actor-isolated property 'computedProp' can not be referenced from a non-isolated deinit; this is an error in Swift 6}}
603+
// expected-note@+1 {{after accessing property 'computedProp', only non-isolated properties of 'self' can be accessed from a deinit}}
604+
let x = computedProp
605+
606+
prop = x // expected-warning {{cannot access property 'prop' here in deinitializer; this is an error in Swift 6}}
607+
}
599608
}
600609

601610
@available(SwiftStdlib 5.5, *)
@@ -622,4 +631,25 @@ actor Rain {
622631

623632
defer { _ = hollerBack(self) }
624633
}
634+
635+
deinit {
636+
x = 1
637+
}
638+
}
639+
640+
@available(SwiftStdlib 5.5, *)
641+
actor DeinitExceptionForSwift5 {
642+
var x: Int = 0
643+
644+
func cleanup() {
645+
x = 0
646+
}
647+
648+
deinit {
649+
// expected-warning@+2 {{actor-isolated instance method 'cleanup()' can not be referenced from a non-isolated deinit; this is an error in Swift 6}}
650+
// expected-note@+1 {{after calling instance method 'cleanup()', only non-isolated properties of 'self' can be accessed from a deinit}}
651+
cleanup()
652+
653+
x = 1 // expected-warning {{cannot access property 'x' here in deinitializer; this is an error in Swift 6}}
654+
}
625655
}

0 commit comments

Comments
 (0)