Skip to content

Commit eb665f6

Browse files
committed
improve and fix diagnostic for implicitly async calls
1 parent 9cba855 commit eb665f6

File tree

5 files changed

+34
-24
lines changed

5 files changed

+34
-24
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4213,9 +4213,10 @@ ERROR(actor_isolated_concurrent_access,none,
42134213
"actor-isolated %0 %1 is unsafe to reference in code "
42144214
"that may execute concurrently",
42154215
(DescriptiveDeclKind, DeclName))
4216-
NOTE(actor_isolated_method,none,
4217-
"only asynchronous methods can be used outside the actor instance; "
4218-
"do you want to add 'async'?", ())
4216+
NOTE(actor_isolated_sync_func,none,
4217+
"calls to %0 %1 from outside of its actor context are "
4218+
"implicitly asynchronous",
4219+
(DescriptiveDeclKind, DeclName))
42194220
NOTE(actor_mutable_state,none,
42204221
"mutable state is only available within the actor instance", ())
42214222
WARNING(shared_mutable_state_access,none,

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -720,10 +720,9 @@ namespace {
720720
// FIXME: Make this diagnostic more sensitive to the isolation context
721721
// of the declaration.
722722
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
723-
// FIXME: We'd like to insert 'async' at the appropriate place, but
724-
// FuncDecl/AbstractFunctionDecl doesn't have the right source-location
725-
// information to do so.
726-
func->diagnose(diag::actor_isolated_method);
723+
func->diagnose(diag::actor_isolated_sync_func,
724+
decl->getDescriptiveKind(),
725+
decl->getName());
727726
} else if (isa<VarDecl>(decl)) {
728727
decl->diagnose(diag::actor_mutable_state);
729728
} else {

test/Concurrency/actor_call_implicitly_async.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ actor class BankAccount {
1818
}
1919

2020
// NOTE: this func is accessed through both async and sync calls.
21-
// expected-note@+1 {{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
21+
// expected-note@+1 {{calls to instance method 'balance()' from outside of its actor context are implicitly asynchronous}}
2222
func balance() -> Int { return curBalance }
2323

24-
// expected-note@+1 {{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
24+
// expected-note@+1 {{calls to instance method 'deposit' from outside of its actor context are implicitly asynchronous}}
2525
func deposit(_ amount : Int) -> Int {
2626
guard amount >= 0 else { return 0 }
2727

@@ -86,6 +86,8 @@ func someAsyncFunc() async {
8686

8787
_ = await a.deposit(b.withdraw(a.deposit(b.withdraw(b.balance()))))
8888

89+
a.testSelfBalance() // expected-error {{call is 'async' but is not marked with 'await'}}
90+
8991
print("ok!")
9092
}
9193

@@ -150,9 +152,9 @@ func blender(_ peeler : () -> Void) {
150152
peeler()
151153
}
152154

153-
@BananaActor func wisk(_ something : Any) { } // expected-note 4 {{only asynchronous methods can be used outside the actor instance}}
155+
@BananaActor func wisk(_ something : Any) { } // expected-note 4 {{calls to global function 'wisk' from outside of its actor context are implicitly asynchronous}}
154156

155-
@BananaActor func peelBanana() { } // expected-note 2 {{only asynchronous methods can be used outside the actor instance}}
157+
@BananaActor func peelBanana() { } // expected-note 2 {{calls to global function 'peelBanana()' from outside of its actor context are implicitly asynchronous}}
156158

157159
@OrangeActor func makeSmoothie() async {
158160
await wisk({})
@@ -174,4 +176,12 @@ func blender(_ peeler : () -> Void) {
174176
// expected-warning@+2 {{no calls to 'async' functions occur within 'await' expression}}
175177
// expected-error@+1 {{global function 'wisk' isolated to global actor 'BananaActor' can not be referenced from different global actor 'OrangeActor'}}
176178
await (true ? wisk : {n in return})(1)
179+
}
180+
181+
182+
// want to make sure there is no note about implicitly async on this func.
183+
@BananaActor func rice() async {}
184+
185+
@OrangeActor func quinoa() async {
186+
rice() // expected-error {{call is 'async' but is not marked with 'await'}}
177187
}

test/Concurrency/actor_isolation.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func acceptEscapingAsyncClosure<T>(_: @escaping () async -> T) { }
1919
actor class MySuperActor {
2020
var superState: Int = 25 // expected-note {{mutable state is only available within the actor instance}}
2121

22-
func superMethod() { } // expected-note 3 {{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
22+
func superMethod() { } // expected-note 3 {{calls to instance method 'superMethod()' from outside of its actor context are implicitly asynchronous}}
2323
func superAsyncMethod() async { }
2424

2525
subscript (index: Int) -> String { // expected-note 3{{subscript declared here}}
@@ -34,7 +34,7 @@ actor class MyActor: MySuperActor {
3434
class func synchronousClass() { }
3535
static func synchronousStatic() { }
3636

37-
func synchronous() -> String { text.first ?? "nothing" } // expected-note 20{{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
37+
func synchronous() -> String { text.first ?? "nothing" } // expected-note 20{{calls to instance method 'synchronous()' from outside of its actor context are implicitly asynchronous}}
3838
func asynchronous() async -> String { synchronous() }
3939
}
4040

@@ -199,7 +199,7 @@ struct GenericGlobalActor<T> {
199199
static var shared: SomeActor { SomeActor() }
200200
}
201201

202-
@SomeGlobalActor func syncGlobalActorFunc() { syncGlobalActorFunc() } // expected-note{{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
202+
@SomeGlobalActor func syncGlobalActorFunc() { syncGlobalActorFunc() } // expected-note{{calls to global function 'syncGlobalActorFunc()' from outside of its actor context are implicitly asynchronous}}
203203
@SomeGlobalActor func asyncGlobalActorFunc() async { await asyncGlobalActorFunc() }
204204

205205
@SomeOtherGlobalActor func syncOtherGlobalActorFunc() { }
@@ -255,7 +255,7 @@ extension MyActor {
255255
}
256256

257257
struct GenericStruct<T> {
258-
@GenericGlobalActor<T> func f() { } // expected-note{{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
258+
@GenericGlobalActor<T> func f() { } // expected-note{{calls to instance method 'f()' from outside of its actor context are implicitly asynchronous}}
259259

260260
@GenericGlobalActor<T> func g() {
261261
f() // okay

test/Concurrency/global_actor_inference.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ protocol P2 {
3333
}
3434

3535
class C1: P1 {
36-
func method() { } // expected-note {{only asynchronous methods can be used outside the actor instance}}
36+
func method() { } // expected-note {{calls to instance method 'method()' from outside of its actor context are implicitly asynchronous}}
3737

3838
// expected-note@+2 {{add '@asyncHandler' to function 'testMethod()' to create an implicit asynchronous context}}
3939
// expected-note@+1 {{add 'async' to function 'testMethod()' to make it asynchronous}}
@@ -44,7 +44,7 @@ class C1: P1 {
4444
}
4545

4646
class C2: P2 {
47-
func method1() { } // expected-note{{only asynchronous methods can be used outside the actor instance}}
47+
func method1() { } // expected-note{{calls to instance method 'method1()' from outside of its actor context are implicitly asynchronous}}
4848
func method2() { }
4949

5050
// expected-note@+2 {{add '@asyncHandler' to function 'testMethod()' to create an implicit asynchronous context}}
@@ -60,27 +60,27 @@ class C2: P2 {
6060
// Global actor inference for classes and extensions
6161
// ----------------------------------------------------------------------
6262
@SomeGlobalActor class C3 {
63-
func method1() { } // expected-note {{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
63+
func method1() { } // expected-note {{calls to instance method 'method1()' from outside of its actor context are implicitly asynchronous}}
6464
}
6565

6666
extension C3 {
67-
func method2() { } // expected-note {{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
67+
func method2() { } // expected-note {{calls to instance method 'method2()' from outside of its actor context are implicitly asynchronous}}
6868
}
6969

7070
class C4: C3 {
71-
func method3() { } // expected-note {{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
71+
func method3() { } // expected-note {{calls to instance method 'method3()' from outside of its actor context are implicitly asynchronous}}
7272
}
7373

7474
extension C4 {
75-
func method4() { } // expected-note {{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
75+
func method4() { } // expected-note {{calls to instance method 'method4()' from outside of its actor context are implicitly asynchronous}}
7676
}
7777

7878
class C5 {
7979
func method1() { }
8080
}
8181

8282
@SomeGlobalActor extension C5 {
83-
func method2() { } // expected-note {{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
83+
func method2() { } // expected-note {{calls to instance method 'method2()' from outside of its actor context are implicitly asynchronous}}
8484
}
8585

8686
// expected-note@+2 5 {{add '@asyncHandler' to function 'testGlobalActorInference(c3:c4:c5:)' to create an implicit asynchronous context}}
@@ -140,7 +140,7 @@ actor class GenericSuper<T> {
140140
}
141141

142142
actor class GenericSub<T> : GenericSuper<[T]> {
143-
override func method() { } // expected-note{{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
143+
override func method() { } // expected-note{{calls to instance method 'method()' from outside of its actor context are implicitly asynchronous}}
144144

145145
@GenericGlobalActor<T> override func method2() { } // expected-error{{global actor 'GenericGlobalActor<T>'-isolated instance method 'method2()' has different actor isolation from global actor 'GenericGlobalActor<[T]>'-isolated overridden declaration}}
146146
@actorIndependent override func method3() { } // expected-error{{actor-independent instance method 'method3()' has different actor isolation from global actor 'GenericGlobalActor<[T]>'-isolated overridden declaration}}
@@ -168,7 +168,7 @@ struct OtherContainer<U> {
168168

169169
// Ensure that substitutions work properly when inheriting.
170170
class Subclass3<V> : Container<(U, V)>.Superclass2 {
171-
func method() { } // expected-note{{only asynchronous methods can be used outside the actor instance; do you want to add 'async'?}}
171+
func method() { } // expected-note{{calls to instance method 'method()' from outside of its actor context are implicitly asynchronous}}
172172

173173
@OtherGlobalActor func testMethod() async {
174174
await method()

0 commit comments

Comments
 (0)