Skip to content

[Concurrency] await try -> try await #35214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1223,7 +1223,7 @@ ERROR(super_in_closure_with_capture,none,
NOTE(super_in_closure_with_capture_here,none,
"'self' explicitly captured here", ())

ERROR(try_before_await,none, "'await' must precede 'try'", ())
WARNING(await_before_try,none, "'try' must precede 'await'", ())
WARNING(warn_await_keyword,none,
"future versions of Swift reserve the word 'await'; "
"if this name is unavoidable, use backticks to escape it", ())
Expand Down
14 changes: 7 additions & 7 deletions lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,13 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
ParserResult<Expr> sub =
parseExprSequenceElement(diag::expected_expr_after_await, isExprBasic);
if (!sub.hasCodeCompletion() && !sub.isNull()) {
if (auto anyTry = dyn_cast<AnyTryExpr>(sub.get())) {
// "try" must precede "await".
diagnose(awaitLoc, diag::await_before_try)
.fixItRemove(awaitLoc)
.fixItInsert(anyTry->getSubExpr()->getStartLoc(), "await ");
}

ElementContext.setCreateSyntax(SyntaxKind::AwaitExpr);
sub = makeParserResult(new (Context) AwaitExpr(awaitLoc, sub.get()));
}
Expand Down Expand Up @@ -448,13 +455,6 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
: parseExprUnary(message, isExprBasic);

