Skip to content

Commit 0daad82

Browse files
committed
[Sema] Propagate @preconcurrency attribute to grouped diagnostics feature
1 parent 85ea5ff commit 0daad82

File tree

3 files changed

+59
-19
lines changed

3 files changed

+59
-19
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,21 +2147,25 @@ namespace {
21472147

21482148
auto behavior = DiagnosticBehavior::Error;
21492149

2150+
// Limit behavior if @preconcurrency detected
2151+
if (errors.front().preconcurrency)
2152+
behavior = DiagnosticBehavior::Warning;
2153+
21502154
// Add Fix-it for missing @SomeActor annotation
21512155
if (isolation.isGlobalActor()) {
21522156
if (missingGlobalActorOnContext(
21532157
const_cast<DeclContext *>(getDeclContext()),
21542158
isolation.getGlobalActor(), behavior) &&
21552159
errors.size() > 1) {
2156-
behavior= DiagnosticBehavior::Note;
2160+
behavior = DiagnosticBehavior::Note;
21572161
}
21582162
}
21592163

21602164
for (IsolationError error : errors) {
21612165
// Diagnose actor_isolated_non_self_reference as note
2162-
// if fix-it provided in missingGlobalActorOnContext
2166+
// if there are multiple of these diagnostics
21632167
ctx.Diags.diagnose(error.loc, error.diag)
2164-
.limitBehaviorUntilSwiftVersion(behavior, 6);
2168+
.limitBehaviorUntilSwiftVersion(behavior, 6);
21652169
}
21662170
}
21672171

@@ -2172,21 +2176,26 @@ namespace {
21722176

21732177
auto behavior = DiagnosticBehavior::Error;
21742178

2179+
// Limit behavior if @preconcurrency detected
2180+
if (errors.front().preconcurrency)
2181+
behavior = DiagnosticBehavior::Warning;
2182+
21752183
// Add Fix-it for missing @SomeActor annotation
21762184
if (isolation.isGlobalActor()) {
21772185
if (missingGlobalActorOnContext(
21782186
const_cast<DeclContext *>(getDeclContext()),
21792187
isolation.getGlobalActor(), behavior) &&
21802188
errors.size() > 1) {
2181-
behavior= DiagnosticBehavior::Note;
2189+
behavior = DiagnosticBehavior::Note;
21822190
}
21832191
}
21842192

21852193
for (IsolationError error : errors) {
21862194
// Diagnose actor_isolated_call as note if
2187-
// fix-it provided in missingGlobalActorOnContext
2188-
ctx.Diags.diagnose(error.loc, error.diag)
2189-
.limitBehaviorUntilSwiftVersion(behavior, 6);
2195+
// if there are multiple actor-isolated function calls
2196+
// from outside the actor
2197+
ctx.Diags.diagnose(error.loc, error.diag)
2198+
.limitBehaviorUntilSwiftVersion(behavior, 6);
21902199
}
21912200
}
21922201

@@ -3449,15 +3458,19 @@ namespace {
34493458

34503459
IsolationError mismatch([calleeDecl, apply, unsatisfiedIsolation, getContextIsolation]() {
34513460
if (calleeDecl) {
3461+
auto preconcurrency = getContextIsolation().preconcurrency() || getActorIsolation(calleeDecl).preconcurrency();
3462+
34523463
return IsolationError(
34533464
apply->getLoc(),
3465+
preconcurrency,
34543466
Diagnostic(diag::actor_isolated_call_decl,
34553467
*unsatisfiedIsolation,
34563468
calleeDecl,
34573469
getContextIsolation()));
34583470
} else {
34593471
return IsolationError(
34603472
apply->getLoc(),
3473+
getContextIsolation().preconcurrency(),
34613474
Diagnostic(diag::actor_isolated_call,
34623475
*unsatisfiedIsolation,
34633476
getContextIsolation()));
@@ -3475,8 +3488,8 @@ namespace {
34753488
}
34763489
} else {
34773490
if (calleeDecl) {
3478-
auto preconcurrency = getContextIsolation().preconcurrency() ||
3479-
getActorIsolation(calleeDecl).preconcurrency();
3491+
auto preconcurrency = getContextIsolation().preconcurrency() || getActorIsolation(calleeDecl).preconcurrency();
3492+
34803493
ctx.Diags.diagnose(
34813494
apply->getLoc(), diag::actor_isolated_call_decl,
34823495
*unsatisfiedIsolation,
@@ -3979,6 +3992,7 @@ namespace {
39793992

39803993
if (ctx.LangOpts.hasFeature(Feature::GroupActorErrors)) {
39813994
IsolationError mismatch = IsolationError(loc,
3995+
preconcurrencyContext,
39823996
Diagnostic(diag::actor_isolated_non_self_reference,
39833997
decl, useKind, refKind + 1, refGlobalActor,
39843998
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: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,34 @@ protocol P {
77
nonisolated func g()
88
}
99

10-
struct S_P: P {
10+
struct S: P {
1111
func f() { }
1212
func g() { }
1313
}
1414

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) {
15+
@preconcurrency struct NonConcurrentS: P {
16+
func f() { }
17+
func g() { }
18+
}
19+
20+
// expected-note@+1{{add '@MainActor' to make global function 'testP(s:p:)' part of global actor 'MainActor'}}
21+
func testP(s: S, p: P) { // expected-error {{calls to '@MainActor'-isolated' code in global function 'testP(s:p:)'}}
22+
1823
p.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
1924
p.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
2025
p.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
2126
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
27+
s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
28+
s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
29+
s.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
30+
s.g() // OKAY
31+
}
32+
// expected-note @+1{{add '@MainActor' to make global function 'testPreconcurrencyP(ncs:)' part of global actor 'MainActor'}}
33+
func testPreconcurrencyP(ncs: NonConcurrentS) { // expected-error {{calls to '@MainActor'-isolated' code in global function 'testPreconcurrencyP(ncs:)'}}
34+
ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
35+
ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
36+
ncs.f() // expected-note{{call to main actor-isolated instance method 'f()' in a synchronous nonisolated context}}
37+
ncs.g() // OKAY
2638
}
2739

2840
actor SomeActor { }
@@ -46,7 +58,7 @@ struct WrapperOnActor<Wrapped: Sendable> {
4658
}
4759

4860
@SomeGlobalActor var projectedValue: Wrapped {
49-
get { }
61+
get { }
5062
set { }
5163
}
5264
}
@@ -81,3 +93,15 @@ struct HasWrapperOnActor {
8193
testMA() // expected-error{{call to main actor-isolated instance method 'testMA()' in a synchronous nonisolated context}}
8294
}
8395
}
96+
97+
@preconcurrency @MainActor
98+
class MainActorPreconcurrency {}
99+
100+
class InferMainActorPreconcurrency: MainActorPreconcurrency {
101+
static func predatesConcurrency() {}
102+
}
103+
104+
nonisolated func testPreconcurrency() {
105+
InferMainActorPreconcurrency.predatesConcurrency()
106+
// expected-warning@-1 {{call to main actor-isolated static method 'predatesConcurrency()' in a synchronous nonisolated context}}
107+
}

0 commit comments

Comments
 (0)