blob: 24c0200ba67f2f22ced5dee2a4cce2fb4518cdf1 [file] [log] [blame]
// RUN: %target-typecheck-verify-swift
func foo(a: Int?, b: Int?) -> Int {
switch (a, b) {
case (.none, _): return 1
case (_, .none): return 2
case (.some(_), .some(_)): return 3
}
}
func bar(a: Bool, b: Bool) -> Int {
switch (a, b) {
case (false, false):
return 1
case (true, _):
return 2
case (false, true):
return 3
}
}
enum Result<T> {
case Ok(T)
case Error(Error)
func shouldWork<U>(other: Result<U>) -> Int {
switch (self, other) { // No warning
case (.Ok, .Ok): return 1
case (.Error, .Error): return 2
case (.Error, _): return 3
case (_, .Error): return 4
}
}
}
enum Foo {
case A(Int)
case B(Int)
}
func foo() {
switch (Foo.A(1), Foo.B(1)) {
case (.A(_), .A(_)):
()
case (.B(_), _):
()
case (_, .B(_)):
()
}
}
class C {}
enum Bar {
case TheCase(C?)
}
func test(f: Bar) -> Bool {
switch f {
case .TheCase(_?):
return true
case .TheCase(nil):
return false
}
}
func op(this : Optional<Bool>, other : Optional<Bool>) -> Optional<Bool> {
switch (this, other) { // No warning
case let (.none, w):
return w
case let (w, .none):
return w
case let (.some(e1), .some(e2)):
return .some(e1 && e2)
}
}
enum Threepeat {
case a, b, c
}
func test3(x: Threepeat, y: Threepeat) {
switch (x, y) { // expected-error {{switch must be exhaustive}}
// expected-note@-1 {{add missing case: '(.a, .c)'}}
case (.a, .a):
()
case (.b, _):
()
case (.c, _):
()
case (_, .b):
()
}
}
enum A {
case A(Int)
case B(Bool)
case C
case D
}
enum B {
case A
case B
}
func s(a: A, b: B) {
switch (a, b) {
case (.A(_), .A):
break
case (.A(_), .B):
break
case (.B(_), let b):
// expected-warning@-1 {{immutable value 'b' was never used; consider replacing with '_' or removing it}}
break
case (.C, _), (.D, _):
break
}
}
enum Grimble {
case A
case B
case C
}
enum Gromble {
case D
case E
}
func doSomething(foo:Grimble, bar:Gromble) {
switch(foo, bar) { // No warning
case (.A, .D):
break
case (.A, .E):
break
case (.B, _):
break
case (.C, _):
break
}
}
enum E {
case A
case B
}
func f(l: E, r: E) {
switch (l, r) {
case (.A, .A):
return
case (.A, _):
return
case (_, .A):
return
case (.B, .B):
return
}
}
enum TestEnum {
case A, B
}
func switchOverEnum(testEnumTuple: (TestEnum, TestEnum)) {
switch testEnumTuple {
case (_,.B):
// Matches (.A, .B) and (.B, .B)
break
case (.A,_):
// Matches (.A, .A)
// Would also match (.A, .B) but first case takes precedent
break
case (.B,.A):
// Matches (.B, .A)
break
}
}
func tests(a: Int?, b: String?) {
switch (a, b) {
case let (.some(n), _): print("a: ", n, "?")
case (.none, _): print("Nothing", "?")
}
switch (a, b) {
case let (.some(n), .some(s)): print("a: ", n, "b: ", s)
case let (.some(n), .none): print("a: ", n, "Nothing")
case (.none, _): print("Nothing")
}
switch (a, b) {
case let (.some(n), .some(s)): print("a: ", n, "b: ", s)
case let (.some(n), .none): print("a: ", n, "Nothing")
case let (.none, .some(s)): print("Nothing", "b: ", s)
case (.none, _): print("Nothing", "?")
}
switch (a, b) {
case let (.some(n), .some(s)): print("a: ", n, "b: ", s)
case let (.some(n), .none): print("a: ", n, "Nothing")
case let (.none, .some(s)): print("Nothing", "b: ", s)
case (.none, .none): print("Nothing", "Nothing")
}
}
enum X {
case Empty
case A(Int)
case B(Int)
}
func f(a: X, b: X) {
switch (a, b) {
case (_, .Empty): ()
case (.Empty, _): ()
case (.A, .A): ()
case (.B, .B): ()
case (.A, .B): ()
case (.B, .A): ()
}
}
func f2(a: X, b: X) {
switch (a, b) {
case (.A, .A): ()
case (.B, .B): ()
case (.A, .B): ()
case (.B, .A): ()
case (_, .Empty): ()
case (.Empty, _): ()
case (.A, .A): () // expected-warning {{case is already handled by previous patterns; consider removing it}}
case (.B, .B): () // expected-warning {{case is already handled by previous patterns; consider removing it}}
case (.A, .B): () // expected-warning {{case is already handled by previous patterns; consider removing it}}
case (.B, .A): () // expected-warning {{case is already handled by previous patterns; consider removing it}}
default: ()
}
}
enum XX : Int {
case A
case B
case C
case D
case E
}
func switcheroo(a: XX, b: XX) -> Int {
switch(a, b) { // No warning
case (.A, _) : return 1
case (_, .A) : return 2
case (.C, _) : return 3
case (_, .C) : return 4
case (.B, .B) : return 5
case (.B, .D) : return 6
case (.D, .B) : return 7
case (.B, .E) : return 8
case (.E, .B) : return 9
case (.E, _) : return 10
case (_, .E) : return 11
case (.D, .D) : return 12
default:
print("never hits this:", a, b)
return 13
}
}
enum PatternCasts {
case one(Any)
case two
}
func checkPatternCasts() {
// Pattern casts with this structure shouldn't warn about duplicate cases.
let x: PatternCasts = .one("One")
switch x {
case .one(let s as String): print(s)
case .one: break
case .two: break
}
// But should warn here.
switch x {
case .one(_): print(s)
case .one: break // expected-warning {{case is already handled by previous patterns; consider removing it}}
case .two: break
}
}
enum Runcible {
case spoon
case hat
case fork
}
func checkDiagnosticMinimality(x: Runcible?) {
switch (x!, x!) { // expected-error {{switch must be exhaustive}}
// expected-note@-1 {{add missing case: '(.fork, _)'}}
// expected-note@-2 {{add missing case: '(.hat, .hat)'}}
// expected-note@-3 {{add missing case: '(.hat, .fork)'}}
// expected-note@-4 {{add missing case: '(_, .fork)'}}
case (.spoon, .spoon):
break
case (.spoon, .hat):
break
case (.hat, .spoon):
break
}
switch (x!, x!) { // expected-error {{switch must be exhaustive}}
// expected-note@-1 {{add missing case: '(.fork, _)'}}
// expected-note@-2 {{add missing case: '(.hat, .spoon)'}}
// expected-note@-3 {{add missing case: '(.hat, .fork)'}}
// expected-note@-4 {{add missing case: '(.spoon, .hat)'}}
// expected-note@-5 {{add missing case: '(.spoon, .fork)'}}
// expected-note@-6 {{add missing case: '(_, .fork)'}}
case (.spoon, .spoon):
break
case (.hat, .hat):
break
}
}
enum LargeSpaceEnum {
case case0
case case1
case case2
case case3
case case4
case case5
case case6
case case7
case case8
case case9
case case10
}
func notQuiteBigEnough() -> Bool {
switch (LargeSpaceEnum.case1, LargeSpaceEnum.case2) { // expected-error {{switch must be exhaustive}}
// expected-note@-1 110 {{add missing case:}}
case (.case0, .case0): return true
case (.case1, .case1): return true
case (.case2, .case2): return true
case (.case3, .case3): return true
case (.case4, .case4): return true
case (.case5, .case5): return true
case (.case6, .case6): return true
case (.case7, .case7): return true
case (.case8, .case8): return true
case (.case9, .case9): return true
case (.case10, .case10): return true
}
}
enum OverlyLargeSpaceEnum {
case case0
case case1
case case2
case case3
case case4
case case5
case case6
case case7
case case8
case case9
case case10
case case11
}
func quiteBigEnough() -> Bool {
switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) { // expected-error {{switch must be exhaustive}}
// expected-note@-1 {{do you want to add a default clause?}}
case (.case0, .case0): return true
case (.case1, .case1): return true
case (.case2, .case2): return true
case (.case3, .case3): return true
case (.case4, .case4): return true
case (.case5, .case5): return true
case (.case6, .case6): return true
case (.case7, .case7): return true
case (.case8, .case8): return true
case (.case9, .case9): return true
case (.case10, .case10): return true
case (.case11, .case11): return true
}
// No diagnostic
switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) { // expected-error {{switch must be exhaustive}}
// expected-note@-1 {{do you want to add a default clause?}}
case (.case0, _): return true
case (.case1, _): return true
case (.case2, _): return true
case (.case3, _): return true
case (.case4, _): return true
case (.case5, _): return true
case (.case6, _): return true
case (.case7, _): return true
case (.case8, _): return true
case (.case9, _): return true
case (.case10, _): return true
}
// No diagnostic
switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) {
case (.case0, _): return true
case (.case1, _): return true
case (.case2, _): return true
case (.case3, _): return true
case (.case4, _): return true
case (.case5, _): return true
case (.case6, _): return true
case (.case7, _): return true
case (.case8, _): return true
case (.case9, _): return true
case (.case10, _): return true
case (.case11, _): return true
}
// No diagnostic
switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) {
case (_, .case0): return true
case (_, .case1): return true
case (_, .case2): return true
case (_, .case3): return true
case (_, .case4): return true
case (_, .case5): return true
case (_, .case6): return true
case (_, .case7): return true
case (_, .case8): return true
case (_, .case9): return true
case (_, .case10): return true
case (_, .case11): return true
}
// No diagnostic
switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) {
case (_, _): return true
}
// No diagnostic
switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) {
case (.case0, .case0): return true
case (.case1, .case1): return true
case (.case2, .case2): return true
case (.case3, .case3): return true
case _: return true
}
}
indirect enum InfinitelySized {
case one
case two
case recur(InfinitelySized)
case mutualRecur(MutuallyRecursive, InfinitelySized)
}
indirect enum MutuallyRecursive {
case one
case two
case recur(MutuallyRecursive)
case mutualRecur(InfinitelySized, MutuallyRecursive)
}
func infinitelySized() -> Bool {
switch (InfinitelySized.one, InfinitelySized.one) { // expected-error {{switch must be exhaustive}}
// expected-note@-1 10 {{add missing case:}}
case (.one, .one): return true
case (.two, .two): return true
}
switch (MutuallyRecursive.one, MutuallyRecursive.one) { // expected-error {{switch must be exhaustive}}
// expected-note@-1 10 {{add missing case:}}
case (.one, .one): return true
case (.two, .two): return true
}
}