mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
536 lines
17 KiB
Swift
536 lines
17 KiB
Swift
// RUN: %empty-directory(%t)
|
|
|
|
// REQUIRES: concurrency
|
|
|
|
func withError() async throws -> String { "" }
|
|
func withError(_ completion: @escaping (String?, Error?) -> Void) { }
|
|
|
|
func notOptional() async throws -> String { "" }
|
|
func notOptional(_ completion: @escaping (String, Error?) -> Void) { }
|
|
|
|
func errorOnly() async throws { }
|
|
func errorOnly(_ completion: @escaping (Error?) -> Void) { }
|
|
|
|
func test(_ str: String) -> Bool { return false }
|
|
|
|
func testParamsSingle() async throws {
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNRELATED %s
|
|
withError { res, err in
|
|
if test("unrelated") {
|
|
print("unrelated")
|
|
} else {
|
|
print("else unrelated")
|
|
}
|
|
}
|
|
// UNRELATED: convert_params_single.swift
|
|
// UNRELATED-NEXT: let res = try await withError()
|
|
// UNRELATED-NEXT: if test("unrelated") {
|
|
// UNRELATED-NEXT: print("unrelated")
|
|
// UNRELATED-NEXT: } else {
|
|
// UNRELATED-NEXT: print("else unrelated")
|
|
// UNRELATED-NEXT: }
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=BOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let bad = err {
|
|
print("got error \(bad)")
|
|
return
|
|
}
|
|
if let str = res {
|
|
print("got result \(str)")
|
|
}
|
|
print("after")
|
|
}
|
|
// BOUND: do {
|
|
// BOUND-NEXT: let str = try await withError()
|
|
// BOUND-NEXT: print("before")
|
|
// BOUND-NEXT: print("got result \(str)")
|
|
// BOUND-NEXT: print("after")
|
|
// BOUND-NEXT: } catch let bad {
|
|
// BOUND-NEXT: print("got error \(bad)")
|
|
// BOUND-NEXT: }
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=BOUND-COMMENT %s
|
|
withError { res, err in // a
|
|
// b
|
|
print("before")
|
|
// c
|
|
if let bad = err { // d
|
|
// e
|
|
print("got error \(bad)")
|
|
// f
|
|
return
|
|
// g
|
|
}
|
|
// h
|
|
if let str = res { // i
|
|
// j
|
|
print("got result \(str)")
|
|
// k
|
|
}
|
|
// l
|
|
print("after")
|
|
// m
|
|
}
|
|
// BOUND-COMMENT: do {
|
|
// BOUND-COMMENT-NEXT: let str = try await withError()
|
|
// BOUND-COMMENT-NEXT: // a
|
|
// BOUND-COMMENT-NEXT: // b
|
|
// BOUND-COMMENT-NEXT: print("before")
|
|
// BOUND-COMMENT-NEXT: // c
|
|
// BOUND-COMMENT-NEXT: // h
|
|
// BOUND-COMMENT-NEXT: // i
|
|
// BOUND-COMMENT-NEXT: // j
|
|
// BOUND-COMMENT-NEXT: print("got result \(str)")
|
|
// BOUND-COMMENT-NEXT: // k
|
|
// BOUND-COMMENT-NEXT: // l
|
|
// BOUND-COMMENT-NEXT: print("after")
|
|
// BOUND-COMMENT-NEXT: // m
|
|
// BOUND-COMMENT-NEXT: } catch let bad {
|
|
// BOUND-COMMENT-NEXT: // d
|
|
// BOUND-COMMENT-NEXT: // e
|
|
// BOUND-COMMENT-NEXT: print("got error \(bad)")
|
|
// BOUND-COMMENT-NEXT: // f
|
|
// BOUND-COMMENT-NEXT: // g
|
|
// BOUND-COMMENT-NEXT: }
|
|
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND-ERR %s
|
|
withError { res, err in
|
|
print("before")
|
|
guard let str = res else {
|
|
print("got error \(err!)")
|
|
return
|
|
}
|
|
print("got result \(str)")
|
|
print("after")
|
|
}
|
|
// UNBOUND-ERR: do {
|
|
// UNBOUND-ERR-NEXT: let str = try await withError()
|
|
// UNBOUND-ERR-NEXT: print("before")
|
|
// UNBOUND-ERR-NEXT: print("got result \(str)")
|
|
// UNBOUND-ERR-NEXT: print("after")
|
|
// UNBOUND-ERR-NEXT: } catch let err {
|
|
// UNBOUND-ERR-NEXT: print("got error \(err)")
|
|
// UNBOUND-ERR-NEXT: }
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=BOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let bad = err {
|
|
print("got error \(bad)")
|
|
} else if let str = res {
|
|
print("got result \(str)")
|
|
}
|
|
print("after")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=BOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let bad = err {
|
|
print("got error \(bad)")
|
|
return
|
|
}
|
|
if let str = res {
|
|
print("got result \(str)")
|
|
}
|
|
print("after")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND-RES %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let bad = err {
|
|
print("got error \(bad)")
|
|
return
|
|
}
|
|
print("got result \(res!)")
|
|
print("after")
|
|
}
|
|
// UNBOUND-RES: do {
|
|
// UNBOUND-RES-NEXT: let res = try await withError()
|
|
// UNBOUND-RES-NEXT: print("before")
|
|
// UNBOUND-RES-NEXT: print("got result \(res)")
|
|
// UNBOUND-RES-NEXT: print("after")
|
|
// UNBOUND-RES-NEXT: } catch let bad {
|
|
// UNBOUND-RES-NEXT: print("got error \(bad)")
|
|
// UNBOUND-RES-NEXT: }
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND-ERR %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let str = res {
|
|
print("got result \(str)")
|
|
print("after")
|
|
return
|
|
}
|
|
print("got error \(err!)")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND-RES %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let bad = err {
|
|
print("got error \(bad)")
|
|
} else {
|
|
print("got result \(res!)")
|
|
}
|
|
print("after")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND-ERR %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let str = res {
|
|
print("got result \(str)")
|
|
} else {
|
|
print("got error \(err!)")
|
|
}
|
|
print("after")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if err != nil {
|
|
print("got error \(err!)")
|
|
return
|
|
}
|
|
print("got result \(res!)")
|
|
print("after")
|
|
}
|
|
// UNBOUND: do {
|
|
// UNBOUND-NEXT: let res = try await withError()
|
|
// UNBOUND-NEXT: print("before")
|
|
// UNBOUND-NEXT: print("got result \(res)")
|
|
// UNBOUND-NEXT: print("after")
|
|
// UNBOUND-NEXT: } catch let err {
|
|
// UNBOUND-NEXT: print("got error \(err)")
|
|
// UNBOUND-NEXT: }
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if res != nil {
|
|
print("got result \(res!)")
|
|
print("after")
|
|
return
|
|
}
|
|
print("got error \(err!)")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if err != nil {
|
|
print("got error \(err!)")
|
|
} else {
|
|
print("got result \(res!)")
|
|
}
|
|
print("after")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if res != nil {
|
|
print("got result \(res!)")
|
|
} else {
|
|
print("got error \(err!)")
|
|
}
|
|
print("after")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if err == nil {
|
|
print("got result \(res!)")
|
|
} else {
|
|
print("got error \(err!)")
|
|
}
|
|
print("after")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if res == nil {
|
|
print("got error \(err!)")
|
|
} else {
|
|
print("got result \(res!)")
|
|
}
|
|
print("after")
|
|
}
|
|
|
|
// Cannot use refactor-check-compiles because of the placeholder, compiler is unable to infer 'str'.
|
|
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNHANDLEDNESTED %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let bad = err {
|
|
print("got error \(bad)")
|
|
} else {
|
|
if let str = res {
|
|
print("got result \(str)")
|
|
}
|
|
}
|
|
print("after")
|
|
}
|
|
// UNHANDLEDNESTED: do {
|
|
// UNHANDLEDNESTED-NEXT: let res = try await withError()
|
|
// UNHANDLEDNESTED-NEXT: print("before")
|
|
// UNHANDLEDNESTED-NEXT: if let str = <#res#> {
|
|
// UNHANDLEDNESTED-NEXT: print("got result \(str)")
|
|
// UNHANDLEDNESTED-NEXT: }
|
|
// UNHANDLEDNESTED-NEXT: print("after")
|
|
// UNHANDLEDNESTED-NEXT: } catch let bad {
|
|
// UNHANDLEDNESTED-NEXT: print("got error \(bad)")
|
|
// UNHANDLEDNESTED-NEXT: }
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=NOERR %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let str = res {
|
|
print("got result \(str)")
|
|
}
|
|
print("after")
|
|
}
|
|
// NOERR: convert_params_single.swift
|
|
// NOERR-NEXT: let str = try await withError()
|
|
// NOERR-NEXT: print("before")
|
|
// NOERR-NEXT: print("got result \(str)")
|
|
// NOERR-NEXT: print("after")
|
|
// NOERR-NOT: }
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=NORES %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let bad = err {
|
|
print("got error \(bad)")
|
|
}
|
|
print("after")
|
|
}
|
|
// NORES: do {
|
|
// NORES-NEXT: let res = try await withError()
|
|
// NORES-NEXT: print("before")
|
|
// NORES-NEXT: print("after")
|
|
// NORES-NEXT: } catch let bad {
|
|
// NORES-NEXT: print("got error \(bad)")
|
|
// NORES-NEXT: }
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if ((res != (nil)) && err == nil) {
|
|
print("got result \(res!)")
|
|
} else {
|
|
print("got error \(err!)")
|
|
}
|
|
print("after")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNKNOWN-COND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if res != nil && test(res!) {
|
|
print("got result \(res!)")
|
|
}
|
|
print("after")
|
|
}
|
|
// UNKNOWN-COND: convert_params_single.swift
|
|
// UNKNOWN-COND-NEXT: let res = try await withError()
|
|
// UNKNOWN-COND-NEXT: print("before")
|
|
// UNKNOWN-COND-NEXT: if <#res#> != nil && test(res) {
|
|
// UNKNOWN-COND-NEXT: print("got result \(res)")
|
|
// UNKNOWN-COND-NEXT: }
|
|
// UNKNOWN-COND-NEXT: print("after")
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNKNOWN-CONDELSE %s
|
|
withError { res, err in
|
|
print("before")
|
|
if res != nil && test(res!) {
|
|
print("got result \(res!)")
|
|
} else {
|
|
print("bad")
|
|
}
|
|
print("after")
|
|
}
|
|
// UNKNOWN-CONDELSE: var res: String? = nil
|
|
// UNKNOWN-CONDELSE-NEXT: var err: (any Error)? = nil
|
|
// UNKNOWN-CONDELSE-NEXT: do {
|
|
// UNKNOWN-CONDELSE-NEXT: res = try await withError()
|
|
// UNKNOWN-CONDELSE-NEXT: } catch {
|
|
// UNKNOWN-CONDELSE-NEXT: err = error
|
|
// UNKNOWN-CONDELSE-NEXT: }
|
|
// UNKNOWN-CONDELSE-EMPTY:
|
|
// UNKNOWN-CONDELSE-NEXT: print("before")
|
|
// UNKNOWN-CONDELSE-NEXT: if res != nil && test(res!) {
|
|
// UNKNOWN-CONDELSE-NEXT: print("got result \(res!)")
|
|
// UNKNOWN-CONDELSE-NEXT: } else {
|
|
// UNKNOWN-CONDELSE-NEXT: print("bad")
|
|
// UNKNOWN-CONDELSE-NEXT: }
|
|
// UNKNOWN-CONDELSE-NEXT: print("after")
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=MULTIBIND %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let str = res {
|
|
print("got result \(str)")
|
|
}
|
|
if let str2 = res {
|
|
print("got result \(str2)")
|
|
}
|
|
if case (let str3?) = (res) {
|
|
print("got result \(str3)")
|
|
}
|
|
print("after")
|
|
}
|
|
// MULTIBIND: let str = try await withError()
|
|
// MULTIBIND-NEXT: print("before")
|
|
// MULTIBIND-NEXT: print("got result \(str)")
|
|
// MULTIBIND-NEXT: print("got result \(str)")
|
|
// MULTIBIND-NEXT: print("got result \(str)")
|
|
// MULTIBIND-NEXT: print("after")
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=NESTEDRET %s
|
|
withError { res, err in
|
|
print("before")
|
|
if let str = res {
|
|
if test(str) {
|
|
return
|
|
}
|
|
print("got result \(str)")
|
|
}
|
|
print("after")
|
|
}
|
|
// NESTEDRET: convert_params_single.swift
|
|
// NESTEDRET-NEXT: let str = try await withError()
|
|
// NESTEDRET-NEXT: print("before")
|
|
// NESTEDRET-NEXT: if test(str) {
|
|
// NESTEDRET-NEXT: <#return#>
|
|
// NESTEDRET-NEXT: }
|
|
// NESTEDRET-NEXT: print("got result \(str)")
|
|
// NESTEDRET-NEXT: print("after")
|
|
// NESTEDRET-NOT: }
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND-ERR %s
|
|
withError { res, err in
|
|
print("before")
|
|
guard let str = res, err == nil else {
|
|
print("got error \(err!)")
|
|
return
|
|
}
|
|
print("got result \(str)")
|
|
print("after")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
guard res != nil else {
|
|
print("got error \(err!)")
|
|
return
|
|
}
|
|
print("got result \(res!)")
|
|
print("after")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
guard err == nil else {
|
|
print("got error \(err!)")
|
|
return
|
|
}
|
|
print("got result \(res!)")
|
|
print("after")
|
|
}
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNBOUND %s
|
|
withError { res, err in
|
|
print("before")
|
|
guard res != nil && err == nil else {
|
|
print("got error \(err!)")
|
|
return
|
|
}
|
|
print("got result \(res!)")
|
|
print("after")
|
|
}
|
|
|
|
// Cannot use refactor-check-compiles as transform results in invalid code,
|
|
// see comment below.
|
|
// RUN: %refactor -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=UNWRAPPING %s
|
|
withError { str, err in
|
|
print("before")
|
|
guard err == nil else { return }
|
|
_ = str!.count
|
|
_ = /*before*/str!/*after*/.count
|
|
_ = str?.count
|
|
_ = str!.count.bitWidth
|
|
_ = str?.count.bitWidth
|
|
_ = (str?.count.bitWidth)!
|
|
_ = str!.first?.isWhitespace
|
|
_ = str?.first?.isWhitespace
|
|
_ = (str?.first?.isWhitespace)!
|
|
print("after")
|
|
}
|
|
// UNWRAPPING: let str = try await withError()
|
|
// UNWRAPPING-NEXT: print("before")
|
|
// UNWRAPPING-NEXT: _ = str.count
|
|
// UNWRAPPING-NEXT: _ = /*before*/str/*after*/.count
|
|
// UNWRAPPING-NEXT: _ = str.count
|
|
// UNWRAPPING-NEXT: _ = str.count.bitWidth
|
|
// UNWRAPPING-NEXT: _ = str.count.bitWidth
|
|
|
|
// Note this transform results in invalid code as str.count.bitWidth is no
|
|
// longer optional, but arguably it's more useful than leaving str as a
|
|
// placeholder. In general, the transform we perform here is locally valid
|
|
// within the optional chain, but may change the type of the overall chain.
|
|
// UNWRAPPING-NEXT: _ = (str.count.bitWidth)!
|
|
|
|
// UNWRAPPING-NEXT: _ = str.first?.isWhitespace
|
|
// UNWRAPPING-NEXT: _ = str.first?.isWhitespace
|
|
// UNWRAPPING-NEXT: _ = (str.first?.isWhitespace)!
|
|
// UNWRAPPING-NEXT: print("after")
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=NOT-OPTIONAL %s
|
|
notOptional { str, err in
|
|
print("before")
|
|
if let err2 = err {
|
|
print("got error \(err2)")
|
|
return
|
|
}
|
|
print("got result \(str)")
|
|
print("after")
|
|
}
|
|
// NOT-OPTIONAL: do {
|
|
// NOT-OPTIONAL-NEXT: let str = try await notOptional()
|
|
// NOT-OPTIONAL-NEXT: print("before")
|
|
// NOT-OPTIONAL-NEXT: print("got result \(str)")
|
|
// NOT-OPTIONAL-NEXT: print("after")
|
|
// NOT-OPTIONAL-NEXT: } catch let err2 {
|
|
// NOT-OPTIONAL-NEXT: print("got error \(err2)")
|
|
// NOT-OPTIONAL-NEXT: }
|
|
|
|
// RUN: %refactor-check-compiles -convert-call-to-async-alternative -dump-text -source-filename %s -pos=%(line+1):3 | %FileCheck -check-prefix=ERROR-ONLY %s
|
|
errorOnly { err in
|
|
print("before")
|
|
if let err2 = err {
|
|
print("got error \(err2)")
|
|
return
|
|
}
|
|
print("after")
|
|
}
|
|
// ERROR-ONLY: convert_params_single.swift
|
|
// ERROR-ONLY-NEXT: do {
|
|
// ERROR-ONLY-NEXT: try await errorOnly()
|
|
// ERROR-ONLY-NEXT: print("before")
|
|
// ERROR-ONLY-NEXT: print("after")
|
|
// ERROR-ONLY-NEXT: } catch let err2 {
|
|
// ERROR-ONLY-NEXT: print("got error \(err2)")
|
|
// ERROR-ONLY-NEXT: }
|
|
// ERROR-ONLY-NOT: }
|
|
}
|