mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This is a diagnostic that is only really emitted as a fallback when the constraint system isn't able to better diagnose the expression. It's not particulary helpful for the user, and can be often be misleading since the underlying issue might not actually be an ambiguity, and the user may well already have a type annotation. Let's instead just emit the fallback diagnostic that we emit in all other cases, asking the user to file a bug.
1650 lines
50 KiB
Swift
1650 lines
50 KiB
Swift
// RUN: %target-typecheck-verify-swift -disable-availability-checking
|
|
|
|
// MARK: Functions
|
|
|
|
func foo() -> Int {
|
|
if .random() { 1 } else { 2 }
|
|
}
|
|
|
|
func foo2() -> Int {
|
|
return if .random() { 1 } else { 2 }
|
|
}
|
|
|
|
func foo3() -> Int {
|
|
if .random() { 1 } else { 2 } as Int
|
|
}
|
|
|
|
func foo4() -> Int {
|
|
return if .random() { 1 } else { 2 } as Int
|
|
}
|
|
|
|
func foo5() -> Int {
|
|
// We only allow coercions as a narrow case in the parser, so attempting to
|
|
// double them up is invalid.
|
|
if .random() { 1 } else { 2 } as Int as Int
|
|
// expected-error@-1 {{consecutive statements on a line must be separated by ';'}}
|
|
// expected-error@-2 {{expected expression}}
|
|
}
|
|
|
|
func foo6() -> Int {
|
|
let x = if .random() { 1 } else { 2 } as Int as Int
|
|
return x
|
|
}
|
|
|
|
func foo7() -> String {
|
|
if .random() { 1 } else { 2 } as String
|
|
// expected-error@-1 {{cannot convert value of type 'Int' to specified type 'String'}}
|
|
}
|
|
|
|
func foo8() -> Int {
|
|
return (if .random() { 1 } else { 2 } as Int)
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
|
|
func foo9() -> String? {
|
|
if .random() { 1 as Any } else { 2 as Any } as? String
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
|
|
func foo10() -> String {
|
|
if .random() { 1 as Any } else { 2 as Any } as! String
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
|
|
func foo11() -> Bool {
|
|
// We don't parse this.
|
|
if .random() { 1 as Any } else { 2 as Any } is String
|
|
// expected-error@-1 {{consecutive statements on a line must be separated by ';'}}
|
|
// expected-error@-2 {{expected expression}}
|
|
// expected-error@-3 {{cannot convert value of type 'Any' to specified type 'Bool'}}
|
|
}
|
|
|
|
func foo12() -> Bool {
|
|
let x = if .random() { 1 as Any } else { 2 as Any } is String
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
return x
|
|
}
|
|
|
|
func bar() -> Int {
|
|
if .random() {
|
|
fatalError()
|
|
} else {
|
|
2
|
|
}
|
|
}
|
|
|
|
func baz() -> Int {
|
|
if .random() {
|
|
"" // expected-error {{cannot convert value of type 'String' to specified type 'Int'}}
|
|
} else {
|
|
0
|
|
}
|
|
}
|
|
|
|
func qux(_ x: Int?) -> Int {
|
|
if let x = x { x } else { 0 }
|
|
}
|
|
|
|
func quux(_ x: Int?) -> Int {
|
|
if case let x? = x { x } else { 0 }
|
|
}
|
|
|
|
func elseIf(_ x: Int?) -> Int {
|
|
if .random() {
|
|
0
|
|
} else if let x = x {
|
|
x
|
|
} else if .random() {
|
|
1
|
|
} else {
|
|
7 + 8
|
|
}
|
|
}
|
|
|
|
func takesValue<T>(_ x: T) {}
|
|
|
|
// expected-error@+1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
takesValue(if .random() {
|
|
0
|
|
} else {
|
|
1
|
|
})
|
|
takesValue(if .random() { 0 } else { 1 })
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
// Cannot parse labeled if as expression.
|
|
do {
|
|
takesValue(x: if .random() { 0 } else { 1 })
|
|
// expected-error@-1 {{extraneous argument label 'x:' in call}}
|
|
// expected-error@-2 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
takesValue(_: x: if .random() { 0 } else { 1 })
|
|
// expected-error@-1 {{expected argument label before colon}}
|
|
// expected-error@-2 {{expected ',' separator}}
|
|
// expected-error@-3 {{cannot find 'x' in scope}}
|
|
// expected-error@-4 {{extra argument in call}}
|
|
// expected-error@-5 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
func takesValueWithLabel<T>(x: T) {}
|
|
do {
|
|
takesValueWithLabel(x: if .random() { 1 } else { 2 })
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
takesValueWithLabel(x: y: if .random() { 1 } else { 2 })
|
|
// expected-error@-1 {{expected argument label before colon}}
|
|
// expected-error@-2 {{expected ',' separator}}
|
|
// expected-error@-3 {{cannot find 'y' in scope}}
|
|
// expected-error@-4 {{extra argument in call}}
|
|
// expected-error@-5 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
func takesValueAndTrailingClosure<T>(_ x: T, _ fn: () -> Int) {}
|
|
takesValueAndTrailingClosure(if .random() { 0 } else { 1 }) { 2 }
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
func takesInOut<T>(_ x: inout T) {}
|
|
takesInOut(&if .random() { 1 } else { 2 })
|
|
// expected-error@-1 {{cannot pass immutable value of type 'Int' as inout argument}}
|
|
// expected-error@-2 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
struct HasSubscript {
|
|
static subscript(x: Int) -> Void { () }
|
|
|
|
subscript(x: Int...) -> Void { () }
|
|
}
|
|
HasSubscript[if .random() { 1 } else { 2 }]
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
func proposalExample1(isRoot: Bool, count: Int, willExpand: Bool, maxDepth: Int) -> String {
|
|
let bullet =
|
|
if isRoot && (count == 0 || !willExpand) { "" }
|
|
else if count == 0 { "- " }
|
|
else if maxDepth <= 0 { "▹ " }
|
|
else { "▿ " }
|
|
return bullet
|
|
}
|
|
|
|
var inAComputedVar: String {
|
|
if .random() { "a" } else { "b" }
|
|
}
|
|
|
|
// MARK: Outer pound if
|
|
|
|
func withPoundIf() -> Int {
|
|
#if true
|
|
if .random() { 0 } else { 1 }
|
|
#endif
|
|
}
|
|
|
|
func withPoundIfClosure() -> Int {
|
|
let fn = {
|
|
#if true
|
|
if .random() { 0 } else { 1 }
|
|
#endif
|
|
}
|
|
return fn()
|
|
}
|
|
|
|
func withPoundIfElse1() -> Int {
|
|
#if true
|
|
if .random() { 0 } else { 1 }
|
|
#else
|
|
0
|
|
#endif
|
|
}
|
|
|
|
func withPoundIfElse2() -> Int {
|
|
#if true
|
|
0
|
|
#else
|
|
if .random() { 0 } else { 1 }
|
|
#endif
|
|
}
|
|
|
|
func withPoundIfElseIf1() -> Int {
|
|
#if true
|
|
if .random() { 0 } else { 1 }
|
|
#elseif true
|
|
0
|
|
#endif
|
|
}
|
|
|
|
|
|
func withPoundIfElseIf2() -> Int {
|
|
#if true
|
|
0
|
|
#elseif true
|
|
if .random() { 0 } else { 1 }
|
|
#endif
|
|
}
|
|
|
|
func withPoundIfElseIfElse1() -> Int {
|
|
#if true
|
|
if .random() { 0 } else { 1 }
|
|
#elseif true
|
|
0
|
|
#else
|
|
0
|
|
#endif
|
|
}
|
|
|
|
func withPoundIfElseIfElse2() -> Int {
|
|
#if true
|
|
0
|
|
#elseif true
|
|
if .random() { 0 } else { 1 }
|
|
#else
|
|
0
|
|
#endif
|
|
}
|
|
|
|
func withPoundIfElseIfElse3() -> Int {
|
|
#if true
|
|
0
|
|
#elseif true
|
|
0
|
|
#else
|
|
if .random() { 0 } else { 1 }
|
|
#endif
|
|
}
|
|
|
|
func withVeryNestedPoundIf() -> Int {
|
|
#if true
|
|
#if true
|
|
#if false
|
|
""
|
|
#else
|
|
if .random() { 0 } else { 1 }
|
|
#endif
|
|
#elseif true
|
|
0
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
func withVeryNestedPoundIfClosure() -> Int {
|
|
let fn = {
|
|
#if true
|
|
#if true
|
|
#if false
|
|
""
|
|
#else
|
|
if .random() { 0 } else { 1 }
|
|
#endif
|
|
#elseif true
|
|
0
|
|
#endif
|
|
#endif
|
|
}
|
|
return fn()
|
|
}
|
|
|
|
// MARK: Explicit returns
|
|
|
|
func explicitReturn1() -> Int {
|
|
print("hello")
|
|
return if .random() { 0 } else { 1 }
|
|
}
|
|
|
|
func explicitReturn2() -> Int {
|
|
return
|
|
if .random() { 0 } else { 1 }
|
|
// expected-warning@-1 {{expression following 'return' is treated as an argument of the 'return'}}
|
|
// expected-note@-2 {{indent the expression to silence this warning}}
|
|
}
|
|
|
|
func explicitReturn3() -> Int {
|
|
return
|
|
if .random() { 0 } else { 1 }
|
|
}
|
|
|
|
func explicitReturn4() {
|
|
// This used to be legal, but is now treated as a return of the if expression.
|
|
return
|
|
if .random() { 0 } else { 1 }
|
|
// expected-error@-1 {{unexpected non-void return value in void function}}
|
|
// expected-note@-2 {{did you mean to add a return type?}}
|
|
}
|
|
|
|
func explicitReturn5() {
|
|
return;
|
|
if .random() { 0 } else { 1 } // expected-warning 2{{integer literal is unused}}
|
|
}
|
|
|
|
func explicitReturn6() {
|
|
return ()
|
|
if .random() { 0 } else { 1 } // expected-warning 2{{integer literal is unused}}
|
|
}
|
|
|
|
var explicitReturn7: String {
|
|
return if .random() { "a" } else { "b" }
|
|
}
|
|
|
|
struct AsPropertyInit {
|
|
var x: Int = if Bool.random() { 1 } else { 0 }
|
|
var y = if .random() { 1 } else { 0 }
|
|
}
|
|
|
|
func testNestedAssignment() {
|
|
var x = 0
|
|
x = if .random() { 0 } else { 1 } // Okay
|
|
let fn = {
|
|
x = if .random() { 0 } else { 1 } // Also okay
|
|
}
|
|
|
|
// We don't allow in a nested assignment.
|
|
// TODO: We could improve this error.
|
|
print(x = if .random() { 0 } else { 1 })
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
_ = x; _ = fn
|
|
}
|
|
|
|
struct TestFailableInit {
|
|
init?(_ x: Bool) {
|
|
let y = if x {
|
|
0
|
|
} else {
|
|
return nil // expected-error {{cannot use 'return' to transfer control out of 'if' expression}}
|
|
}
|
|
_ = y
|
|
}
|
|
}
|
|
|
|
struct TestFailableInitFatalError {
|
|
init?() {
|
|
// In this case, the if does not become an expression.
|
|
if .random() {
|
|
fatalError()
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: Expressions
|
|
|
|
let a = if .random() {
|
|
0
|
|
} else {
|
|
1
|
|
}
|
|
|
|
let b = (if .random() { 1 } else { 2 }) // expected-error {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
let c = (if .random() { 1 } else { 2 }, k: if .random() { 1 } else { 2 }) // expected-error 2{{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
var d = if .random() { if .random() { 1 } else { 2 } } else { 3 }
|
|
|
|
d = if .random() { 0 } else { 1 }
|
|
|
|
let e = "\(if .random() { 1 } else { 2 })" // expected-error {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
let f = { if .random() { 1 } else { 2 } }
|
|
|
|
func throwsError() throws {
|
|
struct E: Error {}
|
|
throw if .random() { E() } else { E() }
|
|
}
|
|
|
|
// FIXME: If we ever support this, we need to fix the premature inference of '[Any]'/'[AnyHashable: Any]'.
|
|
// The issue is that we're attempting to bind defaults to type variables before solving the conjuction.
|
|
let g = [if .random() { "a" } else { "b" }]
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
// expected-error@-2 {{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}}
|
|
|
|
let h = [if .random() { 1 } else { 2 } : if .random() { "a" } else { "b" }]
|
|
// expected-error@-1 2{{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
// expected-error@-2 {{heterogeneous collection literal could only be inferred to '[AnyHashable : Any]'; add explicit type annotation if this is intentional}}
|
|
|
|
let i = [if .random() { 1 } else { 2 }: if .random() { "a" } else { "b" }]
|
|
// expected-error@-1 2{{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
// expected-error@-2 {{heterogeneous collection literal could only be inferred to '[AnyHashable : Any]'; add explicit type annotation if this is intentional}}
|
|
|
|
let j = [if .random() { 1 } else { 2 }:if .random() { "a" } else { "b" }]
|
|
// expected-error@-1 2{{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
// expected-error@-2 {{heterogeneous collection literal could only be inferred to '[AnyHashable : Any]'; add explicit type annotation if this is intentional}}
|
|
|
|
let k = [if .random() { 1 } else { 2 } :if .random() { "a" } else { "b" }]
|
|
// expected-error@-1 2{{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
// expected-error@-2 {{heterogeneous collection literal could only be inferred to '[AnyHashable : Any]'; add explicit type annotation if this is intentional}}
|
|
|
|
let l = if .random() { 1 } else { 2 } as Any
|
|
|
|
let _ = type(of: if .random() { 1 } else { 2 }) // expected-error {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
let _ = (if .random() { () } else { () }) // expected-error {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
let _ = if .random() { 0 } // expected-error {{'if' must have an unconditional 'else' to be used as expression}}
|
|
let _ = if .random() { 0 } else if .random() { 1 } // expected-error {{'if' must have an unconditional 'else' to be used as expression}}
|
|
|
|
func testNonExhaustiveInFunction() {
|
|
if .random() { 0 } // expected-warning {{integer literal is unused}}
|
|
}
|
|
|
|
func testLabelRejection1() -> Int {
|
|
// This was legal before, so remains legal.
|
|
x: if .random() { 0 } else { 1 }
|
|
// expected-warning@-1 2{{integer literal is unused}}
|
|
}
|
|
|
|
func testLabelRejection2() -> Int {
|
|
// This was never legal, so reject.
|
|
x: if .random() { 0 } else { 1 } as Int
|
|
// expected-error@-1 {{'if' cannot have a jump label when used as expression}}
|
|
}
|
|
|
|
do {
|
|
if .random() { 1 } else { 2 } = 3
|
|
// expected-error@-1 {{consecutive statements on a line must be separated by ';'}}
|
|
// expected-error@-2 {{expected expression}}
|
|
// expected-warning@-3 2{{integer literal is unused}}}
|
|
}
|
|
let m: Void = if .random() { 1 } else { 2 } // expected-error {{cannot convert value of type 'Int' to specified type 'Void'}}
|
|
let n: Never = if .random() { 1 } else { 2 } // expected-error {{cannot convert value of type 'Int' to specified type 'Never'}}
|
|
|
|
func testConditionalBinding1(_ x: Int?) -> Int {
|
|
if let x = if .random() { 0 } else { Int?.none } { // expected-error {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
x
|
|
} else {
|
|
0
|
|
}
|
|
}
|
|
|
|
func testConditionalBinding2(_ x: Int?) -> Int {
|
|
if case let x? = if .random() { 0 } else { Int?.none } { // expected-error {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
x
|
|
} else {
|
|
0
|
|
}
|
|
}
|
|
|
|
// MARK: Operators
|
|
|
|
let o = !if .random() { true } else { false } // expected-error {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
// FIXME: Shouldn't be ambiguous
|
|
let p = if .random() { 1 } else { 2 } + // expected-error {{ambiguous use of operator '+'}}
|
|
if .random() { 3 } else { 4 } +
|
|
if .random() { 5 } else { 6 }
|
|
// expected-error@-3 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
// expected-error@-3 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
// expected-error@-3 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
let p1 = if .random() { 1 } else { 2 } + 5
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
let q = .random() ? if .random() { 1 } else { 2 }
|
|
: if .random() { 3 } else { 4 }
|
|
// expected-error@-2 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
// expected-error@-2 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
let r = if .random() { 1 } else { 2 }...if .random() { 1 } else { 2 }
|
|
// expected-error@-1 2{{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
let s = if .random() { 1 } else { 2 } ... if .random() { 1 } else { 2 }
|
|
// expected-error@-1 2{{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
// MARK: Lookup
|
|
|
|
do {
|
|
let t = if .random() { t } else { 0 }
|
|
// expected-error@-1 {{use of local variable 't' before its declaration}}
|
|
// expected-note@-2 {{'t' declared here}}
|
|
}
|
|
|
|
// MARK: Postfix
|
|
|
|
// We don't allow postfix parsing.
|
|
do {
|
|
let _ = if .random() { [1] } else { [1, 2] }.count
|
|
// expected-error@-1 {{consecutive statements on a line must be separated by ';'}}
|
|
// expected-error@-2 {{reference to member 'count' cannot be resolved without a contextual type}}
|
|
|
|
let _ = (if .random() { [1] } else { [1, 2] }).count
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
do {
|
|
let _ = if .random() { Int?.none } else { 1 as Int? }?.bitWidth
|
|
// expected-error@-1 {{consecutive statements on a line must be separated by ';'}}
|
|
// expected-error@-2 {{expected expression}}
|
|
|
|
// FIXME: The type error is likely due to not solving the conjunction before attempting default type var bindings.
|
|
let _ = (if .random() { Int?.none } else { 1 as Int? })?.bitWidth
|
|
// expected-error@-1 {{failed to produce diagnostic for expression}}
|
|
// expected-error@-2 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
do {
|
|
let _ = if .random() { Int?.none } else { 1 as Int? }!
|
|
// expected-error@-1 {{consecutive statements on a line must be separated by ';'}}
|
|
// expected-error@-2 {{expected expression}}
|
|
|
|
let _ = (if .random() { Int?.none } else { 1 as Int? })!
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
do {
|
|
func takesInts(_ x: Int...) {}
|
|
let _ = if .random() { takesInts } else { takesInts }(1, 2, 3)
|
|
// expected-error@-1 {{consecutive statements on a line must be separated by ';'}}
|
|
// expected-warning@-2 {{expression of type '(Int, Int, Int)' is unused}}
|
|
|
|
let _ = (if .random() { takesInts } else { takesInts })(1, 2, 3)
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
func testSubscriptPostfix(_ x: HasSubscript) {
|
|
if .random() { x } else { x }[1, 2, 3]
|
|
// expected-error@-1 {{consecutive statements on a line must be separated by ';'}}
|
|
// expected-warning@-2 {{expression of type 'HasSubscript' is unused}}
|
|
// expected-warning@-3 {{expression of type '[Int]' is unused}}
|
|
// expected-warning@-4 {{expression of type 'HasSubscript' is unused}}
|
|
|
|
(if .random() { x } else { x })[1, 2, 3]
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
do {
|
|
func takesClosure(_ fn: () -> Int) {}
|
|
|
|
let _ = if .random() { takesClosure } else { takesClosure } { 3 }
|
|
// expected-error@-1 {{getter/setter can only be defined for a single variable}}
|
|
|
|
let _ = (if .random() { takesClosure } else { takesClosure }) { 3 }
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
|
|
// MARK: Statements
|
|
|
|
func stmts() {
|
|
if if .random() { true } else { false } {}
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
if try if .random() { true } else { false } {}
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
// expected-warning@-2 {{'try' has no effect on 'if' expression}}
|
|
|
|
// expected-error@+1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
guard if .random() { true } else { false } else {
|
|
return
|
|
}
|
|
|
|
switch if .random() { true } else { false } {
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
case _ where if .random() { true } else { false }:
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
break
|
|
case if .random() { true } else { false }:
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
break
|
|
case if .random() { true } else { false } && false:
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
break
|
|
default:
|
|
break
|
|
}
|
|
|
|
for b in [true] where if b { true } else { false } {}
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
for _ in if .random() { [true] } else { [false] } {}
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
for _ in if .random() { [true] } else { [false] } {} // expected-error {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
// Make sure this doesn't parse as an if expr pattern with a label.
|
|
let x = 0
|
|
switch 0 {
|
|
case x: if .random() { 1 } else { 2 }
|
|
// expected-warning@-1 2{{integer literal is unused}}
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
// MARK: Non-expression branches
|
|
|
|
func noElse() -> Int {
|
|
// Not an expression because no else.
|
|
if .random() {
|
|
0 // expected-warning {{integer literal is unused}}
|
|
}
|
|
1 // expected-warning {{integer literal is unused}}
|
|
}
|
|
|
|
func returnBranches() -> Int {
|
|
// This is not an expression because the branches are not expressions.
|
|
if .random() {
|
|
return 0
|
|
} else {
|
|
return 1
|
|
}
|
|
}
|
|
|
|
func returnBranches1() -> Int {
|
|
return if .random() { // expected-error {{cannot convert return expression of type 'Void' to return type 'Int'}}
|
|
return 0 // expected-error {{cannot use 'return' to transfer control out of 'if' expression}}
|
|
} else {
|
|
return 1 // expected-error {{cannot use 'return' to transfer control out of 'if' expression}}
|
|
}
|
|
}
|
|
|
|
func returnBranchVoid() {
|
|
return if .random() { return } else { return () }
|
|
// expected-error@-1 2{{cannot use 'return' to transfer control out of 'if' expression}}
|
|
}
|
|
|
|
func returnBranchBinding() -> Int {
|
|
let x = if .random() {
|
|
// expected-warning@-1 {{constant 'x' inferred to have type 'Void', which may be unexpected}}
|
|
// expected-note@-2 {{add an explicit type annotation to silence this warning}}
|
|
return 0 // expected-error {{cannot use 'return' to transfer control out of 'if' expression}}
|
|
} else {
|
|
return 1 // expected-error {{cannot use 'return' to transfer control out of 'if' expression}}
|
|
}
|
|
return x // expected-error {{cannot convert return expression of type 'Void' to return type 'Int'}}
|
|
}
|
|
|
|
func returnBranches2() -> Int {
|
|
// We don't allow multiple expressions.
|
|
if .random() {
|
|
print("hello")
|
|
0 // expected-warning {{integer literal is unused}}
|
|
} else {
|
|
1 // expected-warning {{integer literal is unused}}
|
|
}
|
|
}
|
|
|
|
func returnBranches3() -> Int {
|
|
if .random() {
|
|
print("hello")
|
|
return 0
|
|
} else {
|
|
1 // expected-warning {{integer literal is unused}}
|
|
}
|
|
}
|
|
|
|
func returnBranches4() -> Int {
|
|
if .random() { return 1 } else { 0 } // expected-warning {{integer literal is unused}}
|
|
}
|
|
|
|
struct Err: Error {}
|
|
|
|
func returnBranches5() throws -> Int {
|
|
let i = if .random() {
|
|
// expected-warning@-1 {{constant 'i' inferred to have type 'Void', which may be unexpected}}
|
|
// expected-note@-2 {{add an explicit type annotation to silence this warning}}
|
|
return 0 // expected-error {{cannot use 'return' to transfer control out of 'if' expression}}
|
|
} else {
|
|
return 1 // expected-error {{cannot use 'return' to transfer control out of 'if' expression}}
|
|
}
|
|
let j = if .random() {
|
|
// expected-warning@-1 {{constant 'j' inferred to have type 'Void', which may be unexpected}}
|
|
// expected-note@-2 {{add an explicit type annotation to silence this warning}}
|
|
throw Err()
|
|
} else {
|
|
throw Err()
|
|
}
|
|
return i // expected-error {{cannot convert return expression of type 'Void' to return type 'Int'}}
|
|
}
|
|
|
|
func returnBranches6() -> Int {
|
|
// We don't allow multiple expressions.
|
|
let i = if .random() {
|
|
print("hello")
|
|
0 // expected-warning {{integer literal is unused}}
|
|
} else { // expected-error {{non-expression branch of 'if' expression may only end with a 'throw'}}
|
|
1
|
|
}
|
|
return i
|
|
}
|
|
|
|
func returnBranches6PoundIf() -> Int {
|
|
// We don't allow multiple expressions.
|
|
let i = if .random() {
|
|
#if true
|
|
print("hello")
|
|
0 // expected-warning {{integer literal is unused}}
|
|
#endif
|
|
} else { // expected-error {{non-expression branch of 'if' expression may only end with a 'throw'}}
|
|
1
|
|
}
|
|
return i
|
|
}
|
|
|
|
func returnBranches6PoundIf2() -> Int {
|
|
// We don't allow multiple expressions.
|
|
let i = if .random() { // expected-error{{expected expression in branch of 'if' expression}}
|
|
#if false
|
|
print("hello")
|
|
0
|
|
#endif
|
|
} else {
|
|
1
|
|
}
|
|
return i
|
|
}
|
|
|
|
func returnBranches7() -> Int {
|
|
let i = if .random() {
|
|
print("hello")
|
|
return 0 // expected-error {{cannot use 'return' to transfer control out of 'if' expression}}
|
|
} else {
|
|
1
|
|
}
|
|
return i
|
|
}
|
|
|
|
func returnBranches8() -> Int {
|
|
let i = if .random() { return 1 } else { 0 } // expected-error {{cannot use 'return' to transfer control out of 'if' expression}}
|
|
return i
|
|
}
|
|
|
|
func returnBranches9() -> Int {
|
|
let i = if .random() {
|
|
print("hello")
|
|
if .random() {}
|
|
} else { // expected-error {{non-expression branch of 'if' expression may only end with a 'throw'}}
|
|
1
|
|
}
|
|
return i
|
|
}
|
|
|
|
func returnBranches10() -> Int {
|
|
let i = if .random() {
|
|
print("hello")
|
|
if .random() {
|
|
0 // expected-warning {{integer literal is unused}}
|
|
} else {
|
|
2 // expected-warning {{integer literal is unused}}
|
|
}
|
|
} else { // expected-error {{non-expression branch of 'if' expression may only end with a 'throw'}}
|
|
1
|
|
}
|
|
return i
|
|
}
|
|
|
|
func returnBranches11() -> Int {
|
|
let i = if .random() {
|
|
print("hello")
|
|
if .random() {
|
|
"" // expected-warning {{string literal is unused}}
|
|
} else {
|
|
0 // expected-warning {{integer literal is unused}}
|
|
}
|
|
} else { // expected-error {{non-expression branch of 'if' expression may only end with a 'throw'}}
|
|
1
|
|
}
|
|
return i
|
|
}
|
|
|
|
func returnBranches12() -> Int {
|
|
if .random() {
|
|
print("hello")
|
|
if .random() {}
|
|
} else {
|
|
1 // expected-warning {{integer literal is unused}}
|
|
}
|
|
}
|
|
|
|
func returnBranches13() -> Int {
|
|
if .random() {
|
|
print("hello")
|
|
if .random() {
|
|
0 // expected-warning {{integer literal is unused}}
|
|
} else {
|
|
2 // expected-warning {{integer literal is unused}}
|
|
}
|
|
} else {
|
|
1 // expected-warning {{integer literal is unused}}
|
|
}
|
|
}
|
|
|
|
func returnBranches14() -> Int {
|
|
if .random() {
|
|
print("hello")
|
|
if .random() {
|
|
"" // expected-warning {{string literal is unused}}
|
|
} else {
|
|
0 // expected-warning {{integer literal is unused}}
|
|
}
|
|
} else {
|
|
1 // expected-warning {{integer literal is unused}}
|
|
}
|
|
}
|
|
|
|
func nestedType() -> Int {
|
|
if .random() {
|
|
struct S {
|
|
var x: Int
|
|
}
|
|
return S(x: 0).x
|
|
} else {
|
|
0 // expected-warning {{integer literal is unused}}
|
|
}
|
|
}
|
|
|
|
func testEmptyBranch() -> Int {
|
|
let x = if .random() {} else { 0 }
|
|
// expected-error@-1:24 {{expected expression in branch of 'if' expression}}
|
|
return x
|
|
}
|
|
|
|
// MARK: Pound if branches
|
|
|
|
func testPoundIfBranch1() -> Int {
|
|
if .random() {
|
|
#if true
|
|
0
|
|
#endif
|
|
} else {
|
|
0
|
|
}
|
|
}
|
|
|
|
func testPoundIfBranch2() -> Int {
|
|
if .random() {
|
|
#if false
|
|
0
|
|
#endif
|
|
} else {
|
|
0 // expected-warning {{integer literal is unused}}
|
|
}
|
|
}
|
|
|
|
func testPoundIfBranch3() -> Int {
|
|
let x = if .random() { // expected-error{{expected expression in branch of 'if' expression}}
|
|
#if false
|
|
0
|
|
#endif
|
|
} else {
|
|
0
|
|
}
|
|
return x
|
|
}
|
|
|
|
func testPoundIfBranch4() -> Int {
|
|
if .random() {
|
|
#if true
|
|
0
|
|
#endif
|
|
} else {
|
|
#if true
|
|
0
|
|
#endif
|
|
}
|
|
}
|
|
|
|
func testPoundIfBranch5() -> Int {
|
|
// Inactive #if regions don't count
|
|
if .random() {
|
|
#if false
|
|
0
|
|
#endif
|
|
0
|
|
} else {
|
|
1
|
|
}
|
|
}
|
|
|
|
func testPoundIfBranch6() -> Int {
|
|
// Inactive #if regions don't count
|
|
let x = if .random() {
|
|
#if false
|
|
0
|
|
#endif
|
|
0
|
|
} else {
|
|
1
|
|
}
|
|
return x
|
|
}
|
|
|
|
func testPoundIfBranch7() -> Int {
|
|
if .random() {
|
|
#if true
|
|
#if true
|
|
#if false
|
|
""
|
|
#else
|
|
0
|
|
#endif
|
|
#elseif true
|
|
""
|
|
#endif
|
|
#endif
|
|
} else {
|
|
0
|
|
}
|
|
}
|
|
|
|
func testPoundIfBranch8() -> Int {
|
|
if .random() {
|
|
#if false
|
|
0
|
|
#else
|
|
#if true
|
|
if .random() { 0 } else { 1 }
|
|
#endif
|
|
#endif
|
|
} else {
|
|
#if true
|
|
if .random() { 0 } else { 1 }
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// MARK: Jumping
|
|
|
|
func break1() -> Int {
|
|
switch true {
|
|
case true:
|
|
let j = if .random() {
|
|
break // expected-error {{cannot use 'break' to transfer control out of 'if' expression}}
|
|
} else {
|
|
0
|
|
}
|
|
return j
|
|
case false:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func continue1() -> Int {
|
|
for _ in 0 ... 5 {
|
|
let i = if true { continue } else { 1 }
|
|
// expected-error@-1 {{cannot use 'continue' to transfer control out of 'if' expression}}
|
|
return i
|
|
}
|
|
}
|
|
|
|
func return1() -> Int {
|
|
// Make sure we always reject a return.
|
|
let i = if .random() {
|
|
()
|
|
do {
|
|
for _ in [0] {
|
|
while true {
|
|
switch 0 {
|
|
default:
|
|
return 0 // expected-error {{cannot use 'return' to transfer control out of 'if' expression}}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
0
|
|
}
|
|
return i
|
|
}
|
|
|
|
func return2() throws -> Int {
|
|
// In a nested function is okay though.
|
|
let i = if .random() {
|
|
func foo() { return }
|
|
throw Err()
|
|
} else {
|
|
0
|
|
}
|
|
return i
|
|
}
|
|
|
|
func return3() throws -> Int {
|
|
// A nested type is also okay.
|
|
let i = if .random() {
|
|
struct Nested {
|
|
func foo() { return }
|
|
}
|
|
throw Err()
|
|
} else {
|
|
0
|
|
}
|
|
return i
|
|
}
|
|
|
|
func return4() throws -> Int {
|
|
// A nested closure is also okay.
|
|
let i = if .random() {
|
|
let _ = { return }
|
|
throw Err()
|
|
} else {
|
|
0
|
|
}
|
|
return i
|
|
}
|
|
|
|
// https://github.com/swiftlang/swift/issues/75880
|
|
func fallthrough1() throws {
|
|
switch Bool.random() {
|
|
case true:
|
|
let _ = if .random() {
|
|
if .random () {
|
|
fallthrough // expected-error {{cannot use 'fallthrough' to transfer control out of 'if' expression}}
|
|
}
|
|
throw Err()
|
|
} else {
|
|
0
|
|
}
|
|
case false:
|
|
break
|
|
}
|
|
}
|
|
|
|
func fallthrough2() throws -> Int {
|
|
let x = switch Bool.random() {
|
|
case true:
|
|
if .random() {
|
|
if .random () {
|
|
fallthrough // expected-error {{cannot use 'fallthrough' to transfer control out of 'if' expression}}
|
|
}
|
|
throw Err()
|
|
} else {
|
|
0
|
|
}
|
|
case false:
|
|
1
|
|
}
|
|
return x
|
|
}
|
|
|
|
func fallthrough3() -> Int {
|
|
let x = switch Bool.random() {
|
|
case true:
|
|
if .random() {
|
|
fallthrough // expected-error {{cannot use 'fallthrough' to transfer control out of 'if' expression}}
|
|
} else {
|
|
0
|
|
}
|
|
case false:
|
|
1
|
|
}
|
|
return x
|
|
}
|
|
|
|
func fallthrough4() -> Int {
|
|
let x = if .random() {
|
|
fallthrough // expected-error {{'fallthrough' is only allowed inside a switch}}
|
|
} else {
|
|
0
|
|
}
|
|
return x
|
|
}
|
|
|
|
// MARK: Effect specifiers
|
|
|
|
func tryIf1() -> Int {
|
|
try if .random() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func tryIf2() -> Int {
|
|
let x = try if .random() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
return x
|
|
}
|
|
|
|
func tryIf3() -> Int {
|
|
return try if .random() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func tryIf4() throws -> Int {
|
|
return try if .random() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func tryIf5() throws -> Int {
|
|
return try if .random() { tryIf4() } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 {{did you mean to use 'try'?}}
|
|
// expected-note@-4 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-5 {{did you mean to disable error propagation?}}
|
|
}
|
|
|
|
func tryIf6() throws -> Int {
|
|
try if .random() { tryIf4() } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 {{did you mean to use 'try'?}}
|
|
// expected-note@-4 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-5 {{did you mean to disable error propagation?}}
|
|
}
|
|
|
|
func tryIf7() throws -> Int {
|
|
let x = try if .random() { tryIf4() } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 {{did you mean to use 'try'?}}
|
|
// expected-note@-4 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-5 {{did you mean to disable error propagation?}}
|
|
return x
|
|
}
|
|
|
|
func tryIf8() throws -> Int {
|
|
return try if .random() { try tryIf4() } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func tryIf9() throws -> Int {
|
|
try if .random() { try tryIf4() } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func tryIf10() throws -> Int {
|
|
let x = try if .random() { try tryIf4() } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
return x
|
|
}
|
|
|
|
func tryIf11() throws -> Int {
|
|
let x = try if .random() { try tryIf4() } else { tryIf4() }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 {{did you mean to use 'try'?}}
|
|
// expected-note@-4 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-5 {{did you mean to disable error propagation?}}
|
|
return x
|
|
}
|
|
|
|
func tryIf12() throws -> Int {
|
|
let x = try if .random() { tryIf4() } else { tryIf4() }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 2{{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 2{{did you mean to use 'try'?}}
|
|
// expected-note@-4 2{{did you mean to handle error as optional value?}}
|
|
// expected-note@-5 2{{did you mean to disable error propagation?}}
|
|
return x
|
|
}
|
|
|
|
func tryIf13() throws -> Int {
|
|
let x = try if .random() { // expected-warning {{'try' has no effect on 'if' expression}}
|
|
tryIf4() // expected-warning {{result of call to 'tryIf4()' is unused}}
|
|
// expected-warning@-1 {{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-2 {{did you mean to use 'try'?}}
|
|
// expected-note@-3 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-4 {{did you mean to disable error propagation?}}
|
|
|
|
_ = tryIf4()
|
|
// expected-warning@-1 {{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-2 {{did you mean to use 'try'?}}
|
|
// expected-note@-3 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-4 {{did you mean to disable error propagation?}}
|
|
|
|
_ = try tryIf4() // Okay.
|
|
|
|
// Okay.
|
|
do {
|
|
_ = try tryIf4()
|
|
} catch {}
|
|
|
|
print("hello")
|
|
throw Err()
|
|
} else {
|
|
0
|
|
}
|
|
return x
|
|
}
|
|
|
|
func throwsBool() throws -> Bool { true }
|
|
|
|
func tryIf14() throws -> Int {
|
|
try if throwsBool() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 {{did you mean to use 'try'?}}
|
|
// expected-note@-4 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-5 {{did you mean to disable error propagation?}}
|
|
}
|
|
|
|
func tryIf15() throws -> Int {
|
|
try if try throwsBool() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func tryIf16() throws -> Int {
|
|
if throwsBool() { 0 } else { 1 }
|
|
// expected-error@-1 {{call can throw but is not marked with 'try'}}
|
|
// expected-note@-2 {{did you mean to use 'try'?}}
|
|
// expected-note@-3 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-4 {{did you mean to disable error propagation?}}
|
|
}
|
|
|
|
func tryIf17() throws -> Int {
|
|
if .random() { tryIf4() } else { 1 }
|
|
// expected-error@-1 {{call can throw but is not marked with 'try'}}
|
|
// expected-note@-2 {{did you mean to use 'try'?}}
|
|
// expected-note@-3 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-4 {{did you mean to disable error propagation?}}
|
|
}
|
|
|
|
func tryIf18() {
|
|
// Make sure we don't warn here.
|
|
do {
|
|
let _ = if .random() { try tryIf4() } else { 1 }
|
|
} catch {}
|
|
}
|
|
|
|
func tryIf19() {
|
|
// Make sure we don't warn here.
|
|
do {
|
|
let _ = if .random() { throw Err() } else { 1 }
|
|
} catch {}
|
|
}
|
|
|
|
func tryIf19() throws -> Int {
|
|
let x = if .random() { throw Err() } else { 1 }
|
|
return x
|
|
}
|
|
|
|
func tryIf20() throws -> Int {
|
|
if .random() { throw Err() } else { 1 }
|
|
}
|
|
|
|
func tryIf21(_ fn: () throws -> Int) rethrows -> Int {
|
|
let x = if .random() { try fn() } else { 1 }
|
|
return x
|
|
}
|
|
|
|
func tryIf22(_ fn: () throws -> Int) rethrows -> Int {
|
|
if .random() { try fn() } else { 1 }
|
|
}
|
|
|
|
func tryIf23(_ fn: () throws -> Int) rethrows -> Int {
|
|
let x = if .random() { try fn() } else { throw Err() }
|
|
// expected-error@-1 {{a function declared 'rethrows' may only throw if its parameter does}}
|
|
return x
|
|
}
|
|
|
|
func tryIf24(_ fn: () throws -> Int) rethrows -> Int {
|
|
let x = if .random() { try fn() } else { try tryIf4() }
|
|
// expected-error@-1 {{a function declared 'rethrows' may only throw if its parameter does}}
|
|
return x
|
|
}
|
|
|
|
func tryIf25(_ fn: () throws -> Int) rethrows -> Int {
|
|
do {
|
|
let x = if .random() { try fn() } else { try tryIf4() }
|
|
return x
|
|
} catch {
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func tryIf26(_ fn: () throws -> Int) rethrows -> Int {
|
|
do {
|
|
let x = if .random() { try fn() } else { throw Err() }
|
|
return x
|
|
} catch {
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func tryIf27(_ fn: () throws -> Int) rethrows -> Int {
|
|
do {
|
|
let x = if .random() { try fn() } else { try tryIf4() }
|
|
return x
|
|
} catch {
|
|
throw error // expected-error {{a function declared 'rethrows' may only throw if its parameter does}}
|
|
}
|
|
}
|
|
|
|
func tryIf28(_ fn: () throws -> Int) rethrows -> Int {
|
|
do {
|
|
let x = if .random() { try fn() } else { throw Err() }
|
|
return x
|
|
} catch {
|
|
throw error // expected-error {{a function declared 'rethrows' may only throw if its parameter does}}
|
|
}
|
|
}
|
|
|
|
func tryIf29(_ fn: () throws -> Int) rethrows -> Int {
|
|
do {
|
|
let x = if .random() { try fn() } else { 0 }
|
|
return x
|
|
} catch {
|
|
throw error // Okay.
|
|
}
|
|
}
|
|
|
|
func awaitIf1() async -> Int {
|
|
await if .random() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func awaitIf2() async -> Int {
|
|
let x = await if .random() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
return x
|
|
}
|
|
|
|
func awaitIf3() async -> Int {
|
|
return await if .random() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func awaitIf4() async -> Int {
|
|
return await if .random() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func awaitIf5() async -> Int {
|
|
return await if .random() { awaitIf4() } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 {{call is 'async'}}
|
|
}
|
|
|
|
func awaitIf6() async -> Int {
|
|
await if .random() { awaitIf4() } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 {{call is 'async'}}
|
|
}
|
|
|
|
func awaitIf7() async -> Int {
|
|
let x = await if .random() { awaitIf4() } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 {{call is 'async'}}
|
|
return x
|
|
}
|
|
|
|
func awaitIf8() async -> Int {
|
|
return await if .random() { await awaitIf4() } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func awaitIf9() async -> Int {
|
|
await if .random() { await awaitIf4() } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func awaitIf10() async -> Int {
|
|
let x = await if .random() { await awaitIf4() } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
return x
|
|
}
|
|
|
|
func awaitIf11() async -> Int {
|
|
let x = await if .random() { await awaitIf4() } else { awaitIf4() }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 {{call is 'async'}}
|
|
return x
|
|
}
|
|
|
|
func awaitIf12() async -> Int {
|
|
let x = await if .random() { awaitIf4() } else { awaitIf4() }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-2 2{{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 2{{call is 'async'}}
|
|
return x
|
|
}
|
|
|
|
func awaitIf13() async throws -> Int {
|
|
let x = await if .random() { // expected-warning {{'await' has no effect on 'if' expression}}
|
|
awaitIf4() // expected-warning {{result of call to 'awaitIf4()' is unused}}
|
|
// expected-warning@-1 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-2 {{call is 'async'}}
|
|
|
|
_ = awaitIf4()
|
|
// expected-warning@-1 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-2 {{call is 'async'}}
|
|
|
|
_ = await awaitIf4() // Okay.
|
|
|
|
// Okay.
|
|
let _ = {
|
|
_ = await awaitIf4()
|
|
}
|
|
|
|
print("hello")
|
|
throw Err()
|
|
} else {
|
|
0
|
|
}
|
|
return x
|
|
}
|
|
|
|
func asyncBool() async -> Bool { true }
|
|
|
|
func awaitIf14() async -> Int {
|
|
await if asyncBool() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-3 {{call is 'async'}}
|
|
}
|
|
|
|
func awaitIf15() async -> Int {
|
|
await if await asyncBool() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'await' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func awaitIf16() async -> Int {
|
|
if asyncBool() { 0 } else { 1 }
|
|
// expected-error@-1 {{expression is 'async' but is not marked with 'await'}}
|
|
// expected-note@-2 {{call is 'async'}}
|
|
}
|
|
|
|
func awaitIf17() async -> Int {
|
|
if .random() { awaitIf4() } else { 1 }
|
|
// expected-error@-1 {{expression is 'async' but is not marked with 'await'}}
|
|
// expected-note@-2 {{call is 'async'}}
|
|
}
|
|
|
|
func awaitIf18() {
|
|
let _ = {
|
|
let _ = if .random() { await awaitIf4() } else { 1 }
|
|
}
|
|
}
|
|
|
|
func awaitIf19() async -> Int {
|
|
let x = if .random() { await awaitIf4() } else { 1 }
|
|
return x
|
|
}
|
|
|
|
func awaitIf20() async -> Int {
|
|
if .random() { await awaitIf4() } else { 1 }
|
|
}
|
|
|
|
func tryAwaitIf1() async throws -> Int {
|
|
try await if .random() { 0 } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{'await' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func tryAwaitIf2() async throws -> Int {
|
|
try await if .random() { 0 } else { 1 } as Int
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{'await' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func tryAwaitIf3() async throws -> Int {
|
|
try await if .random() { tryAwaitIf2() } else { 1 } as Int
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-3 {{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-4 {{did you mean to use 'try'?}}
|
|
// expected-note@-5 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-6 {{did you mean to disable error propagation?}}
|
|
// expected-warning@-7 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-8 {{call is 'async'}}
|
|
}
|
|
|
|
func tryAwaitIf4() async throws -> Int {
|
|
try await if .random() { try tryAwaitIf2() } else { 1 } as Int
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-3 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-4 {{call is 'async'}}
|
|
}
|
|
|
|
func tryAwaitIf5() async throws -> Int {
|
|
try await if .random() { await tryAwaitIf2() } else { 1 } as Int
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-3 {{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-4 {{did you mean to use 'try'?}}
|
|
// expected-note@-5 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-6 {{did you mean to disable error propagation?}}
|
|
}
|
|
|
|
func tryAwaitIf6() async throws -> Int {
|
|
try await if .random() { try await tryAwaitIf2() } else { 1 } as Int
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{'await' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func tryAwaitIf7() async throws -> Int {
|
|
try await if .random() { tryAwaitIf2() } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-3 {{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-4 {{did you mean to use 'try'?}}
|
|
// expected-note@-5 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-6 {{did you mean to disable error propagation?}}
|
|
// expected-warning@-7 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-8 {{call is 'async'}}
|
|
}
|
|
|
|
func tryAwaitIf8() async throws -> Int {
|
|
try await if .random() { try tryAwaitIf2() } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-3 {{expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-4 {{call is 'async'}}
|
|
}
|
|
|
|
func tryAwaitIf9() async throws -> Int {
|
|
try await if .random() { await tryAwaitIf2() } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{'await' has no effect on 'if' expression}}
|
|
// expected-warning@-3 {{call can throw but is not marked with 'try'; this is an error in the Swift 6 language mode}}
|
|
// expected-note@-4 {{did you mean to use 'try'?}}
|
|
// expected-note@-5 {{did you mean to handle error as optional value?}}
|
|
// expected-note@-6 {{did you mean to disable error propagation?}}
|
|
}
|
|
|
|
func tryAwaitIf10() async throws -> Int {
|
|
try await if .random() { try await tryAwaitIf2() } else { 1 }
|
|
// expected-warning@-1 {{'try' has no effect on 'if' expression}}
|
|
// expected-warning@-2 {{'await' has no effect on 'if' expression}}
|
|
}
|
|
|
|
func tryAwaitIf11(_ fn: () async throws -> Int) async rethrows -> Int {
|
|
do {
|
|
let x = if .random() { try await fn() } else { try await tryAwaitIf4() }
|
|
return x
|
|
} catch {
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func tryAwaitIf12(_ fn: () async throws -> Int) async rethrows -> Int {
|
|
do {
|
|
let x = if .random() { try await fn() } else { throw Err() }
|
|
return x
|
|
} catch {
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func tryAwaitIf13(_ fn: () async throws -> Int) async rethrows -> Int {
|
|
do {
|
|
let x = if .random() { try await fn() } else { try await tryAwaitIf4() }
|
|
return x
|
|
} catch {
|
|
throw error // expected-error {{a function declared 'rethrows' may only throw if its parameter does}}
|
|
}
|
|
}
|
|
|
|
func tryAwaitIf14(_ fn: () async throws -> Int) async rethrows -> Int {
|
|
do {
|
|
let x = if .random() { try await fn() } else { throw Err() }
|
|
return x
|
|
} catch {
|
|
throw error // expected-error {{a function declared 'rethrows' may only throw if its parameter does}}
|
|
}
|
|
}
|
|
|
|
func tryAwaitIf15(_ fn: () async throws -> Int) async rethrows -> Int {
|
|
do {
|
|
let x = if .random() { try await fn() } else { 0 }
|
|
return x
|
|
} catch {
|
|
throw error // Okay.
|
|
}
|
|
}
|
|
|
|
func asyncLetIf(cond: Bool, _ fn: () async throws -> Int) async throws -> Int {
|
|
async let x = if cond {
|
|
fn()
|
|
} else {
|
|
0
|
|
}
|
|
|
|
return try await x
|
|
}
|
|
|
|
struct AnyEraserP: EraserP {
|
|
init<T: EraserP>(erasing: T) {}
|
|
}
|
|
|
|
@_typeEraser(AnyEraserP)
|
|
protocol EraserP {}
|
|
struct SomeEraserP: EraserP {}
|
|
|
|
// rdar://113435870 - Make sure we allow an implicit init(erasing:) call.
|
|
dynamic func testDynamicOpaqueErase() -> some EraserP {
|
|
if .random() { SomeEraserP() } else { SomeEraserP() }
|
|
}
|
|
|
|
struct NonExhaustiveProperty {
|
|
let i = if .random() { 0 }
|
|
// expected-error@-1 {{'if' must have an unconditional 'else' to be used as expression}}
|
|
}
|
|
|
|
// MARK: Out of place if exprs
|
|
|
|
func inDefaultArg(x: Int = if .random() { 0 } else { 0 }) {}
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
func inDefaultArg2(x: Int = { (if .random() { 0 } else { 0 }) }()) {}
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
struct InType {
|
|
let inPropertyInit1 = if .random() { 0 } else { 1 }
|
|
let inPropertyInit2 = (if .random() { 0 } else { 1 })
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
let inPropertyInit3 = {
|
|
let _ = if .random() { 0 } else { 1 }
|
|
let _ = (if .random() { 0 } else { 1 })
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
func foo() {
|
|
let _ = if .random() { 0 } else { 1 }
|
|
let _ = (if .random() { 0 } else { 1 })
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
if .random() {
|
|
return if .random() { 0 } else { 1 }
|
|
} else {
|
|
return (if .random() { 0 } else { 1 })
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|
|
}
|
|
|
|
subscript(x: Int = if .random() { 0 } else { 0 }) -> Int {
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
|
|
let _ = if .random() { 0 } else { 1 }
|
|
let _ = (if .random() { 0 } else { 1 })
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func testCaptureList() {
|
|
let _ = { [x = if .random() { 0 } else { 1 }] in x }
|
|
let _ = { [x = (if .random() { 0 } else { 1 })] in x }
|
|
// expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
|
|
}
|