Skip to content

Commit 35187d2

Browse files
authored
Merge pull request #71643 from hborla/preconcurrency-isolated-derived-conformance
[Concurrency] Don't skip conformance derivation for types with isolated stored properties.
2 parents 2294d9f + fcc7d0f commit 35187d2

File tree

5 files changed

+70
-47
lines changed

5 files changed

+70
-47
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5567,6 +5567,9 @@ ERROR(isolation_macro_experimental,none,
55675567
NOTE(in_derived_conformance, none,
55685568
"in derived conformance to %0",
55695569
(Type))
5570+
NOTE(in_derived_witness, none,
5571+
"in %0 %1 for derived conformance to %2",
5572+
(DescriptiveDeclKind, DeclName, Type))
55705573
ERROR(non_sendable_param_type,none,
55715574
"non-sendable type %0 %select{passed in call to %3 %kind2|"
55725575
"exiting %3 context in call to non-isolated %kind2|"

lib/Sema/DerivedConformanceCodable.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,12 +2086,6 @@ static bool canDeriveCodable(NominalTypeDecl *NTD,
20862086
return false;
20872087
}
20882088

2089-
// Actor-isolated structs and classes cannot derive encodable/decodable
2090-
// unless all of their stored properties are immutable.
2091-
if ((isa<StructDecl>(NTD) || isa<ClassDecl>(NTD)) &&
2092-
memberwiseAccessorsRequireActorIsolation(NTD))
2093-
return false;
2094-
20952089
return true;
20962090
}
20972091

lib/Sema/DerivedConformanceEquatableHashable.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,6 @@ static bool canDeriveConformance(DeclContext *DC,
5050
DC, structDecl, protocol).empty())
5151
return false;
5252