if (hadTry && !sub.hasCodeCompletion() && !sub.isNull()) {
// "await" must precede "try".
if (auto await = dyn_cast<AwaitExpr>(sub.get())) {
diagnose(await->getLoc(), diag::try_before_await)
.fixItRemove(await->getLoc())
.fixItInsert(tryLoc, "await ");
}

ElementContext.setCreateSyntax(SyntaxKind::TryExpr);
switch (trySuffix ? trySuffix->getKind() : tok::NUM_TOKENS) {
case tok::exclaim_postfix:
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/Concurrency/PartialAsyncTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public func withUnsafeContinuation<T>(
public func withUnsafeThrowingContinuation<T>(
_ fn: (UnsafeThrowingContinuation<T>) -> Void
) async throws -> T {
return await try Builtin.withUnsafeThrowingContinuation {
return try await Builtin.withUnsafeThrowingContinuation {
fn(UnsafeThrowingContinuation<T>($0))
}
}
2 changes: 1 addition & 1 deletion stdlib/public/Concurrency/Task.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ extension Task {
/// and throwing a specific error or using `checkCancellation` the error
/// thrown out of the task will be re-thrown here.
public func get() async throws -> Success {
return await try _taskFutureGetThrowing(task)
return try await _taskFutureGetThrowing(task)
}

/// Attempt to cancel the task.
Expand Down
12 changes: 6 additions & 6 deletions stdlib/public/Concurrency/TaskGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ extension Task {
// (although there should be none left by that time)
defer { group.cancelAll() }

let result = await try body(&group)
let result = try await body(&group)

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

return await try Handle<BodyResult>(task: groupTask).get()
return try await Handle<BodyResult>(task: groupTask).get()
}

/// A task group serves as storage for dynamically started tasks.
Expand All @@ -122,7 +122,7 @@ extension Task {
/// Add a child task to the group.
///
/// ### Error handling
/// Operations are allowed to `throw`, in which case the `await try next()`
/// Operations are allowed to `throw`, in which case the `try await next()`
/// invocation corresponding to the failed task will re-throw the given task.
///
/// The `add` function will never (re-)throw errors from the `operation`.
Expand Down Expand Up @@ -155,13 +155,13 @@ extension Task {
///
/// Await on a single completion:
///
/// if let first = await try group.next() {
/// if let first = try await group.next() {
/// return first
/// }
///
/// Wait and collect all group child task completions:
///
/// while let first = await try group.next() {
/// while let first = try await group.next() {
/// collected += value
/// }
/// return collected
Expand Down Expand Up @@ -253,7 +253,7 @@ extension Task.Group {
//
// Failures of tasks are ignored.
while !self.isEmpty {
_ = await try? self.next()
_ = try? await self.next()
// TODO: Should a failure cause a cancellation of the task group?
// This looks very much like supervision trees,
// where one may have various decisions depending on use cases...
Expand Down
12 changes: 6 additions & 6 deletions test/ClangImporter/objc_async.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import ObjCConcurrency
func testSlowServer(slowServer: SlowServer) async throws {
let _: Int = await slowServer.doSomethingSlow("mail")
let _: Bool = await slowServer.checkAvailability()
let _: String = await try slowServer.findAnswer()
let _: String = await try slowServer.findAnswerFailingly()
let _: String = try await slowServer.findAnswer()
let _: String = try await slowServer.findAnswerFailingly()

let (aOpt, b) = await try slowServer.findQAndA()
let (aOpt, b) = try await slowServer.findQAndA()
if let a = aOpt { // make sure aOpt is optional
print(a)
}
let _: String = b // make sure b is non-optional

let _: String = await try slowServer.findAnswer()
let _: String = try await slowServer.findAnswer()

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

let _: String? = await try slowServer.fortune()
let _: Int = await try slowServer.magicNumber(withSeed: 42)
let _: String? = try await slowServer.fortune()
let _: Int = try await slowServer.magicNumber(withSeed: 42)

await slowServer.serverRestart("localhost")
await slowServer.serverRestart("localhost", atPriority: 0.8)
Expand Down
2 changes: 1 addition & 1 deletion test/Concurrency/Runtime/actor_counters.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func runTest(numCounters: Int, numWorkers: Int, numIterations: Int) async {

// Wait until all of the workers have finished.
for worker in workers {
await try! worker.get()
try! await worker.get()
}

// Clear out the scratch buffer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func completeSlowly(n: Int) async -> Int {

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

let first = await try! firstHandle.get()
let first = try! await firstHandle.get()
print("firstHandle.get(): \(first)")
let second = await try! secondHandle.get()
let second = try! await secondHandle.get()
print("secondHandle.get(): \(second)")
let third = await try! thirdHandle.get()
let third = try! await thirdHandle.get()
print("thirdHandle.get(): \(third)")

var sum = 0
print("before group.next(), sum: \(sum)")
while let n = await try! group.next() {
while let n = try! await group.next() {
assert(n <= 3, "Unexpected value: \(n)! Expected <= 3")
print("next: \(n)")
sum += n
Expand Down
4 changes: 2 additions & 2 deletions test/Concurrency/Runtime/async_taskgroup_is_empty.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func asyncEcho(_ value: Int) async -> Int {
}

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

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

// CHECK: next: 1
while let value = await try! group.next() {
while let value = try! await group.next() {
print("next: \(value)")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Dispatch
func test_skipCallingNext_butInvokeCancelAll() async {
let numbers = [1, 1]

let result = await try! Task.withGroup(resultType: Int.self) { (group) async -> Int in
let result = try! await Task.withGroup(resultType: Int.self) { (group) async -> Int in
for n in numbers {
print("group.add { \(n) }")
await group.add { () async -> Int in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import func Foundation.sleep
func test_skipCallingNext() async {
let numbers = [1, 1]

let result = await try! Task.withGroup(resultType: Int.self) { (group) async -> Int in
let result = try! await Task.withGroup(resultType: Int.self) { (group) async -> Int in
for n in numbers {
print("group.add { \(n) }")
await group.add { () async -> Int in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func test_sum_nextOnCompleted() async {
let numbers = [1, 2, 3, 4, 5]
let expected = numbers.reduce(0, +)

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

var sum = 0
do {
while let r = await try group.next() {
while let r = try await group.next() {
fputs("error: \(#function)[\(#file):\(#line)]: next: \(r)\n", stderr)
print("next: \(r)")
// DispatchQueue.main.sync { // TODO: remove once executors/actors are a thing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func test_sum_nextOnPending() async {
let numbers = [1, 2, 3]
let expected = numbers.reduce(0, +)

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

var sum = 0
print("before group.next(), sum: \(sum)")
while let n = await try! group.next() {
while let n = try! await group.next() {
assert(numbers.contains(n), "Unexpected value: \(n)! Expected any of \(numbers)")
print("next: \(n)")
sum += n
Expand Down
10 changes: 5 additions & 5 deletions test/Concurrency/Runtime/async_taskgroup_throw_recover.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ async throws -> Int {

func test_taskGroup_throws() async {
do {
let got = await try Task.withGroup(resultType: Int.self) {
let got = try await Task.withGroup(resultType: Int.self) {
group async throws -> Int in
await group.add { await one() }
await group.add { await try boom() }
await group.add { try await boom() }

do {
while let r = await try group.next() {
while let r = try await group.next() {
print("next: \(r)")
}
} catch {
Expand All @@ -43,7 +43,7 @@ func test_taskGroup_throws() async {
return 3
}

guard let got = await try! group.next() else {
guard let got = try! await group.next() else {
print("task group failed to get 3 (:\(#line))")
return 0
}
Expand All @@ -53,7 +53,7 @@ func test_taskGroup_throws() async {
if got == 1 {
// the previous 1 completed before the 3 we just submitted,
// we still want to see that three so let's await for it
guard let third = await try! group.next() else {
guard let third = try! await group.next() else {
print("task group failed to get 3 (:\(#line))")
return got
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ func boom() async throws -> Int { throw Boom() }

func test_taskGroup_throws_rethrows() async {
do {
let got = await try Task.withGroup(resultType: Int.self) { (group) async throws -> Int in
let got = try await Task.withGroup(resultType: Int.self) { (group) async throws -> Int in
await group.add { await echo(1) }
await group.add { await echo(2) }
await group.add { await try boom() }
await group.add { try await boom() }

do {
while let r = await try group.next() {
while let r = try await group.next() {
print("next: \(r)")
}
} catch {
Expand Down
2 changes: 1 addition & 1 deletion test/Concurrency/Runtime/basic_future.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func testSimple(

do {
print("+ Reader waiting for the result")
let result = await try taskHandle.get()
let result = try await taskHandle.get()
completed = true
print("+ Normal return: \(result)")
assert(result == "Hello \(name) from async world!")
Expand Down
2 changes: 1 addition & 1 deletion test/Concurrency/Runtime/future_fibonacci.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func asyncFib(_ n: Int) async -> Int {
// Sleep a random amount of time waiting on the result producing a result.
usleep(UInt32.random(in: 0..<100) * 1000)

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

// Sleep a random amount of time before producing a result.
usleep(UInt32.random(in: 0..<100) * 1000)
Expand Down
4 changes: 2 additions & 2 deletions test/Concurrency/async_cancellation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ enum PictureData {
}

func test_cancellation_checkCancellation() async throws {
await try Task.checkCancellation()
try await Task.checkCancellation()
}

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

return await try Task.withCancellationHandler(
return try await Task.withCancellationHandler(
handler: { file.close() },
operation: {
await test_cancellation_guard_isCancelled(file)
Expand Down
Loading