Skip to content

Commit 82332ca

Browse files
authored
Merge pull request swiftlang#71471 from angela-laar/fix-grouped-actor-errors-for-preconcurrency
Fix grouped actor errors for preconcurrency
2 parents d72f267 + 81e70cc commit 82332ca

File tree

3 files changed

+98
-22
lines changed

3 files changed

+98
-22
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,23 +2133,29 @@ namespace {
21332133
DiagnosticList errors = list.getSecond();
21342134
ActorIsolation isolation = key.second;
21352135

2136-
auto behavior = DiagnosticBehavior::Error;
2136+
auto behavior = DiagnosticBehavior::Warning;
2137+
// Upgrade behavior if @preconcurrency not detected
2138+
if (llvm::any_of(errors, [&](IsolationError error) {
2139+
return !error.preconcurrency;
2140+
})) {
2141+
behavior = DiagnosticBehavior::Error;
2142+
}
21372143

21382144
// Add Fix-it for missing @SomeActor annotation
21392145
if (isolation.isGlobalActor()) {
21402146
if (missingGlobalActorOnContext(
21412147
const_cast<DeclContext *>(getDeclContext()),
21422148
isolation.getGlobalActor(), behavior) &&
21432149
errors.size() > 1) {
2144-
behavior= DiagnosticBehavior::Note;
2150+
behavior = DiagnosticBehavior::Note;
21452151
}
21462152
}
21472153

21482154
for (IsolationError error : errors) {
21492155
// Diagnose actor_isolated_non_self_reference as note
2150-
// if fix-it provided in missingGlobalActorOnContext
2156+
// if there are multiple of these diagnostics
21512157
ctx.Diags.diagnose(error.loc, error.diag)
2152-
.limitBehaviorUntilSwiftVersion(behavior, 6);
2158+
.limitBehaviorUntilSwiftVersion(behavior, 6);
21532159
}
21542160
}
21552161

@@ -2158,23 +2164,31 @@ namespace {
21582164
DiagnosticList errors = list.getSecond();
21592165
ActorIsolation isolation = key.first;
21602166

2161-
auto behavior = DiagnosticBehavior::Error;
2167+
auto behavior = DiagnosticBehavior::Warning;
2168+
// Upgrade behavior if @preconcurrency not detected
2169+
if (llvm::any_of(errors, [&](IsolationError error) {
2170+
return !error.preconcurrency;
2171+
})) {
2172+
behavior = DiagnosticBehavior::Error;
2173+
}
2174+
21622175

21632176
// Add Fix-it for missing @SomeActor annotation
21642177
if (isolation.isGlobalActor()) {
21652178
if (missingGlobalActorOnContext(
21662179
const_cast<DeclContext *>(getDeclContext()),
21672180
isolation.getGlobalActor(), behavior) &&
21682181
errors.size() > 1) {
2169-
behavior= DiagnosticBehavior::Note;
2182+
behavior = DiagnosticBehavior::Note;
21702183
}
21712184
}
21722185

21732186
for (IsolationError error : errors) {
21742187
// Diagnose actor_isolated_call as note if
2175-
// fix-it provided in missingGlobalActorOnContext
2188+
// if there are multiple actor-isolated function calls
2189+
// from outside the actor
21762190
ctx.Diags.diagnose(error.loc, error.diag)
2177-
.limitBehaviorUntilSwiftVersion(behavior, 6);
2191+
.limitBehaviorUntilSwiftVersion(behavior, 6);
21782192
}
21792193
}
21802194

