Skip to content

Commit 3c38ffe

Browse files
committed
[Concurrency] await try -> try await
The `try await` ordering is both easier to read and indicates the order of operations better, because the suspension point occurs first and then one can observe a thrown error.
1 parent b99533a commit 3c38ffe

29 files changed

+124
-124
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,7 @@ ERROR(super_in_closure_with_capture,none,
12231223
NOTE(super_in_closure_with_capture_here,none,
12241224
"'self' explicitly captured here", ())
12251225

1226-
ERROR(try_before_await,none, "'await' must precede 'try'", ())
1226+
WARNING(await_before_try,none, "'try' must precede 'await'", ())
12271227
WARNING(warn_await_keyword,none,
12281228
"future versions of Swift reserve the word 'await'; "
12291229
"if this name is unavoidable, use backticks to escape it", ())

lib/Parse/ParseExpr.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,13 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
405405
ParserResult<Expr> sub =
406406
parseExprSequenceElement(diag::expected_expr_after_await, isExprBasic);
407407
if (!sub.hasCodeCompletion() && !sub.isNull()) {
408+
if (auto anyTry = dyn_cast<AnyTryExpr>(sub.get())) {
409+
// "try" must precede "await".
410+
diagnose(awaitLoc, diag::await_before_try)
411+
.fixItRemove(awaitLoc)
412+
.fixItInsert(anyTry->getSubExpr()->getStartLoc(), "await ");
413+
}
414+
408415
ElementContext.setCreateSyntax(SyntaxKind::AwaitExpr);
409416
sub = makeParserResult(new (Context) AwaitExpr(awaitLoc, sub.get()));
410417
}
@@ -448,13 +455,6 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
448455
: parseExprUnary(message, isExprBasic);
449456

450457
if (hadTry && !sub.hasCodeCompletion() && !sub.isNull()) {
451-
// "await" must precede "try".
452-
if (auto await = dyn_cast<AwaitExpr>(sub.get())) {
453-
diagnose(await->getLoc(), diag::try_before_await)
454-
.fixItRemove(await->getLoc())
455-
.fixItInsert(tryLoc, "await ");
456-
}
457-
458458
ElementContext.setCreateSyntax(SyntaxKind::TryExpr);
459459
switch (trySuffix ? trySuffix->getKind() : tok::NUM_TOKENS) {
460460
case tok::exclaim_postfix:

stdlib/public/Concurrency/PartialAsyncTask.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public func withUnsafeContinuation<T>(
9898
public func withUnsafeThrowingContinuation<T>(
9999
_ fn: (UnsafeThrowingContinuation<T>) -> Void
100100
) async throws -> T {
101-
return await try Builtin.withUnsafeThrowingContinuation {
101+
return try await Builtin.withUnsafeThrowingContinuation {
102102
fn(UnsafeThrowingContinuation<T>($0))
103103
}
104104
}

stdlib/public/Concurrency/Task.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ extension Task {
122122
/// and throwing a specific error or using `checkCancellation` the error
123123
/// thrown out of the task will be re-thrown here.
124124
public func get() async throws -> Success {
125-
return await try _taskFutureGetThrowing(task)
125+
return try await _taskFutureGetThrowing(task)
126126
}
127127

128128
/// Attempt to cancel the task.

stdlib/public/Concurrency/TaskGroup.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ extension Task {
8686
// (although there should be none left by that time)
8787
defer { group.cancelAll() }
8888

89-
let result = await try body(&group)
89+
let result = try await body(&group)
9090

9191
/// Drain all remaining tasks by awaiting on them;
9292
/// Their failures are ignored;
@@ -98,7 +98,7 @@ extension Task {
9898
// Enqueue the resulting job.
9999
_enqueueJobGlobal(Builtin.convertTaskToJob(groupTask))
100100

101-
return await try Handle<BodyResult>(task: groupTask).get()
101+
return try await Handle<BodyResult>(task: groupTask).get()
102102
}
103103

104104
/// A task group serves as storage for dynamically started tasks.
@@ -122,7 +122,7 @@ extension Task {
122122
/// Add a child task to the group.
123123
///
124124
/// ### Error handling
125-
/// Operations are allowed to `throw`, in which case the `await try next()`
125+
/// Operations are allowed to `throw`, in which case the `try await next()`
126126
/// invocation corresponding to the failed task will re-throw the given task.
127127
///
128128
/// The `add` function will never (re-)throw errors from the `operation`.
@@ -155,13 +155,13 @@ extension Task {
155155
///
156156
/// Await on a single completion:
157157
///
158-
/// if let first = await try group.next() {
158+
/// if let first = try await group.next() {
159159
/// return first
160160
/// }
161161
///
162162
/// Wait and collect all group child task completions:
163163
///
164-
/// while let first = await try group.next() {
164+
/// while let first = try await group.next() {
165165
/// collected += value
166166
/// }
167167
/// return collected
@@ -253,7 +253,7 @@ extension Task.Group {
253253
//
254254
// Failures of tasks are ignored.
255255
while !self.isEmpty {
256-
_ = await try? self.next()
256+
_ = try? await self.next()
257257
// TODO: Should a failure cause a cancellation of the task group?
258258
// This looks very much like supervision trees,
259259
// where one may have various decisions depending on use cases...

test/ClangImporter/objc_async.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ import ObjCConcurrency
88
func testSlowServer(slowServer: SlowServer) async throws {
99
let _: Int = await slowServer.doSomethingSlow("mail")
1010
let _: Bool = await slowServer.checkAvailability()
11-
let _: String = await try slowServer.findAnswer()
12-
let _: String = await try slowServer.findAnswerFailingly()
11+
let _: String = try await slowServer.findAnswer()
12+
let _: String = try await slowServer.findAnswerFailingly()
1313

14-
let (aOpt, b) = await try slowServer.findQAndA()
14+
let (aOpt, b) = try await slowServer.findQAndA()
1515
if let a = aOpt { // make sure aOpt is optional
1616
print(a)
1717
}
1818
let _: String = b // make sure b is non-optional
1919

20-
let _: String = await try slowServer.findAnswer()
20+
let _: String = try await slowServer.findAnswer()
2121

2222
let _: Void = await slowServer.doSomethingFun("jump")
2323
let _: (Int) -> Void = slowServer.completionHandler
@@ -29,8 +29,8 @@ func testSlowServer(slowServer: SlowServer) async throws {
2929
let _: Int = slowServer.doSomethingConflicted("thinking")
3030
// expected-error@-1{{call is 'async' but is not marked with 'await'}}{{16-16=await }}
3131

32-
let _: String? = await try slowServer.fortune()
33-
let _: Int = await try slowServer.magicNumber(withSeed: 42)
32+
let _: String? = try await slowServer.fortune()
33+
let _: Int = try await slowServer.magicNumber(withSeed: 42)
3434

3535
await slowServer.serverRestart("localhost")
3636
await slowServer.serverRestart("localhost", atPriority: 0.8)

test/Concurrency/Runtime/actor_counters.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func runTest(numCounters: Int, numWorkers: Int, numIterations: Int) async {
7070

7171
// Wait until all of the workers have finished.
7272
for worker in workers {
73-
await try! worker.get()
73+
try! await worker.get()
7474
}
7575

7676
// Clear out the scratch buffer.

test/Concurrency/Runtime/async_taskgroup_add_handle_completion.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func completeSlowly(n: Int) async -> Int {
2020

2121
/// Tasks complete AFTER they are next() polled.
2222
func test_sum_nextOnPending() async {
23-
let sum = await try! Task.withGroup(resultType: Int.self) { (group) async -> Int in
23+
let sum = try! await Task.withGroup(resultType: Int.self) { (group) async -> Int in
2424
let firstHandle = await group.add {
2525
let res = await completeSlowly(n: 1)
2626
return res
@@ -34,16 +34,16 @@ func test_sum_nextOnPending() async {
3434
return res
3535
}
3636

37-
let first = await try! firstHandle.get()
37+
let first = try! await firstHandle.get()
3838
print("firstHandle.get(): \(first)")
39-
let second = await try! secondHandle.get()
39+
let second = try! await secondHandle.get()
4040
print("secondHandle.get(): \(second)")
41-
let third = await try! thirdHandle.get()
41+
let third = try! await thirdHandle.get()
4242
print("thirdHandle.get(): \(third)")
4343

4444
var sum = 0
4545
print("before group.next(), sum: \(sum)")
46-
while let n = await try! group.next() {
46+
while let n = try! await group.next() {
4747
assert(n <= 3, "Unexpected value: \(n)! Expected <= 3")
4848
print("next: \(n)")
4949
sum += n

test/Concurrency/Runtime/async_taskgroup_is_empty.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func asyncEcho(_ value: Int) async -> Int {
1717
}
1818

1919
func test_taskGroup_isEmpty() async {
20-
_ = await try! Task.withGroup(resultType: Int.self) { (group) async -> Int in
20+
_ = try! await Task.withGroup(resultType: Int.self) { (group) async -> Int in
2121
// CHECK: before add: isEmpty=true
2222
print("before add: isEmpty=\(group.isEmpty)")
2323

@@ -30,7 +30,7 @@ func test_taskGroup_isEmpty() async {
3030
print("while add running, outside: isEmpty=\(group.isEmpty)")
3131

3232
// CHECK: next: 1
33-
while let value = await try! group.next() {
33+
while let value = try! await group.next() {
3434
print("next: \(value)")
3535
}
3636

test/Concurrency/Runtime/async_taskgroup_next_not_invoked_cancelAll.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Dispatch
99
func test_skipCallingNext_butInvokeCancelAll() async {
1010
let numbers = [1, 1]
1111

12-
let result = await try! Task.withGroup(resultType: Int.self) { (group) async -> Int in
12+
let result = try! await Task.withGroup(resultType: Int.self) { (group) async -> Int in
1313
for n in numbers {
1414
print("group.add { \(n) }")
1515
await group.add { () async -> Int in

test/Concurrency/Runtime/async_taskgroup_next_not_invoked_without_cancelAll.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import func Foundation.sleep
99
func test_skipCallingNext() async {
1010
let numbers = [1, 1]
1111

12-
let result = await try! Task.withGroup(resultType: Int.self) { (group) async -> Int in
12+
let result = try! await Task.withGroup(resultType: Int.self) { (group) async -> Int in
1313
for n in numbers {
1414
print("group.add { \(n) }")
1515
await group.add { () async -> Int in

test/Concurrency/Runtime/async_taskgroup_next_on_completed.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func test_sum_nextOnCompleted() async {
1616
let numbers = [1, 2, 3, 4, 5]
1717
let expected = numbers.reduce(0, +)
1818

19-
let sum = await try! Task.withGroup(resultType: Int.self) { (group) async -> Int in
19+
let sum = try! await Task.withGroup(resultType: Int.self) { (group) async -> Int in
2020
for n in numbers {
2121
await group.add { () async -> Int in
2222
print(" complete group.add { \(n) }")
@@ -30,7 +30,7 @@ func test_sum_nextOnCompleted() async {
3030

3131
var sum = 0
3232
do {
33-
while let r = await try group.next() {
33+
while let r = try await group.next() {
3434
fputs("error: \(#function)[\(#file):\(#line)]: next: \(r)\n", stderr)
3535
print("next: \(r)")
3636
// DispatchQueue.main.sync { // TODO: remove once executors/actors are a thing

test/Concurrency/Runtime/async_taskgroup_next_on_pending.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func test_sum_nextOnPending() async {
1818
let numbers = [1, 2, 3]
1919
let expected = numbers.reduce(0, +)
2020

21-
let sum = await try! Task.withGroup(resultType: Int.self) { (group) async -> Int in
21+
let sum = try! await Task.withGroup(resultType: Int.self) { (group) async -> Int in
2222
for n in numbers {
2323
await group.add {
2424
let res = await completeSlowly(n: n)
@@ -28,7 +28,7 @@ func test_sum_nextOnPending() async {
2828

2929
var sum = 0
3030
print("before group.next(), sum: \(sum)")
31-
while let n = await try! group.next() {
31+
while let n = try! await group.next() {
3232
assert(numbers.contains(n), "Unexpected value: \(n)! Expected any of \(numbers)")
3333
print("next: \(n)")
3434
sum += n

test/Concurrency/Runtime/async_taskgroup_throw_recover.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ async throws -> Int {
2626

2727
func test_taskGroup_throws() async {
2828
do {
29-
let got = await try Task.withGroup(resultType: Int.self) {
29+
let got = try await Task.withGroup(resultType: Int.self) {
3030
group async throws -> Int in
3131
await group.add { await one() }
32-
await group.add { await try boom() }
32+
await group.add { try await boom() }
3333

3434
do {
35-
while let r = await try group.next() {
35+
while let r = try await group.next() {
3636
print("next: \(r)")
3737
}
3838
} catch {
@@ -43,7 +43,7 @@ func test_taskGroup_throws() async {
4343
return 3
4444
}
4545

46-
guard let got = await try! group.next() else {
46+
guard let got = try! await group.next() else {
4747
print("task group failed to get 3 (:\(#line))")
4848
return 0
4949
}
@@ -53,7 +53,7 @@ func test_taskGroup_throws() async {
5353
if got == 1 {
5454
// the previous 1 completed before the 3 we just submitted,
5555
// we still want to see that three so let's await for it
56-
guard let third = await try! group.next() else {
56+
guard let third = try! await group.next() else {
5757
print("task group failed to get 3 (:\(#line))")
5858
return got
5959
}

test/Concurrency/Runtime/async_taskgroup_throw_rethrow.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ func boom() async throws -> Int { throw Boom() }
1414

1515
func test_taskGroup_throws_rethrows() async {
1616
do {
17-
let got = await try Task.withGroup(resultType: Int.self) { (group) async throws -> Int in
17+
let got = try await Task.withGroup(resultType: Int.self) { (group) async throws -> Int in
1818
await group.add { await echo(1) }
1919
await group.add { await echo(2) }
20-
await group.add { await try boom() }
20+
await group.add { try await boom() }
2121

2222
do {
23-
while let r = await try group.next() {
23+
while let r = try await group.next() {
2424
print("next: \(r)")
2525
}
2626
} catch {

test/Concurrency/Runtime/basic_future.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func testSimple(
5656

5757
do {
5858
print("+ Reader waiting for the result")
59-
let result = await try taskHandle.get()
59+
let result = try await taskHandle.get()
6060
completed = true
6161
print("+ Normal return: \(result)")
6262
assert(result == "Hello \(name) from async world!")

test/Concurrency/Runtime/future_fibonacci.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func asyncFib(_ n: Int) async -> Int {
3939
// Sleep a random amount of time waiting on the result producing a result.
4040
usleep(UInt32.random(in: 0..<100) * 1000)
4141

42-
let result = await try! first.get() + second.get()
42+
let result = try! await first.get() + second.get()
4343

4444
// Sleep a random amount of time before producing a result.
4545
usleep(UInt32.random(in: 0..<100) * 1000)

test/Concurrency/async_cancellation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ enum PictureData {
77
}
88

99
func test_cancellation_checkCancellation() async throws {
10-
await try Task.checkCancellation()
10+
try await Task.checkCancellation()
1111
}
1212

1313
func test_cancellation_guard_isCancelled(_ any: Any) async -> PictureData {
@@ -26,7 +26,7 @@ func test_cancellation_withCancellationHandler(_ anything: Any) async -> Picture
2626
let handle = Task.runDetached { () -> PictureData in
2727
let file = SomeFile()
2828

29-
return await try Task.withCancellationHandler(
29+
return try await Task.withCancellationHandler(
3030
handler: { file.close() },
3131
operation: {
3232
await test_cancellation_guard_isCancelled(file)

0 commit comments

Comments
 (0)