| // RUN: %empty-directory(%t) |
| // RUN: %target-build-swift -swift-version 5 %s -o %t/a.out |
| // |
| // RUN: %target-run %t/a.out |
| // REQUIRES: executable_test |
| |
| import StdlibUnittest |
| |
| var ProtocolInitTestSuite = TestSuite("ProtocolInit") |
| |
| func mustThrow<T>(_ f: () throws -> T) { |
| do { |
| _ = try f() |
| preconditionFailure("Didn't throw") |
| } catch {} |
| } |
| |
| func mustFail<T>(f: () -> T?) { |
| if f() != nil { |
| preconditionFailure("Didn't fail") |
| } |
| } |
| |
| enum E : Error { case X } |
| |
| protocol TriviallyConstructible { |
| init(x: LifetimeTracked) |
| init(x: LifetimeTracked, throwsDuring: Bool) throws |
| init?(x: LifetimeTracked, failsDuring: Bool) |
| } |
| |
| extension TriviallyConstructible { |
| init(x: LifetimeTracked, throwsBefore: Bool) throws { |
| if throwsBefore { |
| throw E.X |
| } |
| self.init(x: x) |
| } |
| |
| init(x: LifetimeTracked, throwsAfter: Bool) throws { |
| self.init(x: x) |
| if throwsAfter { |
| throw E.X |
| } |
| } |
| |
| init(x: LifetimeTracked, throwsBefore: Bool, throwsDuring: Bool) throws { |
| if throwsBefore { |
| throw E.X |
| } |
| try self.init(x: x, throwsDuring: throwsDuring) |
| } |
| |
| init(x: LifetimeTracked, throwsBefore: Bool, throwsAfter: Bool) throws { |
| if throwsBefore { |
| throw E.X |
| } |
| self.init(x: x) |
| if throwsAfter { |
| throw E.X |
| } |
| } |
| |
| init(x: LifetimeTracked, throwsDuring: Bool, throwsAfter: Bool) throws { |
| try self.init(x: x, throwsDuring: throwsDuring) |
| if throwsAfter { |
| throw E.X |
| } |
| } |
| |
| init(x: LifetimeTracked, throwsBefore: Bool, throwsDuring: Bool, throwsAfter: Bool) throws { |
| if throwsBefore { |
| throw E.X |
| } |
| try self.init(x: x, throwsDuring: throwsDuring) |
| if throwsAfter { |
| throw E.X |
| } |
| } |
| |
| init?(x: LifetimeTracked, failsBefore: Bool) { |
| if failsBefore { |
| return nil |
| } |
| self.init(x: x) |
| } |
| |
| init?(x: LifetimeTracked, failsAfter: Bool) { |
| self.init(x: x) |
| if failsAfter { |
| return nil |
| } |
| } |
| |
| init?(x: LifetimeTracked, failsBefore: Bool, failsDuring: Bool) { |
| if failsBefore { |
| return nil |
| } |
| self.init(x: x, failsDuring: failsDuring) |
| } |
| |
| init?(x: LifetimeTracked, failsBefore: Bool, failsAfter: Bool) { |
| if failsBefore { |
| return nil |
| } |
| self.init(x: x) |
| if failsAfter { |
| return nil |
| } |
| } |
| |
| init?(x: LifetimeTracked, failsDuring: Bool, failsAfter: Bool) { |
| self.init(x: x, failsDuring: failsDuring) |
| if failsAfter { |
| return nil |
| } |
| } |
| |
| init?(x: LifetimeTracked, failsBefore: Bool, failsDuring: Bool, failsAfter: Bool) { |
| if failsBefore { |
| return nil |
| } |
| self.init(x: x, failsDuring: failsDuring) |
| if failsAfter { |
| return nil |
| } |
| } |
| } |
| |
| class TrivialClass : TriviallyConstructible { |
| let tracker: LifetimeTracked |
| |
| // Protocol requirements |
| required init(x: LifetimeTracked) { |
| self.tracker = x |
| } |
| |
| required convenience init(x: LifetimeTracked, throwsDuring: Bool) throws { |
| self.init(x: x) |
| if throwsDuring { |
| throw E.X |
| } |
| } |
| |
| required convenience init?(x: LifetimeTracked, failsDuring: Bool) { |
| self.init(x: x) |
| if failsDuring { |
| return nil |
| } |
| } |
| |
| // Class initializers delegating to protocol initializers |
| convenience init(throwsBefore: Bool) throws { |
| if throwsBefore { |
| throw E.X |
| } |
| self.init(x: LifetimeTracked(0)) |
| } |
| |
| convenience init(throwsAfter: Bool) throws { |
| self.init(x: LifetimeTracked(0)) |
| if throwsAfter { |
| throw E.X |
| } |
| } |
| |
| convenience init(throwsBefore: Bool, throwsDuring: Bool) throws { |
| if throwsBefore { |
| throw E.X |
| } |
| try self.init(x: LifetimeTracked(0), throwsDuring: throwsDuring) |
| } |
| |
| convenience init(throwsBefore: Bool, throwsAfter: Bool) throws { |
| if throwsBefore { |
| throw E.X |
| } |
| self.init(x: LifetimeTracked(0)) |
| if throwsAfter { |
| throw E.X |
| } |
| } |
| |
| convenience init(throwsDuring: Bool, throwsAfter: Bool) throws { |
| try self.init(x: LifetimeTracked(0), throwsDuring: throwsDuring) |
| if throwsAfter { |
| throw E.X |
| } |
| } |
| |
| convenience init(throwsBefore: Bool, throwsDuring: Bool, throwsAfter: Bool) throws { |
| if throwsBefore { |
| throw E.X |
| } |
| try self.init(x: LifetimeTracked(0), throwsDuring: throwsDuring) |
| if throwsAfter { |
| throw E.X |
| } |
| } |
| |
| convenience init?(failsBefore: Bool) { |
| if failsBefore { |
| return nil |
| } |
| self.init(x: LifetimeTracked(0)) |
| } |
| |
| convenience init?(failsAfter: Bool) { |
| self.init(x: LifetimeTracked(0)) |
| if failsAfter { |
| return nil |
| } |
| } |
| |
| convenience init?(failsBefore: Bool, failsDuring: Bool) { |
| if failsBefore { |
| return nil |
| } |
| self.init(x: LifetimeTracked(0), failsDuring: failsDuring) |
| } |
| |
| convenience init?(failsBefore: Bool, failsAfter: Bool) { |
| if failsBefore { |
| return nil |
| } |
| self.init(x: LifetimeTracked(0)) |
| if failsAfter { |
| return nil |
| } |
| } |
| |
| convenience init?(failsDuring: Bool, failsAfter: Bool) { |
| self.init(x: LifetimeTracked(0), failsDuring: failsDuring) |
| if failsAfter { |
| return nil |
| } |
| } |
| |
| convenience init?(failsBefore: Bool, failsDuring: Bool, failsAfter: Bool) { |
| if failsBefore { |
| return nil |
| } |
| self.init(x: LifetimeTracked(0), failsDuring: failsDuring) |
| if failsAfter { |
| return nil |
| } |
| } |
| } |
| |
| ProtocolInitTestSuite.test("ExtensionInit_Success") { |
| _ = try! TrivialClass(x: LifetimeTracked(0), throwsBefore: false) |
| _ = try! TrivialClass(x: LifetimeTracked(0), throwsAfter: false) |
| _ = try! TrivialClass(x: LifetimeTracked(0), throwsBefore: false, throwsDuring: false) |
| _ = try! TrivialClass(x: LifetimeTracked(0), throwsDuring: false, throwsAfter: false) |
| _ = try! TrivialClass(x: LifetimeTracked(0), throwsBefore: false, throwsAfter: false) |
| _ = try! TrivialClass(x: LifetimeTracked(0), throwsBefore: false, throwsDuring: false, throwsAfter: false) |
| |
| _ = TrivialClass(x: LifetimeTracked(0), failsBefore: false)! |
| _ = TrivialClass(x: LifetimeTracked(0), failsAfter: false)! |
| _ = TrivialClass(x: LifetimeTracked(0), failsBefore: false, failsDuring: false)! |
| _ = TrivialClass(x: LifetimeTracked(0), failsDuring: false, failsAfter: false)! |
| _ = TrivialClass(x: LifetimeTracked(0), failsBefore: false, failsAfter: false)! |
| _ = TrivialClass(x: LifetimeTracked(0), failsBefore: false, failsDuring: false, failsAfter: false)! |
| } |
| |
| ProtocolInitTestSuite.test("ClassInit_Success") { |
| _ = try! TrivialClass(throwsBefore: false) |
| _ = try! TrivialClass(throwsAfter: false) |
| _ = try! TrivialClass(throwsBefore: false, throwsDuring: false) |
| _ = try! TrivialClass(throwsDuring: false, throwsAfter: false) |
| _ = try! TrivialClass(throwsBefore: false, throwsAfter: false) |
| _ = try! TrivialClass(throwsBefore: false, throwsDuring: false, throwsAfter: false) |
| |
| _ = TrivialClass(failsBefore: false)! |
| _ = TrivialClass(failsAfter: false)! |
| _ = TrivialClass(failsBefore: false, failsDuring: false)! |
| _ = TrivialClass(failsDuring: false, failsAfter: false)! |
| _ = TrivialClass(failsBefore: false, failsAfter: false)! |
| _ = TrivialClass(failsBefore: false, failsDuring: false, failsAfter: false)! |
| } |
| |
| ProtocolInitTestSuite.test("ExtensionInit_Failure") { |
| mustThrow { try TrivialClass(x: LifetimeTracked(0), throwsBefore: true) } |
| mustThrow { try TrivialClass(x: LifetimeTracked(0), throwsAfter: true) } |
| mustThrow { try TrivialClass(x: LifetimeTracked(0), throwsBefore: true, throwsDuring: false) } |
| mustThrow { try TrivialClass(x: LifetimeTracked(0), throwsBefore: false, throwsDuring: true) } |
| mustThrow { try TrivialClass(x: LifetimeTracked(0), throwsDuring: true, throwsAfter: false) } |
| mustThrow { try TrivialClass(x: LifetimeTracked(0), throwsDuring: false, throwsAfter: true) } |
| mustThrow { try TrivialClass(x: LifetimeTracked(0), throwsBefore: true, throwsAfter: false) } |
| mustThrow { try TrivialClass(x: LifetimeTracked(0), throwsBefore: false, throwsAfter: true) } |
| mustThrow { try TrivialClass(x: LifetimeTracked(0), throwsBefore: true, throwsDuring: false, throwsAfter: false) } |
| mustThrow { try TrivialClass(x: LifetimeTracked(0), throwsBefore: false, throwsDuring: true, throwsAfter: false) } |
| mustThrow { try TrivialClass(x: LifetimeTracked(0), throwsBefore: false, throwsDuring: false, throwsAfter: true) } |
| |
| mustFail { TrivialClass(x: LifetimeTracked(0), failsBefore: true) } |
| mustFail { TrivialClass(x: LifetimeTracked(0), failsAfter: true) } |
| mustFail { TrivialClass(x: LifetimeTracked(0), failsBefore: true, failsDuring: false) } |
| mustFail { TrivialClass(x: LifetimeTracked(0), failsBefore: false, failsDuring: true) } |
| mustFail { TrivialClass(x: LifetimeTracked(0), failsDuring: true, failsAfter: false) } |
| mustFail { TrivialClass(x: LifetimeTracked(0), failsDuring: false, failsAfter: true) } |
| mustFail { TrivialClass(x: LifetimeTracked(0), failsBefore: true, failsAfter: false) } |
| mustFail { TrivialClass(x: LifetimeTracked(0), failsBefore: false, failsAfter: true) } |
| mustFail { TrivialClass(x: LifetimeTracked(0), failsBefore: true, failsDuring: false, failsAfter: false) } |
| mustFail { TrivialClass(x: LifetimeTracked(0), failsBefore: false, failsDuring: true, failsAfter: false) } |
| mustFail { TrivialClass(x: LifetimeTracked(0), failsBefore: false, failsDuring: false, failsAfter: true) } |
| } |
| |
| ProtocolInitTestSuite.test("ClassInit_Failure") { |
| mustThrow { try TrivialClass(throwsBefore: true) } |
| mustThrow { try TrivialClass(throwsAfter: true) } |
| mustThrow { try TrivialClass(throwsBefore: true, throwsDuring: false) } |
| mustThrow { try TrivialClass(throwsBefore: false, throwsDuring: true) } |
| mustThrow { try TrivialClass(throwsDuring: true, throwsAfter: false) } |
| mustThrow { try TrivialClass(throwsDuring: false, throwsAfter: true) } |
| mustThrow { try TrivialClass(throwsBefore: true, throwsAfter: false) } |
| mustThrow { try TrivialClass(throwsBefore: false, throwsAfter: true) } |
| mustThrow { try TrivialClass(throwsBefore: true, throwsDuring: false, throwsAfter: false) } |
| mustThrow { try TrivialClass(throwsBefore: false, throwsDuring: true, throwsAfter: false) } |
| mustThrow { try TrivialClass(throwsBefore: false, throwsDuring: false, throwsAfter: true) } |
| |
| mustFail { TrivialClass(failsBefore: true) } |
| mustFail { TrivialClass(failsAfter: true) } |
| mustFail { TrivialClass(failsBefore: true, failsDuring: false) } |
| mustFail { TrivialClass(failsBefore: false, failsDuring: true) } |
| mustFail { TrivialClass(failsDuring: true, failsAfter: false) } |
| mustFail { TrivialClass(failsDuring: false, failsAfter: true) } |
| mustFail { TrivialClass(failsBefore: true, failsAfter: false) } |
| mustFail { TrivialClass(failsBefore: false, failsAfter: true) } |
| mustFail { TrivialClass(failsBefore: true, failsDuring: false, failsAfter: false) } |
| mustFail { TrivialClass(failsBefore: false, failsDuring: true, failsAfter: false) } |
| mustFail { TrivialClass(failsBefore: false, failsDuring: false, failsAfter: true) } |
| } |
| |
| struct TrivialStruct : TriviallyConstructible { |
| let x: LifetimeTracked |
| |
| init(x: LifetimeTracked) { |
| self.x = x |
| } |
| |
| init(x: LifetimeTracked, throwsDuring: Bool) throws { |
| self.init(x: x) |
| if throwsDuring { |
| throw E.X |
| } |
| } |
| |
| init?(x: LifetimeTracked, failsDuring: Bool) { |
| self.init(x: x) |
| if failsDuring { |
| return nil |
| } |
| } |
| } |
| |
| struct AddrOnlyStruct : TriviallyConstructible { |
| let x: LifetimeTracked |
| let y: Any |
| |
| init(x: LifetimeTracked) { |
| self.x = x |
| self.y = "Hello world" |
| } |
| |
| init(x: LifetimeTracked, throwsDuring: Bool) throws { |
| self.init(x: x) |
| if throwsDuring { |
| throw E.X |
| } |
| } |
| |
| init?(x: LifetimeTracked, failsDuring: Bool) { |
| self.init(x: x) |
| if failsDuring { |
| return nil |
| } |
| } |
| } |
| |
| extension TriviallyConstructible { |
| init(throwsFirst: Bool, throwsSecond: Bool, initThenInit: ()) throws { |
| try self.init(x: LifetimeTracked(0), throwsDuring: throwsFirst) |
| try self.init(x: LifetimeTracked(0), throwsDuring: throwsSecond) |
| } |
| |
| init(throwsFirst: Bool, throwsSecond: Bool, initThenAssign: ()) throws { |
| try self.init(x: LifetimeTracked(0), throwsDuring: throwsFirst) |
| self = try Self(x: LifetimeTracked(0), throwsDuring: throwsSecond) |
| } |
| |
| init(throwsFirst: Bool, throwsSecond: Bool, assignThenInit: ()) throws { |
| self = try Self(x: LifetimeTracked(0), throwsDuring: throwsFirst) |
| try self.init(x: LifetimeTracked(0), throwsDuring: throwsSecond) |
| } |
| |
| init(throwsFirst: Bool, throwsSecond: Bool, assignThenAssign: ()) throws { |
| self = try Self(x: LifetimeTracked(0), throwsDuring: throwsFirst) |
| try self.init(x: LifetimeTracked(0), throwsDuring: throwsSecond) |
| } |
| } |
| |
| ProtocolInitTestSuite.test("Struct_Success") { |
| _ = try! TrivialStruct(throwsFirst: false, throwsSecond: false, initThenInit: ()) |
| _ = try! TrivialStruct(throwsFirst: false, throwsSecond: false, initThenAssign: ()) |
| _ = try! TrivialStruct(throwsFirst: false, throwsSecond: false, assignThenInit: ()) |
| _ = try! TrivialStruct(throwsFirst: false, throwsSecond: false, assignThenAssign: ()) |
| } |
| |
| ProtocolInitTestSuite.test("Struct_Failure") { |
| mustThrow { try TrivialStruct(throwsFirst: true, throwsSecond: false, initThenInit: ()) } |
| mustThrow { try TrivialStruct(throwsFirst: false, throwsSecond: true, initThenInit: ()) } |
| mustThrow { try TrivialStruct(throwsFirst: true, throwsSecond: false, initThenAssign: ()) } |
| mustThrow { try TrivialStruct(throwsFirst: false, throwsSecond: true, initThenAssign: ()) } |
| mustThrow { try TrivialStruct(throwsFirst: true, throwsSecond: false, assignThenInit: ()) } |
| mustThrow { try TrivialStruct(throwsFirst: false, throwsSecond: true, assignThenInit: ()) } |
| mustThrow { try TrivialStruct(throwsFirst: true, throwsSecond: false, assignThenAssign: ()) } |
| mustThrow { try TrivialStruct(throwsFirst: false, throwsSecond: true, assignThenAssign: ()) } |
| } |
| |
| ProtocolInitTestSuite.test("AddrOnlyStruct_Success") { |
| _ = try! AddrOnlyStruct(throwsFirst: false, throwsSecond: false, initThenInit: ()) |
| _ = try! AddrOnlyStruct(throwsFirst: false, throwsSecond: false, initThenAssign: ()) |
| _ = try! AddrOnlyStruct(throwsFirst: false, throwsSecond: false, assignThenInit: ()) |
| _ = try! AddrOnlyStruct(throwsFirst: false, throwsSecond: false, assignThenAssign: ()) |
| } |
| |
| ProtocolInitTestSuite.test("AddrOnlyStruct_Failure") { |
| mustThrow { try AddrOnlyStruct(throwsFirst: true, throwsSecond: false, initThenInit: ()) } |
| mustThrow { try AddrOnlyStruct(throwsFirst: false, throwsSecond: true, initThenInit: ()) } |
| mustThrow { try AddrOnlyStruct(throwsFirst: true, throwsSecond: false, initThenAssign: ()) } |
| mustThrow { try AddrOnlyStruct(throwsFirst: false, throwsSecond: true, initThenAssign: ()) } |
| mustThrow { try AddrOnlyStruct(throwsFirst: true, throwsSecond: false, assignThenInit: ()) } |
| mustThrow { try AddrOnlyStruct(throwsFirst: false, throwsSecond: true, assignThenInit: ()) } |
| mustThrow { try AddrOnlyStruct(throwsFirst: true, throwsSecond: false, assignThenAssign: ()) } |
| mustThrow { try AddrOnlyStruct(throwsFirst: false, throwsSecond: true, assignThenAssign: ()) } |
| } |
| |
| runAllTests() |