Files
swift-mirror/test/SILGen/switch_expr.swift
Hamish Knight 19938632cd [Sema] Remove RecontextualizeClosures
Merge with ContextualizeClosuresAndMacros, and
rename to ContextualizationWalker given that it
re-contextualizes a whole bunch of AST nodes now.
This ensures we correctly handle cases such as
decls in if/switch expressions within autoclosures.
2024-12-27 14:44:56 +00:00

923 lines
25 KiB
Swift

// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types -enable-experimental-feature ThenStatements %s | %FileCheck %s
// RUN: %target-swift-emit-ir -enable-experimental-feature ThenStatements %s
// REQUIRES: swift_feature_ThenStatements
func foo() -> Int {
switch Bool.random() {
case true:
1
case false:
2
}
}
// CHECK-LABEL: sil hidden [ossa] @$s11switch_expr3fooSiyF : $@convention(thin) () -> Int
// CHECK: [[RESULT:%[0-9]+]] = alloc_stack $Int
// CHECK: switch_value {{%[0-9]+}} : $Builtin.Int1, case {{%[0-9]+}}: [[TRUEBB:bb[0-9]+]], case {{%[0-9]+}}: [[FALSEBB:bb[0-9]+]]
//
// CHECK: [[TRUEBB]]:
// CHECK: [[ONE_BUILTIN:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 1
// CHECK: [[ONE:%[0-9]+]] = apply {{%[0-9]+}}([[ONE_BUILTIN]], {{%[0-9]+}}) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
// CHECK: store [[ONE]] to [trivial] [[RESULT]] : $*Int
// CHECK: br [[EXITBB:bb[0-9]+]]
//
// CHECK: [[FALSEBB]]:
// CHECK: [[TWO_BUILTIN:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 2
// CHECK: [[TWO:%[0-9]+]] = apply {{%[0-9]+}}([[TWO_BUILTIN]], {{%[0-9]+}}) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
// CHECK: store [[TWO]] to [trivial] [[RESULT]] : $*Int
// CHECK: br [[EXITBB]]
//
// CHECK: [[EXITBB]]:
// CHECK: [[VAL:%[0-9]+]] = load [trivial] [[RESULT]] : $*Int
// CHECK: dealloc_stack [[RESULT]] : $*Int
// CHECK: return [[VAL]] : $Int
class C {}
func bar(_ x: C) -> C {
switch Bool.random() {
case true:
x
case false:
C()
}
}
// CHECK-LABEL: sil hidden [ossa] @$s11switch_expr3baryAA1CCADF : $@convention(thin) (@guaranteed C) -> @owned C
// CHECK: bb0([[CPARAM:%[0-9]+]] : @guaranteed $C):
// CHECK: [[RESULT:%[0-9]+]] = alloc_stack $C
// CHECK: switch_value {{%[0-9]+}} : $Builtin.Int1, case {{%[0-9]+}}: [[TRUEBB:bb[0-9]+]], case {{%[0-9]+}}: [[FALSEBB:bb[0-9]+]]
//
// CHECK: [[TRUEBB]]:
// CHECK: [[C:%[0-9]+]] = copy_value [[CPARAM]] : $C
// CHECK: store [[C]] to [init] [[RESULT]] : $*C
// CHECK: br [[EXITBB:bb[0-9]+]]
//
// CHECK: [[FALSEBB]]:
// CHECK: [[CTOR:%[0-9]+]] = function_ref @$s11switch_expr1CCACycfC : $@convention(method) (@thick C.Type) -> @owned C
// CHECK: [[C:%[0-9]+]] = apply [[CTOR]]({{%[0-9]+}}) : $@convention(method) (@thick C.Type) -> @owned C
// CHECK: store [[C]] to [init] [[RESULT]] : $*C
// CHECK: br [[EXITBB]]
//
// CHECK: [[EXITBB]]:
// CHECK: [[VAL:%[0-9]+]] = load [take] [[RESULT]] : $*C
// CHECK: dealloc_stack [[RESULT]] : $*C
// CHECK: return [[VAL]] : $C
struct Err: Error {}
enum E { case a, b, c }
func baz(_ e: E) throws -> Int {
switch e {
case .a:
1
case .b:
throw Err()
default:
2
}
}
// CHECK-LABEL: sil hidden [ossa] @$s11switch_expr3bazySiAA1EOKF : $@convention(thin) (E) -> (Int, @error any Error)
// CHECK: [[RESULT:%[0-9]+]] = alloc_stack $Int
// CHECK: switch_enum %0 : $E, case #E.a!enumelt: [[ABB:bb[0-9]+]], case #E.b!enumelt: [[BBB:bb[0-9]+]], default [[DEFBB:bb[0-9]+]]
//
// CHECK: [[ABB]]:
// CHECK: [[ONE_BUILTIN:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 1
// CHECK: [[ONE:%[0-9]+]] = apply {{%[0-9]+}}([[ONE_BUILTIN]], {{%[0-9]+}}) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
// CHECK: store [[ONE]] to [trivial] [[RESULT]] : $*Int
// CHECK: br [[EXITBB:bb[0-9]+]]
//
// CHECK: [[BBB]]:
// CHECK: throw {{%[0-9]+}} : $any Error
//
// CHECK: [[DEFBB]]:
// CHECK: [[TWO_BUILTIN:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 2
// CHECK: [[TWO:%[0-9]+]] = apply {{%[0-9]+}}([[TWO_BUILTIN]], {{%[0-9]+}}) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
// CHECK: store [[TWO]] to [trivial] [[RESULT]] : $*Int
// CHECK: br [[EXITBB:bb[0-9]+]]
//
// CHECK: [[EXITBB]]:
// CHECK: [[VAL:%[0-9]+]] = load [trivial] [[RESULT]] : $*Int
// CHECK: dealloc_stack [[RESULT]] : $*Int
// CHECK: return [[VAL]] : $Int
func qux() throws -> Int {
switch Bool.random() {
case true:
0
case false:
try baz(.a)
}
}
// CHECK-LABEL: sil hidden [ossa] @$s11switch_expr3quxSiyKF : $@convention(thin) () -> (Int, @error any Error)
// CHECK: [[RESULT:%[0-9]+]] = alloc_stack $Int
// CHECK: switch_value {{%[0-9]+}} : $Builtin.Int1, case {{%[0-9]+}}: [[TRUEBB:bb[0-9]+]], case {{%[0-9]+}}: [[FALSEBB:bb[0-9]+]]
//
// CHECK: [[FALSEBB]]:
// CHECK: try_apply {{%[0-9]+}}({{%[0-9]+}}) : $@convention(thin) (E) -> (Int, @error any Error), normal [[NORMALBB:bb[0-9]+]], error [[ERRORBB:bb[0-9]+]]
//
// CHECK: [[NORMALBB]]([[BAZVAL:%[0-9]+]] : $Int):
// CHECK: store [[BAZVAL]] to [trivial] [[RESULT]] : $*Int
// CHECK: br [[EXITBB:bb[0-9]+]]
//
// CHECK: [[EXITBB]]:
// CHECK: [[VAL:%[0-9]+]] = load [trivial] [[RESULT]] : $*Int
// CHECK: dealloc_stack [[RESULT]] : $*Int
// CHECK: return [[VAL]] : $Int
//
// CHECK: [[ERRORBB]]([[ERR:%[0-9]+]] : @owned $any Error):
// CHECK: dealloc_stack [[RESULT]] : $*Int
// CHECK: throw [[ERR]] : $any Error
func testFallthrough() throws -> Int {
switch Bool.random() {
case true:
if .random() { fallthrough }
throw Err()
case false:
1
}
}
// CHECK-LABEL: sil hidden [ossa] @$s11switch_expr15testFallthroughSiyKF : $@convention(thin) () -> (Int, @error any Error)
// CHECK: [[RESULT:%[0-9]+]] = alloc_stack $Int
// CHECK: switch_value {{%[0-9]+}} : $Builtin.Int1, case {{%[0-9]+}}: [[TRUEBB:bb[0-9]+]], case {{%[0-9]+}}: [[FALSEBB:bb[0-9]+]]
//
// CHECK: [[TRUEBB]]:
// CHECK: cond_br {{.*}}, [[IFTRUEBB:bb[0-9]+]], [[IFFALSEBB:bb[0-9]+]]
//
// CHECK: [[IFTRUEBB]]:
// CHECK: br [[ACTUALFALSEBB:bb[0-9]+]]
//
// CHECK: [[IFFALSEBB]]:
// CHECK: throw {{%[0-9]+}} : $any Error
//
// CHECK: [[FALSEBB]]:
// CHECK: br [[ACTUALFALSEBB]]
//
// CHECK: [[ACTUALFALSEBB]]:
// CHECK: [[ONE_BUILTIN:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 1
// CHECK: [[ONE:%[0-9]+]] = apply {{%[0-9]+}}([[ONE_BUILTIN]], {{%[0-9]+}}) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
// CHECK: store [[ONE]] to [trivial] [[RESULT]] : $*Int
// CHECK: [[VAL:%[0-9]+]] = load [trivial] [[RESULT]] : $*Int
// CHECK: dealloc_stack [[RESULT]] : $*Int
// CHECK: return [[VAL]] : $Int
func testFallthrough2() -> Int {
let x = switch Bool.random() {
case true:
fallthrough
case false:
1
}
return x
}
// CHECK-LABEL: sil hidden [ossa] @$s11switch_expr16testFallthrough2SiyF : $@convention(thin) () -> Int {
// CHECK: [[RESULT:%[0-9]+]] = alloc_stack $Int
// CHECK: switch_value {{%[0-9]+}} : $Builtin.Int1, case {{%[0-9]+}}: [[TRUEBB:bb[0-9]+]], case {{%[0-9]+}}: [[FALSEBB:bb[0-9]+]]
//
// CHECK: [[TRUEBB]]:
// CHECK-NEXT: br [[ENDBB:bb[0-9]+]]
//
// CHECK: [[FALSEBB]]:
// CHECK-NEXT: br [[ENDBB]]
//
// CHECK: [[ENDBB]]:
// CHECK: [[ONELIT:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 1
// CHECK: [[ONE:%[0-9]+]] = apply {{%[0-9]+}}([[ONELIT]], {{%[0-9]+}})
// CHECK: store [[ONE]] to [trivial] [[RESULT]] : $*Int
// CHECK: [[VAL:%[0-9]+]] = load [trivial] [[RESULT]] : $*Int
// CHECK: [[VAL_RESULT:%[0-9]+]] = move_value [var_decl] [[VAL]] : $Int
// CHECK: dealloc_stack [[RESULT]] : $*Int
// CHECK: return [[VAL_RESULT:[%0-9]+]] : $Int
func testFallthrough3() throws -> Int {
switch Bool.random() {
case true:
switch Bool.random() {
case true:
if .random() {
fallthrough
}
throw Err()
case false:
1
}
case false:
0
}
}
func testClosure() throws -> Int {
let fn = {
switch Bool.random() {
case true:
0
case false:
try baz(.a)
}
}
return try fn()
}
// CHECK-LABEL: sil private [ossa] @$s11switch_expr11testClosureSiyKFSiyKcfU_ : $@convention(thin) () -> (Int, @error any Error)
// CHECK: [[RESULT:%[0-9]+]] = alloc_stack $Int
// CHECK: switch_value {{%[0-9]+}} : $Builtin.Int1, case {{%[0-9]+}}: [[TRUEBB:bb[0-9]+]], case {{%[0-9]+}}: [[FALSEBB:bb[0-9]+]]
//
// CHECK: [[FALSEBB]]:
// CHECK: try_apply {{%[0-9]+}}({{%[0-9]+}}) : $@convention(thin) (E) -> (Int, @error any Error), normal [[NORMALBB:bb[0-9]+]], error [[ERRORBB:bb[0-9]+]]
//
// CHECK: [[NORMALBB]]([[BAZVAL:%[0-9]+]] : $Int):
// CHECK: store [[BAZVAL]] to [trivial] [[RESULT]] : $*Int
// CHECK: br [[EXITBB:bb[0-9]+]]
//
// CHECK: [[EXITBB]]:
// CHECK: [[VAL:%[0-9]+]] = load [trivial] [[RESULT]] : $*Int
// CHECK: dealloc_stack [[RESULT]] : $*Int
// CHECK: return [[VAL]] : $Int
//
// CHECK: [[ERRORBB]]([[ERR:%[0-9]+]] : @owned $any Error):
// CHECK: dealloc_stack [[RESULT]] : $*Int
// CHECK: throw [[ERR]] : $any Error
func testVar1() -> Int {
let x = switch Bool.random() {
case let b where b == true:
1
case false:
0
default:
2
}
return x
}
func testVar2() -> Int {
let x = switch Bool.random() {
case let b where b == true:
1
case false:
0
default:
2
}
return x
}
func testCatch() -> Int {
do {
let x = switch Bool.random() {
case true:
0
case false:
throw Err()
}
return x
} catch {
return 0
}
}
struct TestPropertyInit {
var x = switch Bool.random() {
case let b where b == true:
1
case false:
0
default:
2
}
lazy var y = switch Bool.random() {
case let b where b == true:
1
case false:
0
default:
2
}
}
// https://github.com/swiftlang/swift/issues/75294
func testAsyncLet(_ x: Int?) async {
async let _ = switch x { case let i?: i default: 0 }
// CHECK-LABEL: sil private [ossa] @$s11switch_expr12testAsyncLetyySiSgYaFSiyYaYbcfu_ : $@convention(thin) @Sendable @async @substituted <τ_0_0> (Optional<Int>) -> (@out τ_0_0, @error any Error) for <Int>
}
func testNested(_ e: E) throws -> Int {
switch e {
case .a:
1
default:
switch e {
case .b:
throw Err()
default:
2
}
}
}
// CHECK-LABEL: sil hidden [ossa] @$s11switch_expr10testNestedySiAA1EOKF : $@convention(thin) (E) -> (Int, @error any Error)
// CHECK: [[RESULT:%[0-9]+]] = alloc_stack $Int
// CHECK: switch_enum %0 : $E, case #E.a!enumelt: [[ABB:bb[0-9]+]], default [[DEFBB:bb[0-9]+]]
//
// CHECK: [[ABB]]:
// CHECK: [[ONE_BUILTIN:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 1
// CHECK: [[ONE:%[0-9]+]] = apply {{%[0-9]+}}([[ONE_BUILTIN]], {{%[0-9]+}}) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
// CHECK: store [[ONE]] to [trivial] [[RESULT]] : $*Int
// CHECK: br [[EXITBB:bb[0-9]+]]
//
// CHECK: [[DEFBB]]({{.*}}):
// CHECK: [[NESTEDRESULT:%[0-9]+]] = alloc_stack $Int
// CHECK: switch_enum %0 : $E, case #E.b!enumelt: [[BBB:bb[0-9]+]], default [[NESTEDDEFBB:bb[0-9]+]]
// CHECK: [[BBB]]:
// CHECK: throw {{%[0-9]+}} : $any Error
//
// CHECK: [[NESTEDDEFBB]]({{.*}}):
// CHECK: [[TWO_BUILTIN:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 2
// CHECK: [[TWO:%[0-9]+]] = apply {{%[0-9]+}}([[TWO_BUILTIN]], {{%[0-9]+}}) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
// CHECK: store [[TWO]] to [trivial] [[NESTEDRESULT]] : $*Int
// CHECK: [[TMP:%[0-9]+]] = load [trivial] [[NESTEDRESULT]] : $*Int
// CHECK: store [[TMP]] to [trivial] [[RESULT]] : $*Int
// CHECK: br [[EXITBB:bb[0-9]+]]
//
// CHECK: [[EXITBB]]:
// CHECK: [[VAL:%[0-9]+]] = load [trivial] [[RESULT]] : $*Int
// CHECK: dealloc_stack [[RESULT]] : $*Int
// CHECK: return [[VAL]] : $Int
func testPoundIf1() -> Int {
let x = switch Bool.random() {
case true:
#if true
1
#else
""
#endif
case false:
#if false
""
#else
2
#endif
}
return x
}
func testPoundIf2() -> Int {
switch Bool.random() {
case true:
#if false
0
#else
#if true
switch Bool.random() { case true: 0 case false: 1 }
#endif
#endif
case false:
#if true
switch Bool.random() { case true: 0 case false: 1 }
#endif
}
}
func testAssignment() {
var x = 0
x = switch Bool.random() { case true: 0 case false: 1 }
let fn = {
x = switch Bool.random() { case true: 0 case false: 1 }
}
}
func nestedType() throws -> Int {
switch Bool.random() {
case true:
struct S: Error {}
throw S()
case false:
0
}
}
// MARK: Bindings
enum F {
case e(Int)
}
struct S {
var i: Int
var opt: Int?
var computed: Int {
get { i }
set { i = newValue }
}
var coroutined: Int {
_read { yield i }
_modify { yield &i }
}
subscript(x: Int) -> Int {
get { i }
set { i = newValue }
}
mutating func testAssign1(_ x: F) {
i = switch x {
case .e(let y): y
}
}
mutating func testAssign2(_ x: F) {
i = switch x {
case .e(let y): Int(y)
}
}
func testAssign3(_ x: F) {
var i = 0
i = switch x {
case .e(let y): y
}
_ = i
}
func testAssign4(_ x: F) {
var i = 0
let _ = {
i = switch x {
case .e(let y): y
}
}
_ = i
}
mutating func testAssign5(_ x: F) {
i = switch Bool.random() {
case true:
switch x {
case .e(let y): y
}
case let z:
z ? 0 : 1
}
}
mutating func testAssign6(_ x: F) {
i = switch x {
case .e(let y):
switch Bool.random() {
case true: y
case false: y
}
}
}
func testReturn1(_ x: F) -> Int {
switch x {
case .e(let y): y
}
}
func testReturn2(_ x: F) -> Int {
return switch x {
case .e(let y): y
}
}
func testReturn3(_ x: F) -> Int {
{
switch x {
case .e(let y): y
}
}()
}
func testReturn4(_ x: F) -> Int {
return {
switch x {
case .e(let y): y
}
}()
}
func testBinding1(_ x: F) -> Int {
let i = switch x {
case .e(let y): y
}
return i
}
func testBinding2(_ x: F) -> Int {
let i = {
switch x {
case .e(let y): y
}
}()
return i
}
}
enum G {
case e(Int)
case f
}
struct TestLValues {
var s: S
var opt: S?
var optopt: S??
mutating func testOptPromote1() {
opt = switch Bool.random() { case true: s case false: s }
}
mutating func testOptPromote2() {
optopt = switch Bool.random() { case true: s case false: s }
}
mutating func testStored1() {
s.i = switch Bool.random() { case true: 1 case false: 0 }
}
mutating func testStored2() throws {
s.i = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testComputed1() {
s.computed = switch Bool.random() { case true: 1 case false: 0 }
}
mutating func testComputed2() throws {
s.computed = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testCoroutined1() {
s.coroutined = switch Bool.random() { case true: 1 case false: 0 }
}
mutating func testCoroutined2() throws {
s.coroutined = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testOptionalChain1() {
opt?.i = switch Bool.random() { case true: 1 case false: 0 }
}
mutating func testOptionalChain2() throws {
opt?.i = switch Bool.random() { case true: throw Err() case false: 0 }
}
mutating func testOptionalChain3(_ g: G) {
opt?.i = switch g { case .e(let i): i default: 0 }
}
mutating func testOptionalChain4(_ g: G) throws {
opt?.i = switch g { case .e(let i): i default: throw Err() }
}
mutating func testOptionalChain5(_ g: G) throws {
opt?.computed = switch g { case .e(let i): i default: throw Err() }
}
mutating func testOptionalChain6(_ g: G) throws {
opt?.coroutined = switch g { case .e(let i): i default: throw Err() }
}
mutating func testOptionalChain7() throws {
optopt??.i = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testOptionalChain8() throws {
optopt??.opt = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testOptionalChain9() throws {
optopt??.opt? = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testOptionalForce1() throws {
opt!.i = switch Bool.random() { case true: throw Err() case false: 0 }
}
mutating func testOptionalForce2() throws {
opt!.computed = switch Bool.random() { case true: throw Err() case false: 0 }
}
mutating func testOptionalForce3(_ g: G) throws {
opt!.coroutined = switch g { case .e(let i): i default: throw Err() }
}
mutating func testOptionalForce4() throws {
optopt!!.i = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testOptionalForce5() throws {
optopt!!.opt = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testOptionalForce6() throws {
optopt!!.opt! = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testSubscript1() throws {
s[5] = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testSubscript2() throws {
opt?[5] = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testSubscript3() throws {
opt![5] = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testKeyPath1(_ kp: WritableKeyPath<S, Int>) throws {
s[keyPath: kp] = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testKeyPath2(_ kp: WritableKeyPath<S, Int>) throws {
opt?[keyPath: kp] = switch Bool.random() { case true: 1 case false: throw Err() }
}
mutating func testKeyPath3(_ kp: WritableKeyPath<S, Int>) throws {
opt![keyPath: kp] = switch Bool.random() { case true: 1 case false: throw Err() }
}
}
func exprPatternInClosure() {
let f: (Int) -> Void = { i in
switch i {
case i:
()
default:
()
}
}
}
func testNeverSwitch1() {
let x = switch fatalError() {}
return x
}
func testNeverSwitch2() -> Never {
let x = switch fatalError() {
case let x: x
}
return x
}
func testNeverSwitch3() -> Int {
let x = switch fatalError() {
case fatalError(): 0
case _ where .random(): 1
default: 2
}
return x
}
func testNeverSwitch4() {
let x: Void
x = switch fatalError() {}
return x
}
func testNeverSwitch5() -> Never {
let x: Never
x = switch fatalError() {
case let x: x
}
return x
}
func testNeverSwitch6() -> Int {
let x: Int
x = switch fatalError() {
case fatalError(): 0
case _ where .random(): 1
default: 2
}
return x
}
func testNeverSwitch7() {
let _ = switch fatalError() {}
let _ = switch fatalError() { case let x: x }
let _ = switch fatalError() { default: "" }
}
func testNeverSwitch8() {
let _ = switch fatalError() { default: C() }
}
func testNeverSwitch9() {
let i = switch Bool.random() {
case true:
switch fatalError() {}
case false:
switch fatalError() {}
}
return i
}
func testNeverSwitch10() -> Never {
switch fatalError() {}
}
func testNeverSwitch11() {
return switch fatalError() {}
}
func testNeverSwitch12() -> Never {
return switch fatalError() { case let x: x }
}
func testNeverSwitch13() {
return switch fatalError() { case let x: x }
}
extension Never {
init(value: Self) {
self = switch value { case let v: v }
}
}
func testNever5() -> Int {
switch Bool.random() {
case true:
fatalError()
case false:
0
}
}
// CHECK-LABEL: sil hidden [ossa] @$s11switch_expr10testNever5SiyF : $@convention(thin) () -> Int
// CHECK: [[RESULT:%[0-9]+]] = alloc_stack $Int
// CHECK: switch_value {{.*}}, case {{%[0-9]+}}: [[BB_TRUE:bb[0-9]+]], case {{%[0-9]+}}: [[BB_FALSE:bb[0-9]+]]
//
// CHECK: [[BB_TRUE]]:
// CHECK: function_ref fatalError(_:file:line:)
// CHECK: unreachable
//
// CHECK: [[BB_FALSE]]:
// CHECK: store {{%[0-9]+}} to [trivial] [[RESULT]] : $*Int
// CHECK: [[RET:%[0-9]+]] = load [trivial] [[RESULT]] : $*Int
// CHECK: dealloc_stack [[RESULT]] : $*Int
// CHECK: return [[RET]]
func never() -> Never { fatalError() }
func testNever6() -> Int {
switch Bool.random() {
case true:
never()
case false:
0
}
}
func neverTuple() -> (Never, Int) { fatalError() }
func testNever7() -> (Never, Int) {
switch Bool.random() {
case true:
neverTuple()
case false:
(never(), 0)
}
}
// CHECK-LABEL: sil hidden [ossa] @$s11switch_expr10testNever7s5NeverO_SityF : $@convention(thin) () -> (Never, Int)
// CHECK: [[RESULT:%[0-9]+]] = alloc_stack $(Never, Int)
// CHECK: switch_value {{.*}}, case {{%[0-9]+}}: [[BB_TRUE:bb[0-9]+]], case {{%[0-9]+}}: [[BB_FALSE:bb[0-9]+]]
//
// CHECK: [[BB_TRUE]]:
// CHECK: [[ELT_0:%[0-9]+]] = tuple_element_addr [[RESULT]] : $*(Never, Int), 0
// CHECK: [[ELT_1:%[0-9]+]] = tuple_element_addr [[RESULT]] : $*(Never, Int), 1
// CHECK: ([[RET_0:%[0-9]+]], [[RET_1:%[0-9]+]]) = destructure_tuple {{%[0-9]+}} : $(Never, Int)
// CHECK: store [[RET_0]] to [trivial] [[ELT_0]] : $*Never
// CHECK: store [[RET_1]] to [trivial] [[ELT_1]] : $*Int
// CHECK: br [[BB_EXIT:bb[0-9]+]]
//
// CHECK: [[BB_FALSE]]:
// CHECK: [[ELT_0:%[0-9]+]] = tuple_element_addr [[RESULT]] : $*(Never, Int), 0
// CHECK: [[ELT_1:%[0-9]+]] = tuple_element_addr [[RESULT]] : $*(Never, Int), 1
// CHECK: store {{%[0-9]+}} to [trivial] [[ELT_0]] : $*Never
// CHECK: store {{%[0-9]+}} to [trivial] [[ELT_1]] : $*Int
// CHECK: br [[BB_EXIT:bb[0-9]+]]
//
// CHECK: [[BB_EXIT]]:
// CHECK: dealloc_stack [[RESULT]] : $*(Never, Int)
// CHECK: [[RET:%[0-9]+]] = tuple ({{%[0-9]+}} : $Never, {{%[0-9]+}} : $Int)
// CHECK: return [[RET]]
func testCaptureList() -> Int {
let fn = { [x = switch Bool.random() { case true: 0 case false: 1 }] in x }
return fn()
}
// https://github.com/apple/swift/issues/68764
func testConditionalCast<T>(_ x: Any, _ y: Int) -> T? {
switch y {
default:
x as? T
}
}
@propertyWrapper
struct Wrapper<T> {
var wrappedValue: T
}
// rdar://119158202 - Make sure we correctly contextualize local bindings.
func testLazyLocal(_ x: Int?) {
// CHECK-LABEL: sil private [lazy_getter] [noinline] [ossa] @$s11switch_expr13testLazyLocalyySiSgF1aL_Sivg : $@convention(thin) (@guaranteed { var Optional<Int> }, Optional<Int>) -> Int
lazy var a = switch x { case let x?: x case nil: 0 }
_ = a
// CHECK-LABEL: sil private [lazy_getter] [noinline] [ossa] @$s11switch_expr13testLazyLocalyySiSgF1bL_SSvg : $@convention(thin) (@guaranteed { var Optional<String> }) -> @owned String
lazy var b = switch Bool.random() {
case true:
let x = ""
then x
case false:
""
}
_ = b
// CHECK-LABEL: sil private [lazy_getter] [noinline] [ossa] @$s11switch_expr13testLazyLocalyySiSgF1cL_SSvg : $@convention(thin) (@guaranteed { var Optional<String> }) -> @owned String
lazy var c = switch Bool.random() {
case true:
// CHECK-LABEL: sil private [lazy_getter] [noinline] [ossa] @$s11switch_expr13testLazyLocalyySiSgF1cL_SSvg1xL3_SSvg : $@convention(thin) (@guaranteed { var Optional<String> }) -> @owned String
lazy var x = ""
then x
case false:
""
}
_ = c
// CHECK-LABEL: sil private [lazy_getter] [noinline] [ossa] @$s11switch_expr13testLazyLocalyySiSgF1dL_Sivg : $@convention(thin) (@guaranteed { var Optional<Int> }, Optional<Int>) -> Int
lazy var d = switch Bool.random() {
case true:
// CHECK-LABEL: sil private [lazy_getter] [noinline] [ossa] @$s11switch_expr13testLazyLocalyySiSgF1dL_Sivg1yL_Sivg : $@convention(thin) (@guaranteed { var Optional<Int> }, Optional<Int>) -> Int
lazy var y = switch x { case let x?: x case nil: 0 }
then y
case false:
0
}
_ = d
// CHECK-LABEL: sil private [lazy_getter] [noinline] [ossa] @$s11switch_expr13testLazyLocalyySiSgF1eL_Sivg : $@convention(thin) (@guaranteed { var Optional<Int> }) -> Int
lazy var e = switch Bool.random() {
case true:
@Wrapper
var x = 0
then x
case false:
0
}
_ = e
// CHECK-LABEL: sil private [lazy_getter] [noinline] [ossa] @$s11switch_expr13testLazyLocalyySiSgF1fL_Sivg : $@convention(thin) (@guaranteed { var Optional<Int> }) -> Int
lazy var f = switch 0 {
case 1:
1
default:
0
}
_ = f
}
struct LazyProp {
var a: Int?
// CHECK-LABEL: sil hidden [lazy_getter] [noinline] [ossa] @$s11switch_expr8LazyPropV1bSivg : $@convention(method) (@inout LazyProp) -> Int
lazy var b = switch a { case let a?: a case nil: 0 }
// CHECK-LABEL: sil hidden [lazy_getter] [noinline] [ossa] @$s11switch_expr8LazyPropV1cSivg : $@convention(method) (@inout LazyProp) -> Int
lazy var c = switch Bool.random() {
case true:
// CHECK-LABEL: sil private [lazy_getter] [noinline] [ossa] @$s11switch_expr8LazyPropV1cSivg1xL_Sivg : $@convention(thin) (@guaranteed { var Optional<Int> }) -> Int
lazy var x = 0
then x
case false:
0
}
// CHECK-LABEL: sil hidden [lazy_getter] [noinline] [ossa] @$s11switch_expr8LazyPropV1dSivg : $@convention(method) (@inout LazyProp) -> Int
lazy var d = switch Bool.random() {
case true:
// CHECK-LABEL: sil private [lazy_getter] [noinline] [ossa] @$s11switch_expr8LazyPropV1dSivg1xL_Sivg : $@convention(thin) (@guaranteed { var Optional<Int> }, @inout_aliasable LazyProp) -> Int
lazy var x = switch a { case let a?: a case nil: 0 }
then x
case false:
0
}
}