mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
404 lines
10 KiB
Swift
404 lines
10 KiB
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: %target-build-swift %s -Onone -o %t/main -import-objc-header %S/Inputs/enum-nonexhaustivity.h -Xfrontend -disable-objc-attr-requires-foundation-module
|
|
// RUN: %target-codesign %t/main
|
|
// RUN: %target-run %t/main
|
|
// RUN: %target-build-swift %s -O -o %t/main2 -import-objc-header %S/Inputs/enum-nonexhaustivity.h -Xfrontend -disable-objc-attr-requires-foundation-module
|
|
// RUN: %target-codesign %t/main2
|
|
// RUN: %target-run %t/main2
|
|
// RUN: %target-build-swift %s -Ounchecked -o %t/main3 -import-objc-header %S/Inputs/enum-nonexhaustivity.h -Xfrontend -disable-objc-attr-requires-foundation-module
|
|
// RUN: %target-codesign %t/main3
|
|
// RUN: %target-run %t/main3
|
|
// REQUIRES: executable_test
|
|
|
|
import StdlibUnittest
|
|
|
|
var EnumTestSuite = TestSuite("Enums")
|
|
|
|
EnumTestSuite.test("PlainOldSwitch/NonExhaustive") {
|
|
var gotCorrectValue = false
|
|
switch getExpectedValue() {
|
|
case .A, .C:
|
|
expectUnreachable()
|
|
case .B:
|
|
gotCorrectValue = true
|
|
}
|
|
expectTrue(gotCorrectValue)
|
|
}
|
|
|
|
EnumTestSuite.test("TrapOnUnexpected/NonExhaustive")
|
|
.crashOutputMatches("'NonExhaustiveEnum(rawValue: 3)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switch getUnexpectedValue() {
|
|
case .A, .C:
|
|
expectUnreachable()
|
|
case .B:
|
|
expectUnreachable()
|
|
}
|
|
expectUnreachable()
|
|
}
|
|
|
|
EnumTestSuite.test("TrapOnUnexpectedNested/NonExhaustive")
|
|
.crashOutputMatches("'(NonExhaustiveEnum, NonExhaustiveEnum)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switch (getExpectedValue(), getUnexpectedValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (_, .B):
|
|
expectUnreachable()
|
|
case (_, .A), (_, .C):
|
|
expectUnreachable()
|
|
}
|
|
expectUnreachable()
|
|
}
|
|
|
|
EnumTestSuite.test("TrapOnUnexpectedNested2/NonExhaustive")
|
|
.crashOutputMatches("'(NonExhaustiveEnum, NonExhaustiveEnum)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switch (getUnexpectedValue(), getExpectedValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (.B, _):
|
|
expectUnreachable()
|
|
case (.A, _), (.C, _):
|
|
expectUnreachable()
|
|
}
|
|
expectUnreachable()
|
|
}
|
|
|
|
EnumTestSuite.test("UnexpectedOkayNested/NonExhaustive") {
|
|
var gotCorrectValue = false
|
|
switch (getExpectedValue(), getUnexpectedValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (.B, _):
|
|
gotCorrectValue = true
|
|
case (.A, _), (.C, _):
|
|
expectUnreachable()
|
|
}
|
|
expectTrue(gotCorrectValue)
|
|
}
|
|
|
|
EnumTestSuite.test("UnexpectedOkayNested2/NonExhaustive") {
|
|
var gotCorrectValue = false
|
|
switch (getUnexpectedValue(), getExpectedValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (_, .B):
|
|
gotCorrectValue = true
|
|
case (_, .A), (_, .C):
|
|
expectUnreachable()
|
|
}
|
|
expectTrue(gotCorrectValue)
|
|
}
|
|
|
|
EnumTestSuite.test("Equatable/NonExhaustive") {
|
|
expectEqual(getExpectedValue(), .B)
|
|
expectNotEqual(getUnexpectedValue(), .B)
|
|
expectNotEqual(getExpectedValue(), getUnexpectedValue())
|
|
expectEqual(getUnexpectedValue(), getUnexpectedValue())
|
|
}
|
|
|
|
EnumTestSuite.test("Hashable/NonExhaustive") {
|
|
expectEqual(getExpectedValue().hashValue, NonExhaustiveEnum.B.hashValue)
|
|
expectNotEqual(getUnexpectedValue().hashValue, NonExhaustiveEnum.B.hashValue)
|
|
}
|
|
|
|
|
|
EnumTestSuite.test("PlainOldSwitch/LyingExhaustive") {
|
|
var gotCorrectValue = false
|
|
switch getExpectedLiarValue() {
|
|
case .A, .C:
|
|
expectUnreachable()
|
|
case .B:
|
|
gotCorrectValue = true
|
|
}
|
|
expectTrue(gotCorrectValue)
|
|
}
|
|
|
|
EnumTestSuite.test("TrapOnUnexpected/LyingExhaustive")
|
|
.crashOutputMatches("'LyingExhaustiveEnum(rawValue: 3)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switch getUnexpectedLiarValue() {
|
|
case .A, .C:
|
|
expectUnreachable()
|
|
case .B:
|
|
expectUnreachable()
|
|
}
|
|
expectUnreachable()
|
|
}
|
|
|
|
EnumTestSuite.test("TrapOnUnexpectedNested/LyingExhaustive")
|
|
.crashOutputMatches("'(LyingExhaustiveEnum, LyingExhaustiveEnum)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switch (getExpectedLiarValue(), getUnexpectedLiarValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (_, .B):
|
|
expectUnreachable()
|
|
case (_, .A), (_, .C):
|
|
expectUnreachable()
|
|
}
|
|
expectUnreachable()
|
|
}
|
|
|
|
EnumTestSuite.test("TrapOnUnexpectedNested2/LyingExhaustive")
|
|
.crashOutputMatches("'(LyingExhaustiveEnum, LyingExhaustiveEnum)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switch (getUnexpectedLiarValue(), getExpectedLiarValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (.B, _):
|
|
expectUnreachable()
|
|
case (.A, _), (.C, _):
|
|
expectUnreachable()
|
|
}
|
|
expectUnreachable()
|
|
}
|
|
|
|
EnumTestSuite.test("UnexpectedOkayNested/LyingExhaustive") {
|
|
var gotCorrectValue = false
|
|
switch (getExpectedLiarValue(), getUnexpectedLiarValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (.B, _):
|
|
gotCorrectValue = true
|
|
case (.A, _), (.C, _):
|
|
expectUnreachable()
|
|
}
|
|
expectTrue(gotCorrectValue)
|
|
}
|
|
|
|
EnumTestSuite.test("UnexpectedOkayNested2/LyingExhaustive") {
|
|
var gotCorrectValue = false
|
|
switch (getUnexpectedLiarValue(), getExpectedLiarValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (_, .B):
|
|
gotCorrectValue = true
|
|
case (_, .A), (_, .C):
|
|
expectUnreachable()
|
|
}
|
|
expectTrue(gotCorrectValue)
|
|
}
|
|
|
|
EnumTestSuite.test("Equatable/LyingExhaustive") {
|
|
expectEqual(getExpectedLiarValue(), .B)
|
|
expectNotEqual(getUnexpectedLiarValue(), .B)
|
|
expectNotEqual(getExpectedLiarValue(), getUnexpectedLiarValue())
|
|
expectEqual(getUnexpectedLiarValue(), getUnexpectedLiarValue())
|
|
}
|
|
|
|
EnumTestSuite.test("Hashable/LyingExhaustive") {
|
|
expectEqual(getExpectedLiarValue().hashValue, LyingExhaustiveEnum.B.hashValue)
|
|
expectNotEqual(getUnexpectedLiarValue().hashValue, LyingExhaustiveEnum.B.hashValue)
|
|
}
|
|
|
|
|
|
#if _runtime(_ObjC)
|
|
@objc enum SwiftEnum : Int32 {
|
|
case A, B, C
|
|
|
|
@inline(never) static func getExpectedValue() -> SwiftEnum {
|
|
return .B
|
|
}
|
|
@inline(never) static func getUnexpectedValue() -> SwiftEnum {
|
|
return unsafeBitCast(-42 as Int32, to: SwiftEnum.self)
|
|
}
|
|
}
|
|
|
|
EnumTestSuite.test("PlainOldSwitch/SwiftExhaustive") {
|
|
var gotCorrectValue = false
|
|
switch SwiftEnum.getExpectedValue() {
|
|
case .A, .C:
|
|
expectUnreachable()
|
|
case .B:
|
|
gotCorrectValue = true
|
|
}
|
|
expectTrue(gotCorrectValue)
|
|
}
|
|
|
|
EnumTestSuite.test("TrapOnUnexpected/SwiftExhaustive")
|
|
.crashOutputMatches("'SwiftEnum(rawValue: -42)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switch SwiftEnum.getUnexpectedValue() {
|
|
case .A, .C:
|
|
expectUnreachable()
|
|
case .B:
|
|
expectUnreachable()
|
|
}
|
|
expectUnreachable()
|
|
}
|
|
|
|
EnumTestSuite.test("TrapOnUnexpectedNested/SwiftExhaustive")
|
|
.crashOutputMatches("'(SwiftEnum, SwiftEnum)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switch (SwiftEnum.getExpectedValue(), SwiftEnum.getUnexpectedValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (_, .B):
|
|
expectUnreachable()
|
|
case (_, .A), (_, .C):
|
|
expectUnreachable()
|
|
}
|
|
expectUnreachable()
|
|
}
|
|
|
|
EnumTestSuite.test("TrapOnUnexpectedNested2/SwiftExhaustive")
|
|
.crashOutputMatches("'(SwiftEnum, SwiftEnum)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switch (SwiftEnum.getUnexpectedValue(), SwiftEnum.getExpectedValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (.B, _):
|
|
expectUnreachable()
|
|
case (.A, _), (.C, _):
|
|
expectUnreachable()
|
|
}
|
|
expectUnreachable()
|
|
}
|
|
|
|
EnumTestSuite.test("UnexpectedOkayNested/SwiftExhaustive") {
|
|
var gotCorrectValue = false
|
|
switch (SwiftEnum.getExpectedValue(), SwiftEnum.getUnexpectedValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (.B, _):
|
|
gotCorrectValue = true
|
|
case (.A, _), (.C, _):
|
|
expectUnreachable()
|
|
}
|
|
expectTrue(gotCorrectValue)
|
|
}
|
|
|
|
EnumTestSuite.test("UnexpectedOkayNested2/SwiftExhaustive") {
|
|
var gotCorrectValue = false
|
|
switch (SwiftEnum.getUnexpectedValue(), SwiftEnum.getExpectedValue()) {
|
|
case (.A, .A), (.C, .C):
|
|
expectUnreachable()
|
|
case (_, .B):
|
|
gotCorrectValue = true
|
|
case (_, .A), (_, .C):
|
|
expectUnreachable()
|
|
}
|
|
expectTrue(gotCorrectValue)
|
|
}
|
|
|
|
EnumTestSuite.test("Equatable/SwiftExhaustive") {
|
|
expectEqual(SwiftEnum.getExpectedValue(), .B)
|
|
expectNotEqual(SwiftEnum.getUnexpectedValue(), .B)
|
|
expectNotEqual(SwiftEnum.getExpectedValue(), SwiftEnum.getUnexpectedValue())
|
|
expectEqual(SwiftEnum.getUnexpectedValue(), SwiftEnum.getUnexpectedValue())
|
|
}
|
|
|
|
EnumTestSuite.test("Hashable/SwiftExhaustive") {
|
|
expectEqual(SwiftEnum.getExpectedValue().hashValue, SwiftEnum.B.hashValue)
|
|
expectNotEqual(SwiftEnum.getUnexpectedValue().hashValue, SwiftEnum.B.hashValue)
|
|
}
|
|
|
|
@inline(never)
|
|
func switchOnTwoThings<T>(_ a: T, _ b: SwiftEnum) {
|
|
switch (a, b) {
|
|
case (is String, _):
|
|
expectUnreachable()
|
|
case (_, .B):
|
|
return
|
|
case (_, .A), (_, .C):
|
|
expectUnreachable()
|
|
}
|
|
}
|
|
|
|
EnumTestSuite.test("Generic/Trap")
|
|
.crashOutputMatches("'(Int, SwiftEnum)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switchOnTwoThings(1, SwiftEnum.getUnexpectedValue())
|
|
}
|
|
|
|
EnumTestSuite.test("Generic/Okay") {
|
|
switchOnTwoThings(1, SwiftEnum.getExpectedValue())
|
|
}
|
|
|
|
@objc enum UnsignedSwiftEnum : UInt64 {
|
|
case A, B, C
|
|
|
|
@inline(never) static func getExpectedValue() -> UnsignedSwiftEnum {
|
|
return .B
|
|
}
|
|
@inline(never) static func getUnexpectedValue() -> UnsignedSwiftEnum {
|
|
return unsafeBitCast(~(0 as UInt64), to: UnsignedSwiftEnum.self)
|
|
}
|
|
}
|
|
|
|
EnumTestSuite.test("PlainOldSwitch/LargeSwiftExhaustive") {
|
|
var gotCorrectValue = false
|
|
switch UnsignedSwiftEnum.getExpectedValue() {
|
|
case .A, .C:
|
|
expectUnreachable()
|
|
case .B:
|
|
gotCorrectValue = true
|
|
}
|
|
expectTrue(gotCorrectValue)
|
|
}
|
|
|
|
EnumTestSuite.test("TrapOnUnexpected/LargeSwiftExhaustive")
|
|
.crashOutputMatches("'UnsignedSwiftEnum(rawValue: 18446744073709551615)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switch UnsignedSwiftEnum.getUnexpectedValue() {
|
|
case .A, .C:
|
|
expectUnreachable()
|
|
case .B:
|
|
expectUnreachable()
|
|
}
|
|
expectUnreachable()
|
|
}
|
|
|
|
struct Outer {
|
|
@objc enum NestedSwiftEnum: Int32 {
|
|
case A, B, C
|
|
|
|
@inline(never) static func getExpectedValue() -> NestedSwiftEnum {
|
|
return .B
|
|
}
|
|
@inline(never) static func getUnexpectedValue() -> NestedSwiftEnum {
|
|
return unsafeBitCast(-1 as Int32, to: NestedSwiftEnum.self)
|
|
}
|
|
}
|
|
}
|
|
|
|
EnumTestSuite.test("PlainOldSwitch/NestedSwiftExhaustive") {
|
|
var gotCorrectValue = false
|
|
switch Outer.NestedSwiftEnum.getExpectedValue() {
|
|
case .A, .C:
|
|
expectUnreachable()
|
|
case .B:
|
|
gotCorrectValue = true
|
|
}
|
|
expectTrue(gotCorrectValue)
|
|
}
|
|
|
|
EnumTestSuite.test("TrapOnUnexpected/NestedSwiftExhaustive")
|
|
.crashOutputMatches("'NestedSwiftEnum(rawValue: -1)'")
|
|
.code {
|
|
expectCrashLater()
|
|
switch Outer.NestedSwiftEnum.getUnexpectedValue() {
|
|
case .A, .C:
|
|
expectUnreachable()
|
|
case .B:
|
|
expectUnreachable()
|
|
}
|
|
expectUnreachable()
|
|
}
|
|
#endif
|
|
|
|
runAllTests()
|