Olivier: I think that's one of the rare cases where fallthough is acceptable import XCTest class Tester: XCTestCase { func testit() { XCTAssertEqual("a", switchTheFallthroughOrder(foo: .a)) XCTAssertEqual("b", switchTheFallthroughOrder(foo: .b("x"))) XCTAssertEqual("c", switchTheFallthroughOrder(foo: .b("cx"))) XCTAssertEqual("c", switchTheFallthroughOrder(foo: .c)) } } Tester.defaultTestSuite.run() // Goal func Goal() -> String { switch foo { case .a: return "a" // Error: str must be bound in every pattern case .b(let str) where str.hasPrefix("c"), .c: return "c" case .b: return "b" } } // Fallthrough doesn't work func test1() -> String { switch foo { case .a: return "a" // Error: fallthrough from a case which doesn't bind variable 'str' case .c: fallthrough case .b(let str) where str.hasPrefix("c"): return "c" case .b: return "b" } } func obviousWayButNotDesired() -> String { switch foo { case .a: return "a" case .c: return "c" case .b(let str) where str.hasPrefix("c"): return "c" case .b: return "b" } } // By default, the ~= operator compares two values of the same type using the == operator. func test2() -> String { switch foo { case .a: return "a" // Error: Operator function ~= requires that Foo conform to Equatable case _ where foo ~= .c : return "c" case .b(let str) where str.hasPrefix("c"): return "c" case .b: return "b" } } /* error: macOS.playground:23:26: error: expected expression for 'where' guard of 'case' case .c(let _) where let str = "c": fallthrough ^ error: macOS.playground:23:26: error: expected ':' after 'case' case .c(let _) where let str = "c": fallthrough ^ error: macOS.playground:23:39: error: consecutive statements on a line must be separated by ';' case .c(let _) where let str = "c": fallthrough ^ ; error: macOS.playground:23:39: error: expected expression case .c(let _) where let str = "c": fallthrough ^ */ func test3() -> String { switch foo { case .a: return "a" case .c(let _) where let str = "c": fallthrough case.b(let str) where str.hasPrefix("c"): return "c" case .b: return "b" } } // Also a non-winner although it works: func alsoNotDesired() -> String { switch foo { case .a: return "a" case .b(let str) where !str.hasPrefix("c"): return "b" default: return "c" } } // Greg Titus: You can fallthrough into scopes with FEWER variables defined, so this order works: case .b(let str) where str.hasPrefix("c"): fallthrough case .c: return "c" // Suyash Srijan 10:52 AM // I think the best you can do is something like this: switch foo { case .a: return "a" case .b: guard case let .b(str) = foo, str.hasPrefix("c") else { return "b" } fallthrough case .c: return "c" }