Skip to content

Commit 1608b1e

Browse files
committed
Make derived hashValue/hash(into:) nonisolated.
Fixes rdar://80424527.
1 parent ae6694a commit 1608b1e

File tree

3 files changed

+40
-5
lines changed

3 files changed

+40
-5
lines changed

Diff for: lib/Sema/DerivedConformanceEquatableHashable.cpp

+9-4
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,12 @@ deriveHashable_hashInto(
550550
hashDecl->copyFormalAccessFrom(derived.Nominal,
551551
/*sourceIsParentContext=*/true);
552552

553+
// The derived hash(into:) for an actor must be non-isolated.
554+
if (derived.Nominal->isActor() ||
555+
getActorIsolation(derived.Nominal) == ActorIsolation::GlobalActor) {
556+
hashDecl->getAttrs().add(new (C) NonisolatedAttr(/*IsImplicit*/true));
557+
}
558+
553559
derived.addMembersToConformanceContext({hashDecl});
554560

555561
return hashDecl;
@@ -904,10 +910,9 @@ static ValueDecl *deriveHashable_hashValue(DerivedConformance &derived) {
904910
hashValueDecl->copyFormalAccessFrom(derived.Nominal,
905911
/*sourceIsParentContext*/ true);
906912

907-
if (derived.Nominal->isDistributedActor()) {
908-
// While distributed actors implement hash(into:) explicitly, the hashValue
909-
// is still synthesized as usual. We must make it nonisolated in order
910-
// for the hashValue to be able to witness the protocol requirement.
913+
// The derived hashValue of an actor must be nonisolated.
914+
if (derived.Nominal->isActor() ||
915+
getActorIsolation(derived.Nominal) == ActorIsolation::GlobalActor) {
911916
hashValueDecl->getAttrs().add(new (C) NonisolatedAttr(/*IsImplicit*/true));
912917
}
913918

Diff for: test/decl/protocol/conforms/actor_derived.swift

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// REQUIRES: concurrency
3+
4+
@available(SwiftStdlib 5.5, *)
5+
actor A1: Hashable {
6+
nonisolated func hash(into hasher: inout Hasher) { }
7+
static func ==(lhs: A1, rhs: A1) -> Bool { true }
8+
}
9+
10+
@available(SwiftStdlib 5.5, *)
11+
actor A2: Hashable {
12+
nonisolated var hashValue: Int { 0 } // expected-warning{{'Hashable.hashValue' is deprecated as a protocol requirement; conform type 'A2' to 'Hashable' by implementing 'hash(into:)' instead}}
13+
static func ==(lhs: A2, rhs: A2) -> Bool { true }
14+
}
15+
16+
17+
@available(SwiftStdlib 5.5, *)
18+
@MainActor
19+
class C1: Hashable {
20+
nonisolated func hash(into hasher: inout Hasher) { }
21+
nonisolated static func ==(lhs: C1, rhs: C1) -> Bool { true }
22+
}
23+
24+
@available(SwiftStdlib 5.5, *)
25+
@MainActor
26+
class C2: Hashable {
27+
nonisolated var hashValue: Int { 0 } // expected-warning{{'Hashable.hashValue' is deprecated as a protocol requirement; conform type 'C2' to 'Hashable' by implementing 'hash(into:)' instead}}
28+
nonisolated static func ==(lhs: C2, rhs: C2) -> Bool { true }
29+
}
30+

Diff for: test/decl/protocol/special/Actor.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency
22
// REQUIRES: concurrency
33

4-
// Synthesis of for actores.
4+
// Synthesis of conformances for actors.
55

66
@available(SwiftStdlib 5.5, *)
77
actor A1 {

0 commit comments

Comments
 (0)