// RUN: %empty-directory(%t) func withAsyncAlternative(completionHandler: @escaping (Int) -> Void) {} func withAsyncAlternative() async -> Int { return 42 } func withAsyncThrowingAlternative(completionHandler: @escaping (Int?, Error?) -> Void) {} func withAsyncThrowingAlternative() async throws -> Int { return 42 } func withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName(closure: @escaping (Int) -> Void) {} func withoutAsyncAlternativeBecauseOfReturnValue(completionHandler: @escaping (Int) -> Void) -> Bool { return true } func withoutAsyncAlternativeThrowing(closure: @escaping (Int?, Error?) -> Void) {} func withoutAsyncAlternativeThrowingWithMultipleResults(closure: @escaping (Int?, String?, Error?) -> Void) {} func asyncVoidWithoutAlternative(completionHandler2: @escaping () -> Void) {} func resultWithoutAlternative(completionHandler2: @escaping (Result) -> Void) {} func lottaClosures(x: () -> Void, y: () -> Void) -> Int? { nil } struct MyError: Error {} // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=CREATE-CONTINUATION %s func testCreateContinuation(completionHandler: @escaping (Int) -> Void) { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { completionHandler($0) } } // CREATE-CONTINUATION: func testCreateContinuation() async -> Int { // CREATE-CONTINUATION-NEXT: return await withCheckedContinuation { continuation in // CREATE-CONTINUATION-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { // CREATE-CONTINUATION-NEXT: continuation.resume(returning: $0) // CREATE-CONTINUATION-NEXT: } // CREATE-CONTINUATION-NEXT: } // CREATE-CONTINUATION-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS %s func testCreateContinuationWithCompletionHandlerCallInParens(completionHandler: @escaping (Int) -> Void) { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { (completionHandler($0)) } } // CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS: func testCreateContinuationWithCompletionHandlerCallInParens() async -> Int { // CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: return await withCheckedContinuation { continuation in // CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { // CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: continuation.resume(returning: $0) // CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: } // CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: } // CREATE-CONTINUATION-HANDLER-CALL-IN-PARENS-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=CREATE-CONTINUATION-BECAUSE-RETURN-VALUE %s func testCreateContinuationBecauseOfReturnValue(completionHandler: @escaping (Int) -> Void) { _ = withoutAsyncAlternativeBecauseOfReturnValue { completionHandler($0) } } // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE: func testCreateContinuationBecauseOfReturnValue() async -> Int { // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: return await withCheckedContinuation { continuation in // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: _ = withoutAsyncAlternativeBecauseOfReturnValue { // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: continuation.resume(returning: $0) // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: } // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: } // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2 %s func testCreateContinuationBecauseOfReturnValue2(completionHandler: @escaping (Int) -> Void) { let x = withoutAsyncAlternativeBecauseOfReturnValue { completionHandler($0) } print(x) } // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2: func testCreateContinuationBecauseOfReturnValue2() async -> Int { // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: return await withCheckedContinuation { continuation in // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: let x = withoutAsyncAlternativeBecauseOfReturnValue { // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: continuation.resume(returning: $0) // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: } // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: print(x) // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: } // CREATE-CONTINUATION-BECAUSE-RETURN-VALUE-2-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=CONTINUATION-IN-NESTED-EXPRESSION %s func testCompletionHandlerCallInNestedExpression(completionHandler: @escaping (Int) -> Void) { print(withoutAsyncAlternativeBecauseOfReturnValue { completionHandler($0) }) } // CONTINUATION-IN-NESTED-EXPRESSION: func testCompletionHandlerCallInNestedExpression() async -> Int { // CONTINUATION-IN-NESTED-EXPRESSION-NEXT: return await withCheckedContinuation { continuation in // CONTINUATION-IN-NESTED-EXPRESSION-NEXT: print(withoutAsyncAlternativeBecauseOfReturnValue { // CONTINUATION-IN-NESTED-EXPRESSION-NEXT: continuation.resume(returning: $0) // CONTINUATION-IN-NESTED-EXPRESSION-NEXT: }) // CONTINUATION-IN-NESTED-EXPRESSION-NEXT: } // CONTINUATION-IN-NESTED-EXPRESSION-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION %s func testThrowingContinuation(completionHandler: @escaping (Int?, Error?) -> Void) { withoutAsyncAlternativeThrowing { (theValue, theError) in if let theError = theError { completionHandler(nil, theError) } else { completionHandler(theValue!, nil) } } } // THROWING-CONTINUATION: func testThrowingContinuation() async throws -> Int { // THROWING-CONTINUATION-NEXT: return try await withCheckedThrowingContinuation { continuation in // THROWING-CONTINUATION-NEXT: withoutAsyncAlternativeThrowing { (theValue, theError) in // THROWING-CONTINUATION-NEXT: if let theError = theError { // THROWING-CONTINUATION-NEXT: continuation.resume(throwing: theError) // THROWING-CONTINUATION-NEXT: } else { // THROWING-CONTINUATION-NEXT: continuation.resume(returning: theValue!) // THROWING-CONTINUATION-NEXT: } // THROWING-CONTINUATION-NEXT: } // THROWING-CONTINUATION-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT %s func testThrowingContinuationRelayingErrorAndResult(completionHandler: @escaping (Int?, Error?) -> Void) { withoutAsyncAlternativeThrowing { (theValue, theError) in completionHandler(theValue, theError) } } // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT: func testThrowingContinuationRelayingErrorAndResult() async throws -> Int { // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: return try await withCheckedThrowingContinuation { continuation in // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: withoutAsyncAlternativeThrowing { (theValue, theError) in // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: if let error = theError { // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: continuation.resume(throwing: error) // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: } else { // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: guard let theValue1 = theValue else { // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: fatalError("Expected non-nil result 'theValue1' in the non-error case") // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: continuation.resume(returning: theValue1) // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-RESULT-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT %s func testThrowingContinuationRelayingErrorAndComplexResult(completionHandler: @escaping (Int?, Error?) -> Void) { withoutAsyncAlternativeThrowing { (theValue, theError) in completionHandler(theValue.map({ $0 + 1 }), theError) } } // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT: func testThrowingContinuationRelayingErrorAndComplexResult() async throws -> Int { // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: return try await withCheckedThrowingContinuation { continuation in // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: withoutAsyncAlternativeThrowing { (theValue, theError) in // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: if let error = theError { // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: continuation.resume(throwing: error) // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: } else { // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: guard let result = theValue.map({ $0 + 1 }) else { // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: fatalError("Expected non-nil result in the non-error case") // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: continuation.resume(returning: result) // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS %s func testThrowingContinuationRelayingErrorAndTwoComplexResults(completionHandler: @escaping (Int?, Int?, Error?) -> Void) { withoutAsyncAlternativeThrowing { (theValue, theError) in completionHandler(theValue.map({ $0 + 1 }), theValue.map({ $0 + 2 }), theError) } } // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS: func testThrowingContinuationRelayingErrorAndTwoComplexResults() async throws -> (Int, Int) { // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: return try await withCheckedThrowingContinuation { continuation in // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: withoutAsyncAlternativeThrowing { (theValue, theError) in // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: if let error = theError { // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: continuation.resume(throwing: error) // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: } else { // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: guard let result0 = theValue.map({ $0 + 1 }) else { // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: fatalError("Expected non-nil result 'result0' in the non-error case") // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: guard let result1 = theValue.map({ $0 + 2 }) else { // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: fatalError("Expected non-nil result 'result1' in the non-error case") // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: continuation.resume(returning: (result0, result1)) // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-TWO-COMPLEX-RESULTS-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE %s func testThrowingContinuationRelayingErrorAndComplexResultWithTrailingClosure(completionHandler: @escaping (Int?, Error?) -> Void) { withoutAsyncAlternativeThrowing { (theValue, theError) in completionHandler(theValue.map { $0 + 1 }, theError) } } // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE: func testThrowingContinuationRelayingErrorAndComplexResultWithTrailingClosure() async throws -> Int { // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: return try await withCheckedThrowingContinuation { continuation in // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: withoutAsyncAlternativeThrowing { (theValue, theError) in // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: if let error = theError { // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: continuation.resume(throwing: error) // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: } else { // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: guard let result = (theValue.map { $0 + 1 }) else { // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: fatalError("Expected non-nil result in the non-error case") // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: continuation.resume(returning: result) // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: } // THROWING-CONTINUATION-RELAYING-ERROR-AND-COMPLEX-RESULT-WITH-TRAILING-CLOSURE-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MULTIPLE-TRAILING-CLOSURES %s func testThrowingContinuationRelayingErrorAndComplexResultWithMultipleTrailingClosures(completionHandler: @escaping (Int?, Error?) -> Void) { withoutAsyncAlternativeThrowing { theValue, theError in completionHandler(lottaClosures {} y: {}, theError) } } // MULTIPLE-TRAILING-CLOSURES: func testThrowingContinuationRelayingErrorAndComplexResultWithMultipleTrailingClosures() async throws -> Int { // MULTIPLE-TRAILING-CLOSURES-NEXT: return try await withCheckedThrowingContinuation { continuation in // MULTIPLE-TRAILING-CLOSURES-NEXT: withoutAsyncAlternativeThrowing { theValue, theError in // MULTIPLE-TRAILING-CLOSURES-NEXT: if let error = theError { // MULTIPLE-TRAILING-CLOSURES-NEXT: continuation.resume(throwing: error) // MULTIPLE-TRAILING-CLOSURES-NEXT: } else { // MULTIPLE-TRAILING-CLOSURES-NEXT: guard let result = (lottaClosures {} y: {}) else { // MULTIPLE-TRAILING-CLOSURES-NEXT: fatalError("Expected non-nil result in the non-error case") // MULTIPLE-TRAILING-CLOSURES-NEXT: } // MULTIPLE-TRAILING-CLOSURES-NEXT: continuation.resume(returning: result) // MULTIPLE-TRAILING-CLOSURES-NEXT: } // MULTIPLE-TRAILING-CLOSURES-NEXT: } // MULTIPLE-TRAILING-CLOSURES-NEXT: } // MULTIPLE-TRAILING-CLOSURES-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT %s func testAlwaysReturnBothResultAndCompletionHandler(completionHandler: @escaping (Int?, Error?) -> Void) { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { theValue in completionHandler(theValue, MyError()) } } // THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT: func testAlwaysReturnBothResultAndCompletionHandler() async throws -> Int { // THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: return try await withCheckedThrowingContinuation { continuation in // THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { theValue in // THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: continuation.resume(throwing: MyError()) // THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: } // THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: } // THROWING-CONTINUATION-ALWAYS-RETURNING-ERROR-AND-RESULT-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE %s func testAmbiguousCallToCompletionHandlerWithAlwaysNilVariable(completionHandler: @escaping (Int?, Error?) -> Void) { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { theValue in let error: Error? = nil completionHandler(theValue, error) } } // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE: func testAmbiguousCallToCompletionHandlerWithAlwaysNilVariable() async throws -> Int { // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: return try await withCheckedThrowingContinuation { continuation in // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { theValue in // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: let error: Error? = nil // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: if let error = error { // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: continuation.resume(throwing: error) // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: } else { // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: continuation.resume(returning: theValue) // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: } // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: } // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: } // AMBIGUOUS-CALL-WITH-ALWAYS-NIL-VARIABLE-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=PREVIOUS-COMPLETION-HANDLER-CALL %s func testPreviousCompletionHandlerCall(completionHandler: @escaping (Int) -> Void) { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { print($0) } withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { completionHandler($0) } } // PREVIOUS-COMPLETION-HANDLER-CALL: func testPreviousCompletionHandlerCall() async -> Int { // PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { // PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: print($0) // PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: } // PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: return await withCheckedContinuation { continuation in // PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { // PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: continuation.resume(returning: $0) // PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: } // PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: } // PREVIOUS-COMPLETION-HANDLER-CALL-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=PREVIOUS-ASYNC-CALL %s func testPreviousAsyncCall(completionHandler: @escaping (Int) -> Void) { withAsyncAlternative { message in print(message) } withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { completionHandler($0) } } // PREVIOUS-ASYNC-CALL: func testPreviousAsyncCall() async -> Int { // PREVIOUS-ASYNC-CALL-NEXT: let message = await withAsyncAlternative() // PREVIOUS-ASYNC-CALL-NEXT: print(message) // PREVIOUS-ASYNC-CALL-NEXT: return await withCheckedContinuation { continuation in // PREVIOUS-ASYNC-CALL-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { // PREVIOUS-ASYNC-CALL-NEXT: continuation.resume(returning: $0) // PREVIOUS-ASYNC-CALL-NEXT: } // PREVIOUS-ASYNC-CALL-NEXT: } // PREVIOUS-ASYNC-CALL-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=IN-IF-ELSE %s func testInIfElse(completionHandler: @escaping (Int) -> Void) { if true { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { completionHandler($0) } } else { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { completionHandler($0) } } } // IN-IF-ELSE: func testInIfElse() async -> Int { // IN-IF-ELSE-NEXT: if true { // IN-IF-ELSE-NEXT: return await withCheckedContinuation { continuation in // IN-IF-ELSE-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { // IN-IF-ELSE-NEXT: continuation.resume(returning: $0) // IN-IF-ELSE-NEXT: } // IN-IF-ELSE-NEXT: } // IN-IF-ELSE-NEXT: } else { // IN-IF-ELSE-NEXT: return await withCheckedContinuation { continuation in // IN-IF-ELSE-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { // IN-IF-ELSE-NEXT: continuation.resume(returning: $0) // IN-IF-ELSE-NEXT: } // IN-IF-ELSE-NEXT: } // IN-IF-ELSE-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=ASYNC-AFTER-CONTINUATION %s func testAsyncAfterContinuation(completionHandler: @escaping (Int) -> Void) { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { completionHandler($0) } withAsyncAlternative { print($0) } } // ASYNC-AFTER-CONTINUATION: func testAsyncAfterContinuation() async -> Int { // ASYNC-AFTER-CONTINUATION-NEXT: return await withCheckedContinuation { continuation in // ASYNC-AFTER-CONTINUATION-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { // ASYNC-AFTER-CONTINUATION-NEXT: continuation.resume(returning: $0) // ASYNC-AFTER-CONTINUATION-NEXT: } // ASYNC-AFTER-CONTINUATION-NEXT: withAsyncAlternative { // ASYNC-AFTER-CONTINUATION-NEXT: print($0) // ASYNC-AFTER-CONTINUATION-NEXT: } // ASYNC-AFTER-CONTINUATION-NEXT: } // ASYNC-AFTER-CONTINUATION-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC %s func testWithoutAsyncAlternativeNestedInWithoutAsyncAlternative(completionHandler: @escaping (Int) -> Void) { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { firstResult in withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { secondResult in completionHandler(firstResult + secondResult) } } } // WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC: func testWithoutAsyncAlternativeNestedInWithoutAsyncAlternative() async -> Int { // WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: return await withCheckedContinuation { continuation in // WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { firstResult in // WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { secondResult in // WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: continuation.resume(returning: firstResult + secondResult) // WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: } // WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: } // WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: } // WITHOUT-ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=WITHOUT-ASYNC-NESTED-IN-ASYNC %s func testWithoutAsyncAlternativeNestedInAsyncAlternative(completionHandler: @escaping (Int) -> Void) { withAsyncAlternative { firstResult in withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { secondResult in completionHandler(firstResult + secondResult) } } } // WITHOUT-ASYNC-NESTED-IN-ASYNC: func testWithoutAsyncAlternativeNestedInAsyncAlternative() async -> Int { // WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: let firstResult = await withAsyncAlternative() // WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: return await withCheckedContinuation { continuation in // WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { secondResult in // WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: continuation.resume(returning: firstResult + secondResult) // WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: } // WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: } // WITHOUT-ASYNC-NESTED-IN-ASYNC-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=ASYNC-NESTED-IN-WITHOUT-ASYNC %s func testAsyncAlternativeNestedInWithoutAsyncAlternative(completionHandler: @escaping (Int) -> Void) { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { firstResult in withAsyncAlternative { secondResult in completionHandler(firstResult + secondResult) } } } // ASYNC-NESTED-IN-WITHOUT-ASYNC: func testAsyncAlternativeNestedInWithoutAsyncAlternative() async -> Int { // ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: return await withCheckedContinuation { continuation in // ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { firstResult in // ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: withAsyncAlternative { secondResult in // ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: continuation.resume(returning: firstResult + secondResult) // ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: } // ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: } // ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: } // ASYNC-NESTED-IN-WITHOUT-ASYNC-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=SHADOW-CONT-NAME %s func testShadowContName(completionHandler: @escaping (Int) -> Void) { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { continuation in completionHandler(continuation) } } // SHADOW-CONT-NAME: func testShadowContName() async -> Int { // SHADOW-CONT-NAME-NEXT: return await withCheckedContinuation { continuation in // SHADOW-CONT-NAME-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { continuation1 in // SHADOW-CONT-NAME-NEXT: continuation.resume(returning: continuation1) // SHADOW-CONT-NAME-NEXT: } // SHADOW-CONT-NAME-NEXT: } // SHADOW-CONT-NAME-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=SHADOW-CONT-NAME-2 %s func testShadowContName2(completionHandler: @escaping (Int) -> Void) { let continuation = 3 withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { result in completionHandler(result + continuation) } } // SHADOW-CONT-NAME-2: func testShadowContName2() async -> Int { // SHADOW-CONT-NAME-2-NEXT: let continuation = 3 // SHADOW-CONT-NAME-2-NEXT: return await withCheckedContinuation { continuation1 in // SHADOW-CONT-NAME-2-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { result in // SHADOW-CONT-NAME-2-NEXT: continuation1.resume(returning: result + continuation) // SHADOW-CONT-NAME-2-NEXT: } // SHADOW-CONT-NAME-2-NEXT: } // SHADOW-CONT-NAME-2-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=VOID-RETURN %s func testVoidReturnValue(completionHandler: @escaping () -> Void) { asyncVoidWithoutAlternative { completionHandler() } } // VOID-RETURN: func testVoidReturnValue() async { // VOID-RETURN-NEXT: return await withCheckedContinuation { continuation in // VOID-RETURN-NEXT: asyncVoidWithoutAlternative { // VOID-RETURN-NEXT: continuation.resume(returning: ()) // VOID-RETURN-NEXT: } // VOID-RETURN-NEXT: } // VOID-RETURN-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=SIMPLE-RESULT %s func testSimpleResult(completionHandler: @escaping (Result) -> Void) { resultWithoutAlternative { result in completionHandler(result) } } // SIMPLE-RESULT: func testSimpleResult() async throws -> Int { // SIMPLE-RESULT-NEXT: return try await withCheckedThrowingContinuation { continuation in // SIMPLE-RESULT-NEXT: resultWithoutAlternative { result in // SIMPLE-RESULT-NEXT: continuation.resume(with: result) // SIMPLE-RESULT-NEXT: } // SIMPLE-RESULT-NEXT: } // SIMPLE-RESULT-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=RESULT-FROM-VALUE-AND-ERROR %s func testResultFromValueAndError(completionHandler: @escaping (Result) -> Void) { withoutAsyncAlternativeThrowing { (value, error) in if let error = error { completionHandler(.failure(error)) } else { completionHandler(.success(value!)) } } } // RESULT-FROM-VALUE-AND-ERROR: func testResultFromValueAndError() async throws -> Int { // RESULT-FROM-VALUE-AND-ERROR-NEXT: return try await withCheckedThrowingContinuation { continuation in // RESULT-FROM-VALUE-AND-ERROR-NEXT: withoutAsyncAlternativeThrowing { (value, error) in // RESULT-FROM-VALUE-AND-ERROR-NEXT: if let error = error { // RESULT-FROM-VALUE-AND-ERROR-NEXT: continuation.resume(with: .failure(error)) // RESULT-FROM-VALUE-AND-ERROR-NEXT: } else { // RESULT-FROM-VALUE-AND-ERROR-NEXT: continuation.resume(with: .success(value!)) // RESULT-FROM-VALUE-AND-ERROR-NEXT: } // RESULT-FROM-VALUE-AND-ERROR-NEXT: } // RESULT-FROM-VALUE-AND-ERROR-NEXT: } // RESULT-FROM-VALUE-AND-ERROR-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MULTIPLE-RETURN-VALUES-AND-ERROR %s func testMultipleReturnValuesAndError(completion: @escaping (Int?, String?, Error?) -> Void) { withoutAsyncAlternativeThrowingWithMultipleResults { (first, second, error) in completion(first, second, error) } } // MULTIPLE-RETURN-VALUES-AND-ERROR: func testMultipleReturnValuesAndError() async throws -> (Int, String) { // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: return try await withCheckedThrowingContinuation { continuation in // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: withoutAsyncAlternativeThrowingWithMultipleResults { (first, second, error) in // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: if let error = error { // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: continuation.resume(throwing: error) // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: } else { // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: guard let first1 = first else { // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: fatalError("Expected non-nil result 'first1' in the non-error case") // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: } // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: guard let second1 = second else { // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: fatalError("Expected non-nil result 'second1' in the non-error case") // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: } // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: continuation.resume(returning: (first1, second1)) // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: } // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: } // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: } // MULTIPLE-RETURN-VALUES-AND-ERROR-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR %s func testReturnNonOptionalValuesForResultAndError(completion: @escaping (Int?, Error?) -> Void) { withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { result in completion(1, MyError()) } } // NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR: func testReturnNonOptionalValuesForResultAndError() async throws -> Int { // NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: return try await withCheckedThrowingContinuation { continuation in // NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: withoutAsyncAlternativeBecauseOfMismatchedCompletionHandlerName { result in // NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: continuation.resume(throwing: MyError()) // NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: } // NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: } // NON-OPTIONAL-VALUE-FOR-RESULT-AND-ERROR-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT %s func testMixedOptionalAnNonOptionalResults(completion: @escaping (Int?, String?, Error?) -> Void) { withoutAsyncAlternativeThrowing { (theResult, error) in completion(theResult, "hi", nil) } } // MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT: func testMixedOptionalAnNonOptionalResults() async throws -> (Int, String) { // MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: return try await withCheckedThrowingContinuation { continuation in // MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: withoutAsyncAlternativeThrowing { (theResult, error) in // MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: guard let theResult1 = theResult else { // MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: fatalError("Expected non-nil result 'theResult1' in the non-error case") // MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: } // MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: continuation.resume(returning: (theResult1, "hi")) // MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: } // MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: } // MIXED-OPTIONAL-AND-NON-OPTIONAL-RESULT-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL %s func testUseOptionalResultValueAfterCompletionHandlerCall(completion: @escaping (Int?, String?, Error?) -> Void) { withoutAsyncAlternativeThrowing { (theResult, error) in completion(theResult, "hi", nil) print(theResult.map { $0 + 1 } as Any) } } // USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL: func testUseOptionalResultValueAfterCompletionHandlerCall() async throws -> (Int, String) { // USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: return try await withCheckedThrowingContinuation { continuation in // USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: withoutAsyncAlternativeThrowing { (theResult, error) in // USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: guard let theResult1 = theResult else { // USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: fatalError("Expected non-nil result 'theResult1' in the non-error case") // USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: } // USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: continuation.resume(returning: (theResult1, "hi")) // USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: print(theResult.map { $0 + 1 } as Any) // USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: } // USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: } // USE-OPTIONAL-RESULT-AFTER-COMPLETION-HANDLER-CALL-NEXT: } // We shouldn't need to unwrap `theResult` twice here, but the example is silly and I don't care too much. // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=PASS-SAME-RESULT-TWICE %s func testPassSameResultTwice(completion: @escaping (Int?, Int?, Error?) -> Void) { withoutAsyncAlternativeThrowing { (theResult, error) in completion(theResult, theResult, nil) } } // PASS-SAME-RESULT-TWICE: func testPassSameResultTwice() async throws -> (Int, Int) { // PASS-SAME-RESULT-TWICE-NEXT: return try await withCheckedThrowingContinuation { continuation in // PASS-SAME-RESULT-TWICE-NEXT: withoutAsyncAlternativeThrowing { (theResult, error) in // PASS-SAME-RESULT-TWICE-NEXT: guard let theResult1 = theResult else { // PASS-SAME-RESULT-TWICE-NEXT: fatalError("Expected non-nil result 'theResult1' in the non-error case") // PASS-SAME-RESULT-TWICE-NEXT: } // PASS-SAME-RESULT-TWICE-NEXT: guard let theResult2 = theResult else { // PASS-SAME-RESULT-TWICE-NEXT: fatalError("Expected non-nil result 'theResult2' in the non-error case") // PASS-SAME-RESULT-TWICE-NEXT: } // PASS-SAME-RESULT-TWICE-NEXT: continuation.resume(returning: (theResult1, theResult2)) // PASS-SAME-RESULT-TWICE-NEXT: } // PASS-SAME-RESULT-TWICE-NEXT: } // PASS-SAME-RESULT-TWICE-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL %s func testUseResultAfterAmbiguousCompletionHandlerCall(completion: @escaping (Int?, Error?) -> Void) { withoutAsyncAlternativeThrowing { (theResult, error) in completion(theResult, error) print(theResult as Any) } } // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL: func testUseResultAfterAmbiguousCompletionHandlerCall() async throws -> Int { // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: return try await withCheckedThrowingContinuation { continuation in // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: withoutAsyncAlternativeThrowing { (theResult, error) in // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: if let error = error { // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: continuation.resume(throwing: error) // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: } else { // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: guard let theResult1 = theResult else { // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: fatalError("Expected non-nil result 'theResult1' in the non-error case") // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: } // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: continuation.resume(returning: theResult1) // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: } // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: print(theResult as Any) // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: } // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: } // USE-RESULT-AFTER-AMBIGUOUS-HANDLER-CALL-NEXT: } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=TWO-COMPLEITON-HANDLER-CALLS %s func testTwoCompletionHandlerCalls(completion: @escaping (Int?, Error?) -> Void) { withoutAsyncAlternativeThrowing { (theResult, error) in completion(theResult, error) completion(theResult, error) } } // TWO-COMPLEITON-HANDLER-CALLS: func testTwoCompletionHandlerCalls() async throws -> Int { // TWO-COMPLEITON-HANDLER-CALLS-NEXT: return try await withCheckedThrowingContinuation { continuation in // TWO-COMPLEITON-HANDLER-CALLS-NEXT: withoutAsyncAlternativeThrowing { (theResult, error) in // TWO-COMPLEITON-HANDLER-CALLS-NEXT: if let error = error { // TWO-COMPLEITON-HANDLER-CALLS-NEXT: continuation.resume(throwing: error) // TWO-COMPLEITON-HANDLER-CALLS-NEXT: } else { // TWO-COMPLEITON-HANDLER-CALLS-NEXT: guard let theResult1 = theResult else { // TWO-COMPLEITON-HANDLER-CALLS-NEXT: fatalError("Expected non-nil result 'theResult1' in the non-error case") // TWO-COMPLEITON-HANDLER-CALLS-NEXT: } // TWO-COMPLEITON-HANDLER-CALLS-NEXT: continuation.resume(returning: theResult1) // TWO-COMPLEITON-HANDLER-CALLS-NEXT: } // TWO-COMPLEITON-HANDLER-CALLS-NEXT: if let error = error { // TWO-COMPLEITON-HANDLER-CALLS-NEXT: continuation.resume(throwing: error) // TWO-COMPLEITON-HANDLER-CALLS-NEXT: } else { // TWO-COMPLEITON-HANDLER-CALLS-NEXT: guard let theResult2 = theResult else { // TWO-COMPLEITON-HANDLER-CALLS-NEXT: fatalError("Expected non-nil result 'theResult2' in the non-error case") // TWO-COMPLEITON-HANDLER-CALLS-NEXT: } // TWO-COMPLEITON-HANDLER-CALLS-NEXT: continuation.resume(returning: theResult2) // TWO-COMPLEITON-HANDLER-CALLS-NEXT: } // TWO-COMPLEITON-HANDLER-CALLS-NEXT: } // TWO-COMPLEITON-HANDLER-CALLS-NEXT: } // TWO-COMPLEITON-HANDLER-CALLS-NEXT: } // Reduced version of https://twitter.com/peterfriese/status/1397835146133479428 class DataTask { let completionHandler: (String?, Error?) -> Void init(completionHandler: @escaping (String?, Error?) -> Void) { self.completionHandler = completionHandler } func resume() { completionHandler("mock result", nil) } } class URLSession { static let shared = URLSession() func dataTask(completionHandler: @escaping (String?, Error?) -> Void) -> DataTask { return DataTask(completionHandler: completionHandler) } } func processURLResult(_ data: String) throws -> Int { return data.count } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=URL-SESSION %s func testDataTask(_ completion: @escaping (Int?) -> Void) { let dataTask = URLSession.shared.dataTask { (data, error) in guard let data = data else { return // Yes, there is a bug about not calling completion here, but that's copied from the Twitter link above } do { let processed = try processURLResult(data) completion(processed) } catch { completion(nil) } } dataTask.resume() } // URL-SESSION: func testDataTask() async -> Int? { // URL-SESSION-NEXT: return await withCheckedContinuation { continuation in // URL-SESSION-NEXT: let dataTask1 = URLSession.shared.dataTask { (data, error) in // URL-SESSION-NEXT: guard let data1 = data else { // URL-SESSION-NEXT: return // Yes, there is a bug about not calling completion here, but that's copied from the Twitter link above // URL-SESSION-NEXT: } // URL-SESSION-NEXT: do { // URL-SESSION-NEXT: let processed = try processURLResult(data1) // URL-SESSION-NEXT: continuation.resume(returning: processed) // URL-SESSION-NEXT: } catch { // URL-SESSION-NEXT: continuation.resume(returning: nil) // URL-SESSION-NEXT: } // URL-SESSION-NEXT: } // URL-SESSION-NEXT: dataTask1.resume() // URL-SESSION-NEXT: } // URL-SESSION-NEXT: } // Reduced version of rdar://79304583 class DispatchQueue { init() {} func async(execute work: @escaping @convention(block) () -> Void) { work() } } func syncComputation() -> Int { return 42 } // RUN: %refactor-check-compiles -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=DISPATCH %s func testDispatch(_ completionHandler: @escaping (Int) -> Void) { let queue = DispatchQueue() queue.async { completionHandler(syncComputation()) } } // DISPATCH: func testDispatch() async -> Int { // DISPATCH-NEXT: let queue = DispatchQueue() // DISPATCH-NEXT: return await withCheckedContinuation { continuation in // DISPATCH-NEXT: queue.async { // DISPATCH-NEXT: continuation.resume(returning: syncComputation()) // DISPATCH-NEXT: } // DISPATCH-NEXT: } // DISPATCH-NEXT: }