@@ -3437,15 +3451,20 @@ namespace {
34373451

34383452
IsolationError mismatch([calleeDecl, apply, unsatisfiedIsolation, getContextIsolation]() {
34393453
if (calleeDecl) {
3454+
auto preconcurrency = getContextIsolation().preconcurrency() ||
3455+
getActorIsolation(calleeDecl).preconcurrency();
3456+
34403457
return IsolationError(
34413458
apply->getLoc(),
3459+
preconcurrency,
34423460
Diagnostic(diag::actor_isolated_call_decl,
34433461
*unsatisfiedIsolation,
34443462
calleeDecl,
34453463
getContextIsolation()));
34463464
} else {
34473465
return IsolationError(
34483466
apply->getLoc(),
3467+
getContextIsolation().preconcurrency(),
34493468
Diagnostic(diag::actor_isolated_call,
34503469
*unsatisfiedIsolation,
34513470
getContextIsolation()));
@@ -3464,7 +3483,8 @@ namespace {
34643483
} else {
34653484
if (calleeDecl) {
34663485
auto preconcurrency = getContextIsolation().preconcurrency() ||
3467-
getActorIsolation(calleeDecl).preconcurrency();
3486+
getActorIsolation(calleeDecl).preconcurrency();
3487+
34683488
ctx.Diags.diagnose(
34693489
apply->getLoc(), diag::actor_isolated_call_decl,
34703490
*unsatisfiedIsolation,
@@ -3967,6 +3987,7 @@ namespace {
39673987

39683988
if (ctx.LangOpts.hasFeature(Feature::GroupActorErrors)) {
39693989
IsolationError mismatch = IsolationError(loc,
3990+
preconcurrencyContext,
39703991
Diagnostic(diag::actor_isolated_non_self_reference,
39713992
decl, useKind, refKind + 1, refGlobalActor,
39723993
result.isolation));

lib/Sema/TypeCheckConcurrency.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,12 @@ struct IsolationError {
254254

255255
SourceLoc loc;
256256

257+
bool preconcurrency;
258+
257259
Diagnostic diag;
258260

259261
public:
260-
IsolationError(SourceLoc loc, Diagnostic diag) : loc(loc), diag(diag) {}
262+
IsolationError(SourceLoc loc, bool preconcurrency, Diagnostic diag) : loc(loc), preconcurrency(preconcurrency), diag(diag) {}
261263

262264
};
263265

test/Concurrency/grouped_actor_isolation_diagnostics.swift

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-feature GroupActorErrors
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-feature GroupActorErrors -strict-concurrency=complete
22
// REQUIRES: concurrency
33

44
@MainActor
@@ -7,22 +7,52 @@ protocol P {
77
nonisolated func g()
88
}
99

10-
struct S_P: P {
10+
@preconcurrency @MainActor
11+
protocol Q {
12+
func f()
13+
nonisolated func g()
14+
}
15+
16+
struct S: P {
17+
func f() { }
18+
func g() { }
19+
}
20+
21+
@preconcurrency
22+
struct NonConcurrentS: Q {
1123
func f() { }
1224
func g() { }
1325
}
1426

15-
// expected-error@+2{{calls to '@MainActor'-isolated' code in global function 'testP(x:p:)'}}
16-
// expected-note@+1{{add '@MainActor' to make global function 'testP(x:p:)' part of global actor 'MainActor'}}
17-
func testP(x: S_P, p: P) {
27+
// expected-note@+1{{add '@MainActor' to make global function 'testP(s:p:)' part of global actor 'MainActor'}}
28+
func testP(s: S, p: P) { // expected-error {{calls to '@MainActor'-isolated' code in global function 'testP(s:p:)'}}
1829
p.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
1930
p.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
2031
p.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
2132
p.g() // OKAY
22-
x.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
23-
x.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
24-
x.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
25-
x.g() // OKAY
33+
s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
34+
s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
35+
s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
36+
s.g() // OKAY
37+
}
38+
// expected-note @+1{{add '@MainActor' to make global function 'testPreconcurrency(ncs:s:)' part of global actor 'MainActor'}}
39+
func testPreconcurrency(ncs: NonConcurrentS, s:S ) { // expected-error {{calls to '@MainActor'-isolated' code in global function 'testPreconcurrency(ncs:s:)'}}
40+
ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
41+
ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
42+
ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
43+
ncs.g() // OKAY
44+
s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
45+
s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
46+
s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
47+
s.g() // OKAY
48+
}
49+
50+
// expected-note @+1{{add '@MainActor' to make global function 'testOnlyPreconcurrency(ncs:)' part of global actor 'MainActor'}}
51+
func testOnlyPreconcurrency(ncs: NonConcurrentS) { // expected-warning {{calls to '@MainActor'-isolated' code in global function 'testOnlyPreconcurrency(ncs:)'}}
52+
ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
53+
ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
54+
ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
55+
ncs.g() // OKAY
2656
}
2757

2858
actor SomeActor { }
@@ -46,7 +76,7 @@ struct WrapperOnActor<Wrapped: Sendable> {
4676
}
4777

4878
@SomeGlobalActor var projectedValue: Wrapped {
49-
get { }
79+
get { }
5080
set { }
5181
}
5282
}
@@ -75,9 +105,32 @@ struct HasWrapperOnActor {
75105
@MainActor
76106
func testMA(){ }
77107

78-
// expected-error@+2{{calls to '@MainActor'-isolated' code in instance method 'testErrors()'}}
79108
// expected-note@+1{{add '@MainActor' to make instance method 'testErrors()' part of global actor 'MainActor'}}
80-
func testErrors() {
109+
func testErrors() { // expected-error{{calls to '@MainActor'-isolated' code in instance method 'testErrors()'}}
81110
testMA() // expected-error{{call to main actor-isolated instance method 'testMA()' in a synchronous nonisolated context}}
82111
}
83112
}
113+
114+
@preconcurrency @MainActor
115+
class MainActorPreconcurrency {}
116+
117+
class InferMainActorPreconcurrency: MainActorPreconcurrency {
118+
static func predatesConcurrency() {}
119+
func predatesConcurrency (s: String) -> String { return s }
120+
func predatesConcurrency (n: Int) -> Int { return n }
121+
}
122+
123+
nonisolated func testPreconcurrency() {
124+
InferMainActorPreconcurrency.predatesConcurrency()
125+
// expected-warning@-1 {{call to main actor-isolated static method 'predatesConcurrency()' in a synchronous nonisolated context}}
126+
}
127+
128+
func testPreconcurrencyGrouped() { // expected-warning {{calls to '@MainActor'-isolated' code in global function 'testPreconcurrencyGrouped()'}}
129+
// expected-note@-1 {{add '@MainActor' to make global function 'testPreconcurrencyGrouped()' part of global actor 'MainActor'}}
130+
InferMainActorPreconcurrency.predatesConcurrency()
131+
// expected-note@-1 {{call to main actor-isolated static method 'predatesConcurrency()' in a synchronous nonisolated context}}
132+
let _ = InferMainActorPreconcurrency().predatesConcurrency(s:"swift 6")
133+
// expected-note@-1 {{call to main actor-isolated instance method 'predatesConcurrency(s:)' in a synchronous nonisolated context}}
134+
let _ = InferMainActorPreconcurrency().predatesConcurrency(n:4)
135+
// expected-note@-1 {{call to main actor-isolated instance method 'predatesConcurrency(n:)' in a synchronous nonisolated context}}
136+
}

0 commit comments

Comments
 (0)