// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types -parse-as-library %s | %FileCheck %s enum Boolish { case falsy case truthy } // CHECK-LABEL: sil hidden [ossa] @$s4enum13Boolish_casesyyF func Boolish_cases() { // CHECK: [[BOOLISH:%[0-9]+]] = metatype $@thin Boolish.Type // CHECK-NEXT: [[FALSY:%[0-9]+]] = enum $Boolish, #Boolish.falsy!enumelt // CHECK-NEXT: ignored_use _ = Boolish.falsy // CHECK-NEXT: [[BOOLISH:%[0-9]+]] = metatype $@thin Boolish.Type // CHECK-NEXT: [[TRUTHY:%[0-9]+]] = enum $Boolish, #Boolish.truthy!enumelt _ = Boolish.truthy } enum Optionable { case nought case mere(Int) } // CHECK-LABEL: sil hidden [ossa] @$s4enum16Optionable_casesyySiF func Optionable_cases(_ x: Int) { // CHECK: [[METATYPE:%.*]] = metatype $@thin Optionable.Type // CHECK: [[FN:%.*]] = function_ref @$s4enum16Optionable_casesyySiFAA0B0OSicADmcfu_ _ = Optionable.mere // CHECK: [[METATYPE:%.*]] = metatype $@thin Optionable.Type // CHECK: [[RES:%.*]] = enum $Optionable, #Optionable.mere!enumelt, %0 : $Int _ = Optionable.mere(x) } // CHECK-LABEL: sil private [ossa] @$s4enum16Optionable_casesyySiFAA0B0OSicADmcfu_ : $@convention(thin) (@thin Optionable.Type) -> @owned @callee_guaranteed (Int) -> Optionable // CHECK-LABEL: sil private [ossa] @$s4enum16Optionable_casesyySiFAA0B0OSicADmcfu_ADSicfu0_ : $@convention(thin) (Int, @thin Optionable.Type) -> Optionable { protocol P {} struct S : P {} enum AddressOnly { case nought case mere(P) case phantom(S) } // CHECK-LABEL: sil hidden [ossa] @$s4enum17AddressOnly_casesyyAA1SVF func AddressOnly_cases(_ s: S) { // CHECK: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type // CHECK: [[FN:%.*]] = function_ref @$s4enum17AddressOnly_casesyyAA1SVFAA0bC0OAA1P_pcAFmcfu_ // CHECK-NEXT: [[CTOR:%.*]] = apply [[FN]]([[METATYPE]]) // CHECK-NEXT: ignored_use // CHECK-NEXT: destroy_value [[CTOR]] _ = AddressOnly.mere // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type // CHECK-NEXT: [[NOUGHT:%.*]] = alloc_stack $AddressOnly // CHECK-NEXT: inject_enum_addr [[NOUGHT]] // CHECK-NEXT: ignored_use // CHECK-NEXT: destroy_addr [[NOUGHT]] // CHECK-NEXT: dealloc_stack [[NOUGHT]] _ = AddressOnly.nought // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type // CHECK-NEXT: [[MERE:%.*]] = alloc_stack $AddressOnly // CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[MERE]] // CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = init_existential_addr [[PAYLOAD]] // CHECK-NEXT: store %0 to [trivial] [[PAYLOAD_ADDR]] // CHECK-NEXT: inject_enum_addr [[MERE]] // CHECK-NEXT: ignored_use // CHECK-NEXT: destroy_addr [[MERE]] // CHECK-NEXT: dealloc_stack [[MERE]] _ = AddressOnly.mere(s) // Address-only enum vs loadable payload // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type // CHECK-NEXT: [[PHANTOM:%.*]] = alloc_stack $AddressOnly // CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[PHANTOM]] : $*AddressOnly, #AddressOnly.phantom!enumelt // CHECK-NEXT: store %0 to [trivial] [[PAYLOAD]] // CHECK-NEXT: inject_enum_addr [[PHANTOM]] : $*AddressOnly, #AddressOnly.phantom!enumelt // CHECK-NEXT: ignored_use // CHECK-NEXT: destroy_addr [[PHANTOM]] // CHECK-NEXT: dealloc_stack [[PHANTOM]] _ = AddressOnly.phantom(s) // CHECK: return } enum PolyOptionable { case nought case mere(T) } // CHECK-LABEL: sil hidden [ossa] @$s4enum20PolyOptionable_casesyyxlF func PolyOptionable_cases(_ t: T) { // CHECK: [[METATYPE:%.*]] = metatype $@thin PolyOptionable.Type // CHECK-NEXT: [[NOUGHT:%.*]] = alloc_stack $PolyOptionable // CHECK-NEXT: inject_enum_addr [[NOUGHT]] // CHECK-NEXT: ignored_use // CHECK-NEXT: destroy_addr [[NOUGHT]] // CHECK-NEXT: dealloc_stack [[NOUGHT]] _ = PolyOptionable.nought // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin PolyOptionable.Type // CHECK-NEXT: [[MERE:%.*]] = alloc_stack $PolyOptionable // CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[MERE]] // CHECK-NEXT: copy_addr %0 to [init] [[PAYLOAD]] : $*T // CHECK-NEXT: inject_enum_addr [[MERE]] // CHECK-NEXT: ignored_use // CHECK-NEXT: destroy_addr [[MERE]] // CHECK-NEXT: dealloc_stack [[MERE]] _ = PolyOptionable.mere(t) // CHECK-NOT: destroy_addr %0 // CHECK: return } // The substituted type is loadable and trivial here // CHECK-LABEL: sil hidden [ossa] @$s4enum32PolyOptionable_specialized_casesyySiF func PolyOptionable_specialized_cases(_ t: Int) { // CHECK: [[METATYPE:%.*]] = metatype $@thin PolyOptionable.Type // CHECK-NEXT: [[NOUGHT:%.*]] = enum $PolyOptionable, #PolyOptionable.nought!enumelt // CHECK-NEXT: ignored_use _ = PolyOptionable.nought // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin PolyOptionable.Type // CHECK-NEXT: [[NOUGHT:%.*]] = enum $PolyOptionable, #PolyOptionable.mere!enumelt, %0 _ = PolyOptionable.mere(t) // CHECK: return } // Regression test for a bug where temporary allocations created as a result of // tuple implosion were not deallocated in enum constructors. struct String { var ptr: AnyObject } enum Foo { case a(P, String) } func Foo_cases() { _ = Foo.a } enum Indirect { indirect case payload((T, other: T)) case none } // CHECK-LABEL: sil{{.*}} @{{.*}}makeIndirectEnum{{.*}} : $@convention(thin) (@in_guaranteed T) -> @owned Indirect // CHECK: [[BOX:%.*]] = alloc_box $<τ_0_0> { var (τ_0_0, other: τ_0_0) } // CHECK: enum $Indirect, #Indirect.payload!enumelt, [[BOX]] : $<τ_0_0> { var (τ_0_0, other: τ_0_0) } func makeIndirectEnum(_ payload: T) -> Indirect { return Indirect.payload((payload, other: payload)) } // https://github.com/apple/swift/issues/52118 enum TrailingClosureConcrete { case label(fn: () -> Int) case noLabel(() -> Int) case twoElementsLabel(x: Int, fn: () -> Int) case twoElementsNoLabel(_ x: Int, _ fn: () -> Int) } func useTrailingClosureConcrete() { _ = TrailingClosureConcrete.label { 0 } _ = TrailingClosureConcrete.noLabel { 0 } _ = TrailingClosureConcrete.twoElementsLabel(x: 0) { 0 } _ = TrailingClosureConcrete.twoElementsNoLabel(0) { 0 } } enum TrailingClosureGeneric { case label(fn: () -> T) case noLabel(() -> T) case twoElementsLabel(x: T, fn: () -> T) case twoElementsNoLabel(_ x: T, _ fn: () -> T) } func useTrailingClosureGeneric(t: T) { _ = TrailingClosureGeneric.label { t } _ = TrailingClosureGeneric.noLabel { t } _ = TrailingClosureGeneric.twoElementsLabel(x: t) { t } _ = TrailingClosureGeneric.twoElementsNoLabel(t) { t } } // https://github.com/apple/swift/issues/50338 enum OneOrTwo { case one case two } // CHECK-LABEL: sil hidden [ossa] @$s4enum18matchOptionalEnum13baryAA8OneOrTwoOSg_tF : $@convention(thin) (Optional) -> () { // CHECK: bb0(%0 : $Optional): // CHECK-NEXT: debug_value %0 : $Optional, let, name "bar", argno 1 // CHECK-NEXT: switch_enum %0 : $Optional, case #Optional.some!enumelt: bb1, default bb4 // CHECK: bb1([[PHI_ARG:%.*]] : $OneOrTwo): // CHECK-NEXT: switch_enum [[PHI_ARG]] : $OneOrTwo, case #OneOrTwo.one!enumelt: bb2, case #OneOrTwo.two!enumelt: bb3 func matchOptionalEnum1(bar: OneOrTwo?) { switch bar { case .one: print("one") case .two?: print("two") default: print("default") } } // CHECK-LABEL: sil hidden [ossa] @$s4enum18matchOptionalEnum23baryAA8OneOrTwoOSgSg_tF : $@convention(thin) (Optional>) -> () { // CHECK: bb0(%0 : $Optional>): // CHECK-NEXT: debug_value %0 : $Optional>, let, name "bar", argno 1 // CHECK-NEXT: switch_enum %0 : $Optional>, case #Optional.none!enumelt: bb1, default bb2 func matchOptionalEnum2(bar: OneOrTwo??) { switch bar { case .none: print("none") default: print("default") } } enum OneTwoOrNone { case one case two var none: Self { .one } } // CHECK-LABEL: sil hidden [ossa] @$s4enum18matchOptionalEnum33baryAA12OneTwoOrNoneOSg_tF : $@convention(thin) (Optional) -> () { // CHECK: bb0(%0 : $Optional): // CHECK-NEXT: debug_value %0 : $Optional, let, name "bar", argno 1 // CHECK-NEXT: switch_enum %0 : $Optional, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb4 // CHECK: bb1([[PHI_ARG:%.*]] : $OneTwoOrNone): // CHECK-NEXT: switch_enum [[PHI_ARG]] : $OneTwoOrNone, case #OneTwoOrNone.one!enumelt: bb2, case #OneTwoOrNone.two!enumelt: bb3 func matchOptionalEnum3(bar: OneTwoOrNone?) { switch bar { case .one: print("one") case .two?: print("two") case .none: print("none") default: print("default") } } // Make sure that we handle enum, tuple initialization composed // correctly. Previously, we leaked down a failure path due to us misusing // scopes. enum rdar81817725 { case localAddress case setOption(Int, Any) static func takeAny(_:Any) -> Bool { return true } static func testSwitchCleanup(syscall: rdar81817725, expectedLevel: Int, valueMatcher: (Any) -> Bool) throws -> Bool { if case .setOption(expectedLevel, let value) = syscall { return rdar81817725.takeAny(value) } else { return false } } } enum Indirected { case a case b indirect case c(Int) } func throwingFunction() throws -> Int { return 0 } // CHECK-LABEL: sil hidden [ossa] @$s4enum29throwInIndirectConstructorArgAA10IndirectedOyKF // CHECK: [[BOX:%.*]] = alloc_box ${ var Int } // CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = project_box [[BOX]] // CHECK-NEXT: // function_ref // CHECK-NEXT: [[FN:%.*]] = function_ref // CHECK-NEXT: try_apply [[FN]]() // CHECK: bb1([[RESULT:%.*]] : $Int): // CHECK-NEXT: store [[RESULT]] to [trivial] [[PAYLOAD_ADDR]] // CHECK-NEXT: [[ENUM:%.*]] = enum $Indirected, #Indirected.c!enumelt, [[BOX]] // CHECK-NEXT: return [[ENUM]] : $Indirected // CHECK: bb2([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: dealloc_box [[BOX]] // CHECK-NEXT: throw [[ERROR]] func throwInIndirectConstructorArg() throws -> Indirected { return .c(try throwingFunction()) }