Skip to content

Commit 37d02a2

Browse files
authored
Merge pull request #35930 from kavon/async-fixit
2 parents aef551b + 9342540 commit 37d02a2

9 files changed

+42
-25
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,22 @@ static bool checkAsyncHandler(FuncDecl *func, bool diagnose) {
116116

117117
void swift::addAsyncNotes(AbstractFunctionDecl const* func) {
118118
assert(func);
119-
if (!isa<DestructorDecl>(func))
120-
func->diagnose(diag::note_add_async_to_function, func->getName());
121-
// TODO: we need a source location for effects attributes so that we
122-
// can also emit a fix-it that inserts 'async' in the right place for func.
123-
// It's possibly a bit tricky to get the right source location from
124-
// just the AbstractFunctionDecl, but it's important to circle-back
125-
// to this.
119+
if (!isa<DestructorDecl>(func)) {
120+
auto note =
121+
func->diagnose(diag::note_add_async_to_function, func->getName());
122+
123+
if (func->hasThrows()) {
124+
auto replacement = func->getAttrs().hasAttribute<RethrowsAttr>()
125+
? "async rethrows"
126+
: "async throws";
127+
128+
note.fixItReplace(SourceRange(func->getThrowsLoc()), replacement);
129+
130+
} else {
131+
note.fixItInsert(func->getParameters()->getRParenLoc().getAdvancedLoc(1),
132+
" async");
133+
}
134+
}
126135

127136
if (func->canBeAsyncHandler()) {
128137
func->diagnose(

test/Concurrency/actor_call_implicitly_async.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func anotherAsyncFunc() async {
125125

126126
}
127127

128-
// expected-note@+2 {{add 'async' to function 'regularFunc()' to make it asynchronous}} {{none}}
128+
// expected-note@+2 {{add 'async' to function 'regularFunc()' to make it asynchronous}} {{19-19= async}}
129129
// expected-note@+1 {{add '@asyncHandler' to function 'regularFunc()' to create an implicit asynchronous context}} {{1-1=@asyncHandler }}
130130
func regularFunc() {
131131
let a = BankAccount(initialDeposit: 34)

test/Concurrency/actor_isolation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ extension MyActor {
4545
set { }
4646
}
4747

48-
// expected-note@+1 {{add 'async' to function 'actorIndependentFunc(otherActor:)' to make it asynchronous}} {{none}}
48+
// expected-note@+1 {{add 'async' to function 'actorIndependentFunc(otherActor:)' to make it asynchronous}} {{67-67= async}}
4949
@actorIndependent func actorIndependentFunc(otherActor: MyActor) -> Int {
5050
_ = immutable
5151
_ = text[0] // expected-error{{actor-isolated property 'text' can not be referenced from an '@actorIndependent' context}}
@@ -279,7 +279,7 @@ struct GenericStruct<T> {
279279
}
280280

281281
// expected-note@+2 {{add '@asyncHandler' to function 'h()' to create an implicit asynchronous context}} {{3-3=@asyncHandler }}
282-
// expected-note@+1 {{add 'async' to function 'h()' to make it asynchronous}} {{none}}
282+
// expected-note@+1 {{add 'async' to function 'h()' to make it asynchronous}} {{39-39= async}}
283283
@GenericGlobalActor<String> func h() {
284284
f() // expected-error{{'async' in a function that does not support concurrency}}
285285
_ = f // expected-error{{instance method 'f()' isolated to global actor 'GenericGlobalActor<T>' can not be referenced from different global actor 'GenericGlobalActor<String>'}}

test/Concurrency/async_throwing.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func throwingTask() async throws -> String {
4545
}
4646

4747
// expected-note@+2 7 {{add '@asyncHandler' to function 'syncTest()' to create an implicit asynchronous context}} {{1-1=@asyncHandler }}
48-
// expected-note@+1 7 {{add 'async' to function 'syncTest()' to make it asynchronous}} {{none}}
48+
// expected-note@+1 7 {{add 'async' to function 'syncTest()' to make it asynchronous}} {{16-16= async}}
4949
func syncTest() {
5050
let _ = invoke(fn: normalTask) // expected-error{{'async' in a function that does not support concurrency}}
5151
let _ = invokeAuto(42) // expected-error{{'async' in a function that does not support concurrency}}

test/Concurrency/global_actor_from_ordinary_context.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ func referenceGlobalActor2() {
4949

5050

5151
// expected-note@+2 {{add '@asyncHandler' to function 'referenceAsyncGlobalActor()' to create an implicit asynchronous context}} {{1-1=@asyncHandler }}
52-
// expected-note@+1 {{add 'async' to function 'referenceAsyncGlobalActor()' to make it asynchronous}} {{none}}
52+
// expected-note@+1 {{add 'async' to function 'referenceAsyncGlobalActor()' to make it asynchronous}} {{33-33= async}}
5353
func referenceAsyncGlobalActor() {
5454
let y = asyncGlobalActFn
5555
y() // expected-error{{'async' in a function that does not support concurrency}}
5656
}
5757

5858

5959
// expected-note@+3 {{add '@asyncHandler' to function 'callGlobalActor()' to create an implicit asynchronous context}} {{1-1=@asyncHandler }}
60-
// expected-note@+2 {{add 'async' to function 'callGlobalActor()' to make it asynchronous}} {{none}}
60+
// expected-note@+2 {{add 'async' to function 'callGlobalActor()' to make it asynchronous}} {{23-23= async}}
6161
// expected-note@+1 {{add '@SomeGlobalActor' to make global function 'callGlobalActor()' part of global actor 'SomeGlobalActor'}} {{1-1=@SomeGlobalActor }}
6262
func callGlobalActor() {
6363
syncGlobActorFn() // expected-error {{'async' in a function that does not support concurrency}}
@@ -76,7 +76,7 @@ func fromClosure() {
7676
}
7777

7878
class Taylor {
79-
init() { // expected-note {{add 'async' to function 'init()' to make it asynchronous}} {{none}}
79+
init() { // expected-note {{add 'async' to function 'init()' to make it asynchronous}} {{9-9= async}}
8080
syncGlobActorFn() // expected-error {{'async' in a function that does not support concurrency}}
8181

8282
// expected-error@+1 {{global function 'syncGlobActorFn()' isolated to global actor 'SomeGlobalActor' can not be referenced from this context}}
@@ -92,7 +92,7 @@ class Taylor {
9292

9393
// expected-note@+3 2 {{add '@SomeGlobalActor' to make instance method 'method1()' part of global actor 'SomeGlobalActor'}} {{3-3=@SomeGlobalActor }}
9494
// expected-note@+2 {{add '@asyncHandler' to function 'method1()' to create an implicit asynchronous context}} {{3-3=@asyncHandler }}
95-
// expected-note@+1 {{add 'async' to function 'method1()' to make it asynchronous}} {{none}}
95+
// expected-note@+1 {{add 'async' to function 'method1()' to make it asynchronous}} {{17-17= async}}
9696
func method1() {
9797
syncGlobActorFn() // expected-error {{'async' in a function that does not support concurrency}}
9898

test/Concurrency/global_actor_inference.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class C1: P1 {
4646
func method() { } // expected-note {{calls to instance method 'method()' from outside of its actor context are implicitly asynchronous}}
4747

4848
// expected-note@+2 {{add '@asyncHandler' to function 'testMethod()' to create an implicit asynchronous context}} {{3-3=@asyncHandler }}
49-
// expected-note@+1 {{add 'async' to function 'testMethod()' to make it asynchronous}} {{none}}
49+
// expected-note@+1 {{add 'async' to function 'testMethod()' to make it asynchronous}} {{38-38= async}}
5050
@OtherGlobalActor func testMethod() {
5151
method() // expected-error {{'async' in a function that does not support concurrency}}
5252
_ = method // expected-error {{instance method 'method()' isolated to global actor 'SomeGlobalActor' can not be referenced from different global actor 'OtherGlobalActor'}}
@@ -58,7 +58,7 @@ class C2: P2 {
5858
func method2() { }
5959

6060
// expected-note@+2 {{add '@asyncHandler' to function 'testMethod()' to create an implicit asynchronous context}} {{3-3=@asyncHandler }}
61-
// expected-note@+1 {{add 'async' to function 'testMethod()' to make it asynchronous}} {{none}}
61+
// expected-note@+1 {{add 'async' to function 'testMethod()' to make it asynchronous}} {{38-38= async}}
6262
@OtherGlobalActor func testMethod() {
6363
method1() // expected-error{{'async' in a function that does not support concurrency}}
6464
_ = method1 // expected-error{{instance method 'method1()' isolated to global actor 'SomeGlobalActor' can not be referenced from different global actor 'OtherGlobalActor'}}
@@ -94,7 +94,7 @@ class C5 {
9494
}
9595

9696
// expected-note@+2 5 {{add '@asyncHandler' to function 'testGlobalActorInference(c3:c4:c5:)' to create an implicit asynchronous context}} {{1-1=@asyncHandler }}
97-
// expected-note@+1 5 {{add 'async' to function 'testGlobalActorInference(c3:c4:c5:)' to make it asynchronous}} {{none}}
97+
// expected-note@+1 5 {{add 'async' to function 'testGlobalActorInference(c3:c4:c5:)' to make it asynchronous}} {{72-72= async}}
9898
@OtherGlobalActor func testGlobalActorInference(c3: C3, c4: C4, c5: C5) {
9999
// Propagation via class annotation
100100
c3.method1() // expected-error{{'async' in a function that does not support concurrency}}
@@ -156,7 +156,7 @@ actor GenericSub<T> : GenericSuper<[T]> {
156156
@actorIndependent override func method3() { } // expected-error{{actor-independent instance method 'method3()' has different actor isolation from global actor 'GenericGlobalActor<[T]>'-isolated overridden declaration}}
157157

158158
// expected-note@+2 {{add '@asyncHandler' to function 'testMethod()' to create an implicit asynchronous context}} {{3-3=@asyncHandler }}
159-
// expected-note@+1 {{add 'async' to function 'testMethod()' to make it asynchronous}} {{none}}
159+
// expected-note@+1 {{add 'async' to function 'testMethod()' to make it asynchronous}} {{38-38= async}}
160160
@OtherGlobalActor func testMethod() {
161161
method() // expected-error{{'async' in a function that does not support concurrency}}
162162
_ = method // expected-error{{instance method 'method()' isolated to global actor 'GenericGlobalActor<[T]>' can not be referenced from different global actor 'OtherGlobalActor'}}
@@ -233,7 +233,7 @@ func bar() async {
233233

234234
// expected-note@+3 {{add '@SomeGlobalActor' to make global function 'barSync()' part of global actor 'SomeGlobalActor'}} {{1-1=@SomeGlobalActor }}
235235
// expected-note@+2 {{add '@asyncHandler' to function 'barSync()' to create an implicit asynchronous context}} {{1-1=@asyncHandler }}
236-
// expected-note@+1 {{add 'async' to function 'barSync()' to make it asynchronous}} {{none}}
236+
// expected-note@+1 {{add 'async' to function 'barSync()' to make it asynchronous}} {{15-15= async}}
237237
func barSync() {
238238
foo() // expected-error {{'async' in a function that does not support concurrency}}
239239
}

test/attr/asynchandler.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class Y: P {
6060
// @asyncHandler is not inferred for classes
6161

6262
func callback() {
63-
// expected-note@-1{{add 'async' to function 'callback()' to make it asynchronous}} {{none}}
63+
// expected-note@-1{{add 'async' to function 'callback()' to make it asynchronous}} {{18-18= async}}
6464
// expected-note@-2{{add '@asyncHandler' to function 'callback()' to create an implicit asynchronous context}} {{3-3=@asyncHandler }}
6565

6666
// okay, it's an async context

test/attr/attr_objc_async.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ actor MyActor {
3737

3838
// Actor-isolated entities cannot be exposed to Objective-C.
3939
@objc func synchronousBad() { } // expected-error{{actor-isolated instance method 'synchronousBad()' cannot be @objc}}
40-
// expected-note@-1{{add 'async' to function 'synchronousBad()' to make it asynchronous}} {{none}}
40+
// expected-note@-1{{add 'async' to function 'synchronousBad()' to make it asynchronous}} {{30-30= async}}
4141
// expected-note@-2{{add '@asyncHandler' to function 'synchronousBad()' to create an implicit asynchronous context}} {{3-3=@asyncHandler }}
4242

4343
@objc var badProp: AnyObject { self } // expected-error{{actor-isolated property 'badProp' cannot be @objc}}

test/expr/unary/async_await.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,19 @@ func test2(
2222
print("foo")
2323
}
2424

25-
func test3() { // expected-note{{add 'async' to function 'test3()' to make it asynchronous}} {{none}}
25+
func test3() { // expected-note{{add 'async' to function 'test3()' to make it asynchronous}} {{13-13= async}}
2626
// expected-note@-1{{add '@asyncHandler' to function 'test3()' to create an implicit asynchronous context}}{{1-1=@asyncHandler }}
2727
_ = await getInt() // expected-error{{'async' in a function that does not support concurrency}}
2828
}
2929

30+
func test4()throws { // expected-note{{add 'async' to function 'test4()' to make it asynchronous}} {{13-19=async throws}}
31+
_ = await getInt() // expected-error{{'async' in a function that does not support concurrency}}
32+
}
33+
34+
func test5<T>(_ f : () async throws -> T) rethrows->T { // expected-note{{add 'async' to function 'test5' to make it asynchronous}} {{44-52=async rethrows}}
35+
return try await f() // expected-error{{'async' in a function that does not support concurrency}}
36+
}
37+
3038
enum SomeEnum: Int {
3139
case foo = await 5 // expected-error{{raw value for enum case must be a literal}}
3240
}
@@ -43,7 +51,7 @@ func acceptAutoclosureAsyncThrowsRethrows(_: @autoclosure () async throws -> Int
4351

4452
func acceptAutoclosureNonAsyncBad(_: @autoclosure () async -> Int) -> Int { 0 }
4553
// expected-error@-1{{'async' autoclosure parameter in a non-'async' function}}
46-
// expected-note@-2{{add 'async' to function 'acceptAutoclosureNonAsyncBad' to make it asynchronous}} {{none}}
54+
// expected-note@-2{{add 'async' to function 'acceptAutoclosureNonAsyncBad' to make it asynchronous}} {{67-67= async}}
4755

4856
struct HasAsyncBad {
4957
init(_: @autoclosure () async -> Int) { }
@@ -182,7 +190,7 @@ func testAsyncLet() async throws {
182190
_ = await x5
183191
}
184192

185-
// expected-note@+2 4{{add 'async' to function 'testAsyncLetOutOfAsync()' to make it asynchronous}} {{none}}
193+
// expected-note@+2 4{{add 'async' to function 'testAsyncLetOutOfAsync()' to make it asynchronous}} {{30-30= async}}
186194
// expected-note@+1 4{{add '@asyncHandler' to function 'testAsyncLetOutOfAsync()' to create an implicit asynchronous context}} {{1-1=@asyncHandler }}
187195
func testAsyncLetOutOfAsync() {
188196
async let x = 1 // expected-error{{'async let' in a function that does not support concurrency}}

0 commit comments

Comments
 (0)