mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Better handle non-refutable patterns in async transform
Keep track of patterns that bind multiple vars and print them out when converting an async call. If the parameter being bound isn't referenced elsewhere, we'll print the pattern inline as e.g: ``` let ((x, y), z) = await foo() ``` Otherwise, if the parameter is referenced elsewhere in the block we'll print the pattern out of line, such as: ``` let (res, z) = await foo() let (x, y) = res ``` In addition, make sure to print var bindings out of line if there's also a let binding, e.g: ``` let x = await foo() var y = x ``` This ensures any mutations to y doesn't affect x. If there's only a single var binding, we'll print it inline. rdar://77802560
This commit is contained in:
@@ -5,6 +5,432 @@ enum E : Error { case e }
|
||||
func anyCompletion(_ completion: (Any?, Error?) -> Void) {}
|
||||
func anyResultCompletion(_ completion: (Result<Any?, Error>) -> Void) {}
|
||||
|
||||
func stringTupleParam(_ completion: ((String, String)?, Error?) -> Void) {}
|
||||
func stringTupleParam() async throws -> (String, String) {}
|
||||
|
||||
func stringTupleResult(_ completion: (Result<(String, String), Error>) -> Void) {}
|
||||
func stringTupleResult() async throws -> (String, String) {}
|
||||
|
||||
func mixedTupleResult(_ completion: (Result<((Int, Float), String), Error>) -> Void) {}
|
||||
func mixedTupleResult() async throws -> ((Int, Float), String) {}
|
||||
|
||||
func multipleTupleParam(_ completion: ((String, String)?, (Int, Int)?, Error?) -> Void) {}
|
||||
func multipleTupleParam() async throws -> ((String, String), (Int, Int)) {}
|
||||
|
||||
func testPatterns() async throws {
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=INLINE %s
|
||||
stringTupleParam { strs, err in
|
||||
guard let (str1, str2) = strs else { return }
|
||||
print(str1, str2)
|
||||
}
|
||||
|
||||
// INLINE: let (str1, str2) = try await stringTupleParam()
|
||||
// INLINE-NEXT: print(str1, str2)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=INLINE-VAR %s
|
||||
stringTupleParam { strs, err in
|
||||
guard var (str1, str2) = strs else { return }
|
||||
print(str1, str2)
|
||||
}
|
||||
|
||||
// INLINE-VAR: var (str1, str2) = try await stringTupleParam()
|
||||
// INLINE-VAR-NEXT: print(str1, str2)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=INLINE-BLANK %s
|
||||
stringTupleParam { strs, err in
|
||||
guard var (_, str2) = strs else { return }
|
||||
print(str2)
|
||||
}
|
||||
|
||||
// INLINE-BLANK: var (_, str2) = try await stringTupleParam()
|
||||
// INLINE-BLANK-NEXT: print(str2)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=INLINE-TYPED %s
|
||||
stringTupleParam { strs, err in
|
||||
guard let (str1, str2): (String, String) = strs else { return }
|
||||
print(str1, str2)
|
||||
}
|
||||
|
||||
// INLINE-TYPED: let (str1, str2) = try await stringTupleParam()
|
||||
// INLINE-TYPED-NEXT: print(str1, str2)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=INLINE-CASE %s
|
||||
stringTupleParam { strs, err in
|
||||
guard case (let str1, var str2)? = strs else { return }
|
||||
print(str1, str2)
|
||||
}
|
||||
|
||||
// INLINE-CASE: var (str1, str2) = try await stringTupleParam()
|
||||
// INLINE-CASE-NEXT: print(str1, str2)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=INLINE-CASE-TYPED %s
|
||||
stringTupleParam { strs, err in
|
||||
guard case let (str1, str2)?: (String, String)? = strs else { return }
|
||||
print(str1, str2)
|
||||
}
|
||||
|
||||
// INLINE-CASE-TYPED: let (str1, str2) = try await stringTupleParam()
|
||||
// INLINE-CASE-TYPED-NEXT: print(str1, str2)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=OUT-OF-LINE %s
|
||||
stringTupleParam { strs, err in
|
||||
guard let (str1, str2) = strs else { return }
|
||||
print(str1, str2, strs!)
|
||||
}
|
||||
|
||||
// OUT-OF-LINE: let strs = try await stringTupleParam()
|
||||
// OUT-OF-LINE-NEXT: let (str1, str2) = strs
|
||||
// OUT-OF-LINE-NEXT: print(str1, str2, strs)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=OUT-OF-LINE-VAR %s
|
||||
stringTupleParam { strs, err in
|
||||
guard var (str1, _) = strs else { return }
|
||||
str1 = ""
|
||||
print(str1, {strs!})
|
||||
}
|
||||
|
||||
// OUT-OF-LINE-VAR: let strs = try await stringTupleParam()
|
||||
// OUT-OF-LINE-VAR-NEXT: var (str1, _) = strs
|
||||
// OUT-OF-LINE-VAR-NEXT: str1 = ""
|
||||
// OUT-OF-LINE-VAR-NEXT: print(str1, {strs})
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=OUT-OF-LINE-CASE %s
|
||||
stringTupleParam { strs, err in
|
||||
guard case (let str1, var str2)? = strs else { return }
|
||||
print(str1, str2, strs!)
|
||||
}
|
||||
|
||||
// OUT-OF-LINE-CASE: let strs = try await stringTupleParam()
|
||||
// OUT-OF-LINE-CASE-NEXT: var (str1, str2) = strs
|
||||
// OUT-OF-LINE-CASE-NEXT: print(str1, str2, strs)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=FALLBACK %s
|
||||
stringTupleParam { strs, err in
|
||||
guard let (str1, str2) = strs, str1 == "hi" else { fatalError() }
|
||||
print(str1, str2, err)
|
||||
}
|
||||
|
||||
// FALLBACK: var strs: (String, String)? = nil
|
||||
// FALLBACK-NEXT: var err: Error? = nil
|
||||
// FALLBACK-NEXT: do {
|
||||
// FALLBACK-NEXT: strs = try await stringTupleParam()
|
||||
// FALLBACK-NEXT: } catch {
|
||||
// FALLBACK-NEXT: err = error
|
||||
// FALLBACK-NEXT: }
|
||||
// FALLBACK-EMPTY:
|
||||
// FALLBACK-NEXT: guard let (str1, str2) = strs, str1 == "hi" else { fatalError() }
|
||||
// FALLBACK-NEXT: print(str1, str2, err)
|
||||
|
||||
// FIXME: Arguably we should be able to classify everything after the guard as
|
||||
// a success path and avoid the fallback in this case.
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=FALLBACK2 %s
|
||||
stringTupleParam { strs, err in
|
||||
guard let (str1, str2) = strs else { fatalError() }
|
||||
print(str1, str2)
|
||||
if .random(), err == nil {
|
||||
print("yay")
|
||||
} else {
|
||||
print("nay")
|
||||
}
|
||||
}
|
||||
|
||||
// FALLBACK2: var strs: (String, String)? = nil
|
||||
// FALLBACK2-NEXT: var err: Error? = nil
|
||||
// FALLBACK2-NEXT: do {
|
||||
// FALLBACK2-NEXT: strs = try await stringTupleParam()
|
||||
// FALLBACK2-NEXT: } catch {
|
||||
// FALLBACK2-NEXT: err = error
|
||||
// FALLBACK2-NEXT: }
|
||||
// FALLBACK2-EMPTY:
|
||||
// FALLBACK2-NEXT: guard let (str1, str2) = strs else { fatalError() }
|
||||
// FALLBACK2-NEXT: print(str1, str2)
|
||||
// FALLBACK2-NEXT: if .random(), err == nil {
|
||||
// FALLBACK2-NEXT: print("yay")
|
||||
// FALLBACK2-NEXT: } else {
|
||||
// FALLBACK2-NEXT: print("nay")
|
||||
// FALLBACK2-NEXT: }
|
||||
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED-BINDINGS %s
|
||||
stringTupleParam { strs, err in
|
||||
guard let x = strs else { return }
|
||||
guard var (str1, str2) = strs else { return }
|
||||
guard var y = strs else { return }
|
||||
guard let z = strs else { return }
|
||||
y = ("hello", "there")
|
||||
print(x, y, z, str1, str2)
|
||||
}
|
||||
|
||||
// Make sure that we
|
||||
// 1. Coalesce the z binding, as it is a let
|
||||
// 2. Preserve the y binding, as it is a var
|
||||
// 3. Print the multi-var binding out of line
|
||||
//
|
||||
// MIXED-BINDINGS: let x = try await stringTupleParam()
|
||||
// MIXED-BINDINGS-NEXT: var (str1, str2) = x
|
||||
// MIXED-BINDINGS-NEXT: var y = x
|
||||
// MIXED-BINDINGS-NEXT: y = ("hello", "there")
|
||||
// MIXED-BINDINGS-NEXT: print(x, y, x, str1, str2)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED-BINDINGS2 %s
|
||||
stringTupleParam { strs, err in
|
||||
guard var (str1, str2) = strs else { return }
|
||||
str1 = "hi"
|
||||
guard var x = strs else { return }
|
||||
x = ("hello", "there")
|
||||
print(x, str1, str2)
|
||||
}
|
||||
|
||||
// MIXED-BINDINGS2: var x = try await stringTupleParam()
|
||||
// MIXED-BINDINGS2-NEXT: var (str1, str2) = x
|
||||
// MIXED-BINDINGS2-NEXT: str1 = "hi"
|
||||
// MIXED-BINDINGS2-NEXT: x = ("hello", "there")
|
||||
// MIXED-BINDINGS2-NEXT: print(x, str1, str2)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED-BINDINGS3 %s
|
||||
stringTupleParam { strs, err in
|
||||
guard let (str1, str2) = strs else { return }
|
||||
guard let x = strs else { return }
|
||||
print(x, str1, str2)
|
||||
}
|
||||
|
||||
// MIXED-BINDINGS3: let x = try await stringTupleParam()
|
||||
// MIXED-BINDINGS3-NEXT: let (str1, str2) = x
|
||||
// MIXED-BINDINGS3-NEXT: print(x, str1, str2)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=ALIAS-BINDINGS %s
|
||||
stringTupleParam { strs, err in
|
||||
guard let x = strs else { return }
|
||||
guard let y = strs else { return }
|
||||
guard let z = strs else { return }
|
||||
print(x, y, z)
|
||||
}
|
||||
|
||||
// ALIAS-BINDINGS: let x = try await stringTupleParam()
|
||||
// ALIAS-BINDINGS-NEXT: print(x, x, x)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=ALIAS-BINDINGS2 %s
|
||||
stringTupleParam { strs, err in
|
||||
guard var x = strs else { return }
|
||||
guard var y = strs else { return }
|
||||
guard let z = strs else { return }
|
||||
print(x, y, z)
|
||||
}
|
||||
|
||||
// ALIAS-BINDINGS2: let z = try await stringTupleParam()
|
||||
// ALIAS-BINDINGS2-NEXT: var x = z
|
||||
// ALIAS-BINDINGS2-NEXT: var y = z
|
||||
// ALIAS-BINDINGS2-NEXT: print(x, y, z)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=ALIAS-BINDINGS3 %s
|
||||
stringTupleParam { strs, err in
|
||||
guard var x = strs else { return }
|
||||
guard var y = strs else { return }
|
||||
guard var z = strs else { return }
|
||||
print(x, y, z)
|
||||
}
|
||||
|
||||
// ALIAS-BINDINGS3: var x = try await stringTupleParam()
|
||||
// ALIAS-BINDINGS3-NEXT: var y = x
|
||||
// ALIAS-BINDINGS3-NEXT: var z = x
|
||||
// ALIAS-BINDINGS3-NEXT: print(x, y, z)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=ALIAS-BINDINGS4 %s
|
||||
stringTupleParam { strs, err in
|
||||
guard var x = strs else { return }
|
||||
guard let y = strs else { return }
|
||||
guard let z = strs else { return }
|
||||
print(x, y, z)
|
||||
}
|
||||
|
||||
// ALIAS-BINDINGS4: let y = try await stringTupleParam()
|
||||
// ALIAS-BINDINGS4-NEXT: var x = y
|
||||
// ALIAS-BINDINGS4-NEXT: print(x, y, y)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=ALIAS-BINDINGS5 %s
|
||||
stringTupleParam { strs, err in
|
||||
guard var x = strs else { return }
|
||||
print(x)
|
||||
}
|
||||
|
||||
// ALIAS-BINDINGS5: var x = try await stringTupleParam()
|
||||
// ALIAS-BINDINGS5-NEXT: print(x)
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=STRING-TUPLE-RESULT %s
|
||||
stringTupleResult { res in
|
||||
switch res {
|
||||
case .success((let x, let y)):
|
||||
print(x, y)
|
||||
case .failure:
|
||||
print("oh no")
|
||||
}
|
||||
}
|
||||
// STRING-TUPLE-RESULT: do {
|
||||
// STRING-TUPLE-RESULT-NEXT: let (x, y) = try await stringTupleResult()
|
||||
// STRING-TUPLE-RESULT-NEXT: print(x, y)
|
||||
// STRING-TUPLE-RESULT-NEXT: } catch {
|
||||
// STRING-TUPLE-RESULT-NEXT: print("oh no")
|
||||
// STRING-TUPLE-RESULT-NEXT: }
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED-TUPLE-RESULT %s
|
||||
mixedTupleResult { res in
|
||||
if case .failure(let err) = res {
|
||||
print("oh no")
|
||||
}
|
||||
if case .success(((let x, let y), let z)) = res {
|
||||
print("a", x, y, z)
|
||||
}
|
||||
switch res {
|
||||
case .success(let ((x, _), z)):
|
||||
print("b", x, z)
|
||||
case .failure:
|
||||
print("oh no again")
|
||||
}
|
||||
}
|
||||
|
||||
// MIXED-TUPLE-RESULT: do {
|
||||
// MIXED-TUPLE-RESULT-NEXT: let res = try await mixedTupleResult()
|
||||
// MIXED-TUPLE-RESULT-NEXT: let ((x, y), z) = res
|
||||
// MIXED-TUPLE-RESULT-NEXT: let ((x1, _), z1) = res
|
||||
// MIXED-TUPLE-RESULT-NEXT: print("a", x, y, z)
|
||||
// MIXED-TUPLE-RESULT-NEXT: print("b", x, z)
|
||||
// MIXED-TUPLE-RESULT-NEXT: } catch let err {
|
||||
// MIXED-TUPLE-RESULT-NEXT: print("oh no")
|
||||
// MIXED-TUPLE-RESULT-NEXT: print("oh no again")
|
||||
// MIXED-TUPLE-RESULT-NEXT: }
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED-TUPLE-RESULT2 %s
|
||||
mixedTupleResult { res in
|
||||
switch res {
|
||||
case .success(((let x, let _), let z)):
|
||||
print(x, z)
|
||||
case .failure(let err):
|
||||
print("oh no \(err)")
|
||||
}
|
||||
}
|
||||
|
||||
// MIXED-TUPLE-RESULT2: do {
|
||||
// MIXED-TUPLE-RESULT2-NEXT: let ((x, _), z) = try await mixedTupleResult()
|
||||
// MIXED-TUPLE-RESULT2-NEXT: print(x, z)
|
||||
// MIXED-TUPLE-RESULT2-NEXT: } catch let err {
|
||||
// MIXED-TUPLE-RESULT2-NEXT: print("oh no \(err)")
|
||||
// MIXED-TUPLE-RESULT2-NEXT: }
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MIXED-TUPLE-RESULT3 %s
|
||||
mixedTupleResult { res in
|
||||
if let ((_, y), z) = try? res.get() {
|
||||
print(y, z)
|
||||
} else {
|
||||
print("boo")
|
||||
}
|
||||
}
|
||||
|
||||
// MIXED-TUPLE-RESULT3: do {
|
||||
// MIXED-TUPLE-RESULT3-NEXT: let ((_, y), z) = try await mixedTupleResult()
|
||||
// MIXED-TUPLE-RESULT3-NEXT: print(y, z)
|
||||
// MIXED-TUPLE-RESULT3-NEXT: } catch {
|
||||
// MIXED-TUPLE-RESULT3-NEXT: print("boo")
|
||||
// MIXED-TUPLE-RESULT3-NEXT: }
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MULTIPLE-TUPLE-PARAM %s
|
||||
multipleTupleParam { strs, ints, err in
|
||||
guard let (str1, str2) = strs, let (int1, int2) = ints else {
|
||||
print("ohno")
|
||||
return
|
||||
}
|
||||
print(str1, str2, int1, int2)
|
||||
}
|
||||
// MULTIPLE-TUPLE-PARAM: do {
|
||||
// MULTIPLE-TUPLE-PARAM-NEXT: let ((str1, str2), (int1, int2)) = try await multipleTupleParam()
|
||||
// MULTIPLE-TUPLE-PARAM-NEXT: print(str1, str2, int1, int2)
|
||||
// MULTIPLE-TUPLE-PARAM-NEXT: } catch let err {
|
||||
// MULTIPLE-TUPLE-PARAM-NEXT: print("ohno")
|
||||
// MULTIPLE-TUPLE-PARAM-NEXT: }
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MULTIPLE-TUPLE-PARAM2 %s
|
||||
multipleTupleParam { strs, ints, err in
|
||||
guard let (str1, str2) = strs, var (int1, int2) = ints else {
|
||||
print("ohno")
|
||||
return
|
||||
}
|
||||
print(str1, str2, int1, int2)
|
||||
}
|
||||
// MULTIPLE-TUPLE-PARAM2: do {
|
||||
// MULTIPLE-TUPLE-PARAM2-NEXT: var ((str1, str2), (int1, int2)) = try await multipleTupleParam()
|
||||
// MULTIPLE-TUPLE-PARAM2-NEXT: print(str1, str2, int1, int2)
|
||||
// MULTIPLE-TUPLE-PARAM2-NEXT: } catch let err {
|
||||
// MULTIPLE-TUPLE-PARAM2-NEXT: print("ohno")
|
||||
// MULTIPLE-TUPLE-PARAM2-NEXT: }
|
||||
|
||||
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MULTIPLE-TUPLE-PARAM3 %s
|
||||
multipleTupleParam { strs, ints, err in
|
||||
guard let (str1, str2) = strs, let (int1, int2) = ints else {
|
||||
print("ohno")
|
||||
return
|
||||
}
|
||||
print(strs!)
|
||||
print(str1, str2, int1, int2)
|
||||
}
|
||||
// MULTIPLE-TUPLE-PARAM3: do {
|
||||
// MULTIPLE-TUPLE-PARAM3-NEXT: let (strs, (int1, int2)) = try await multipleTupleParam()
|
||||
// MULTIPLE-TUPLE-PARAM3-NEXT: let (str1, str2) = strs
|
||||
// MULTIPLE-TUPLE-PARAM3-NEXT: print(strs)
|
||||
// MULTIPLE-TUPLE-PARAM3-NEXT: print(str1, str2, int1, int2)
|
||||
// MULTIPLE-TUPLE-PARAM3-NEXT: } catch let err {
|
||||
// MULTIPLE-TUPLE-PARAM3-NEXT: print("ohno")
|
||||
// MULTIPLE-TUPLE-PARAM3-NEXT: }
|
||||
}
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NAME-COLLISION %s
|
||||
func testNameCollision(_ completion: () -> Void) {
|
||||
let a = ""
|
||||
stringTupleParam { strs, err in
|
||||
guard let (a, b) = strs else { return }
|
||||
print(a, b)
|
||||
}
|
||||
let b = ""
|
||||
stringTupleParam { strs, err in
|
||||
guard let (a, b) = strs else { return }
|
||||
print(a, b, strs!)
|
||||
}
|
||||
print(a, b)
|
||||
completion()
|
||||
}
|
||||
|
||||
// TODO: `throws` isn't added to the function declaration
|
||||
// NAME-COLLISION: func testNameCollision() async {
|
||||
// NAME-COLLISION-NEXT: let a = ""
|
||||
// NAME-COLLISION-NEXT: let (a1, b) = try await stringTupleParam()
|
||||
// NAME-COLLISION-NEXT: print(a1, b)
|
||||
// NAME-COLLISION-NEXT: let b1 = ""
|
||||
// NAME-COLLISION-NEXT: let strs = try await stringTupleParam()
|
||||
// NAME-COLLISION-NEXT: let (a2, b2) = strs
|
||||
// NAME-COLLISION-NEXT: print(a2, b2, strs)
|
||||
// NAME-COLLISION-NEXT: print(a, b1)
|
||||
// NAME-COLLISION-NEXT: return
|
||||
// NAME-COLLISION-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=NAME-COLLISION2 %s
|
||||
func testNameCollision2(_ completion: () -> Void) {
|
||||
mixedTupleResult { res in
|
||||
guard case let .success((x, y), z) = res else { return }
|
||||
stringTupleParam { strs, err in
|
||||
if let (x, y) = strs {
|
||||
print("a", x, y)
|
||||
}
|
||||
}
|
||||
print("b", x, y, z)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: `throws` isn't added to the function declaration
|
||||
// NAME-COLLISION2: func testNameCollision2() async {
|
||||
// NAME-COLLISION2-NEXT: let ((x, y), z) = try await mixedTupleResult()
|
||||
// NAME-COLLISION2-NEXT: let (x1, y1) = try await stringTupleParam()
|
||||
// NAME-COLLISION2-NEXT: print("a", x1, y1)
|
||||
// NAME-COLLISION2-NEXT: print("b", x, y, z)
|
||||
// NAME-COLLISION2-NEXT: }
|
||||
|
||||
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):1 | %FileCheck -check-prefix=TEST-UNHANDLED %s
|
||||
anyCompletion { val, err in
|
||||
if let x = val {
|
||||
@@ -118,3 +544,18 @@ anyResultCompletion { res in
|
||||
print("oh no")
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we handle a capture list okay.
|
||||
class C {
|
||||
// RUN: %refactor -convert-to-async -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=CAPTURE %s
|
||||
func foo() {
|
||||
let _ = { [weak self] in
|
||||
print(self!)
|
||||
}
|
||||
}
|
||||
}
|
||||
// CAPTURE: func foo() async {
|
||||
// CAPTURE-NEXT: let _ = { [weak self] in
|
||||
// CAPTURE-NEXT: print(self!)
|
||||
// CAPTURE-NEXT: }
|
||||
// CAPTURE-NEXT: }
|
||||
|
||||
Reference in New Issue
Block a user