53-
// If the struct is actor-isolated, we cannot derive Equatable/Hashable
54-
// conformance if any of the stored properties are mutable.
55-
if (memberwiseAccessorsRequireActorIsolation(structDecl))
56-
return false;
57-
5853
return true;
5954
}
6055

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3921,38 +3921,61 @@ namespace {
39213921
bool preconcurrencyContext =
39223922
result.options.contains(ActorReferenceResult::Flags::Preconcurrency);
39233923

3924-
if (ctx.LangOpts.hasFeature(Feature::GroupActorErrors)) {
3925-
IsolationError mismatch = IsolationError(loc, Diagnostic(diag::actor_isolated_non_self_reference,
3926-
decl,
3927-
useKind,
3928-
refKind + 1, refGlobalActor,
3929-
result.isolation));
3930-
3931-
auto iter = refErrors.find(std::make_pair(refKind,result.isolation));
3932-
if (iter != refErrors.end()){
3933-
iter->second.push_back(mismatch);
3934-
} else {
3935-
DiagnosticList list;
3936-
list.push_back(mismatch);
3937-
auto keyPair = std::make_pair(refKind,result.isolation);
3938-
refErrors.insert(std::make_pair(keyPair, list));
3924+
Type derivedConformanceType;
3925+
DeclName requirementName;
3926+
if (loc.isInvalid()) {
3927+
auto *decl = getDeclContext()->getAsDecl();
3928+
if (decl && decl->isImplicit()) {
3929+
auto *parentDC = decl->getDeclContext();
3930+
loc = parentDC->getAsDecl()->getLoc();
3931+
3932+
if (auto *implements = decl->getAttrs().getAttribute<ImplementsAttr>()) {
3933+
derivedConformanceType =
3934+
implements->getProtocol(parentDC)->getDeclaredInterfaceType();
3935+
requirementName = implements->getMemberName();
39393936
}
3937+
}
3938+
}
3939+
3940+
if (ctx.LangOpts.hasFeature(Feature::GroupActorErrors)) {
3941+
IsolationError mismatch = IsolationError(loc,
3942+
Diagnostic(diag::actor_isolated_non_self_reference,
3943+
decl, useKind, refKind + 1, refGlobalActor,
3944+
result.isolation));
3945+
3946+
auto iter = refErrors.find(std::make_pair(refKind,result.isolation));
3947+
if (iter != refErrors.end()) {
3948+
iter->second.push_back(mismatch);
39403949
} else {
3941-
ctx.Diags.diagnose(
3942-
loc, diag::actor_isolated_non_self_reference,
3943-
decl,
3944-
useKind,
3945-
refKind + 1, refGlobalActor,
3946-
result.isolation)
3947-
.warnUntilSwiftVersionIf(preconcurrencyContext, 6);
3948-
3949-
noteIsolatedActorMember(decl, context);
3950-
if (result.isolation.isGlobalActor()) {
3951-
missingGlobalActorOnContext(
3952-
const_cast<DeclContext *>(getDeclContext()),
3953-
result.isolation.getGlobalActor(), DiagnosticBehavior::Note);
3954-
}
3950+
DiagnosticList list;
3951+
list.push_back(mismatch);
3952+
auto keyPair = std::make_pair(refKind,result.isolation);
3953+
refErrors.insert(std::make_pair(keyPair, list));
39553954
}
3955+
} else {
3956+
ctx.Diags.diagnose(
3957+
loc, diag::actor_isolated_non_self_reference,
3958+
decl, useKind,
3959+
refKind + 1, refGlobalActor,
3960+
result.isolation)
3961+
.warnUntilSwiftVersionIf(preconcurrencyContext, 6);
3962+
3963+
if (derivedConformanceType) {
3964+
auto *decl = dyn_cast<ValueDecl>(getDeclContext()->getAsDecl());
3965+
ctx.Diags.diagnose(loc, diag::in_derived_witness,
3966+
decl->getDescriptiveKind(),
3967+
requirementName,
3968+
derivedConformanceType);
3969+
}
3970+
3971+
noteIsolatedActorMember(decl, context);
3972+
if (result.isolation.isGlobalActor()) {
3973+
missingGlobalActorOnContext(
3974+
const_cast<DeclContext *>(getDeclContext()),
3975+
result.isolation.getGlobalActor(), DiagnosticBehavior::Note);
3976+
}
3977+
}
3978+
39563979
return true;
39573980
}
39583981
}
Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
// RUN: %target-swift-frontend -disable-availability-checking -strict-concurrency=complete -parse-as-library %s -emit-sil -o /dev/null -verify
2-
// RUN: %target-swift-frontend -disable-availability-checking -strict-concurrency=complete -parse-as-library %s -emit-sil -o /dev/null -verify -strict-concurrency=targeted
3-
// RUN: %target-swift-frontend -disable-availability-checking -strict-concurrency=complete -parse-as-library %s -emit-sil -o /dev/null -verify -strict-concurrency=complete
42
// RUN: %target-swift-frontend -disable-availability-checking -strict-concurrency=complete -parse-as-library %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -enable-experimental-feature RegionBasedIsolation
53

64
// REQUIRES: concurrency
@@ -12,18 +10,28 @@ struct X1: Equatable, Hashable, Codable {
1210
let y: String
1311
}
1412

15-
// expected-error@+5{{type 'X2' does not conform to protocol 'Encodable'}}
16-
// expected-error@+4{{type 'X2' does not conform to protocol 'Decodable'}}
17-
// expected-error@+3{{type 'X2' does not conform to protocol 'Equatable'}}
18-
// expected-error@+2{{type 'X2' does not conform to protocol 'Hashable'}}
13+
// expected-error@+5 3{{main actor-isolated property 'y' can not be referenced from a non-isolated context}}
14+
// expected-note@+4{{in static method '==' for derived conformance to 'Equatable'}}
15+
// expected-error@+3{{main actor-isolated property 'y' can not be referenced from a non-isolated context}}
16+
// expected-note@+2{{in static method '==' for derived conformance to 'Equatable'}}
1917
@MainActor
2018
struct X2: Equatable, Hashable, Codable {
2119
let x: Int
22-
var y: String
20+
var y: String // expected-note 4 {{property declared here}}
2321
}
2422

2523
@MainActor
2624
enum X3: Hashable, Comparable, Codable {
2725
case a
2826
case b(Int)
2927
}
28+
29+
// expected-warning@+5{{main actor-isolated property 'y' can not be referenced from a non-isolated context}}
30+
// expected-note@+4{{in static method '==' for derived conformance to 'Equatable'}}
31+
// expected-warning@+3{{main actor-isolated property 'y' can not be referenced from a non-isolated context}}
32+
// expected-note@+2{{in static method '==' for derived conformance to 'Equatable'}}
33+
@preconcurrency @MainActor
34+
struct X4: Equatable {
35+
let x: Int
36+
var y: String // expected-note 2 {{property declared here}}
37+
}

0 commit comments

Comments
 (0)