mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This changes code generation a bit, because now the conditional state bitmap uses a bit to track if the 'self' box was stored, not if the 'self' value was consumed. In some cases, this eliminates an extra bit, in other places it introduces an extra bit, but it really doesn't matter because LLVM will optimize this bit manipulation easily.
441 lines
12 KiB
Swift
441 lines
12 KiB
Swift
// RUN: %target-run-simple-swift
|
|
// REQUIRES: executable_test
|
|
|
|
import StdlibUnittest
|
|
|
|
|
|
var ThrowingInitTestSuite = TestSuite("ThrowingInit")
|
|
|
|
enum E : Error {
|
|
case X
|
|
}
|
|
|
|
func unwrap(_ b: Bool) throws -> Int {
|
|
if b {
|
|
throw E.X
|
|
}
|
|
return 0
|
|
}
|
|
|
|
class Bear {
|
|
let x: LifetimeTracked
|
|
|
|
/* Designated */
|
|
init(n: Int) {
|
|
x = LifetimeTracked(0)
|
|
}
|
|
|
|
init(n: Int, before: Bool) throws {
|
|
if before {
|
|
throw E.X
|
|
}
|
|
self.x = LifetimeTracked(0)
|
|
}
|
|
|
|
init(n: Int, after: Bool) throws {
|
|
self.x = LifetimeTracked(0)
|
|
if after {
|
|
throw E.X
|
|
}
|
|
}
|
|
|
|
init(n: Int, before: Bool, after: Bool) throws {
|
|
if before {
|
|
throw E.X
|
|
}
|
|
self.x = LifetimeTracked(0)
|
|
if after {
|
|
throw E.X
|
|
}
|
|
}
|
|
|
|
/* Convenience */
|
|
convenience init(before: Bool) throws {
|
|
try unwrap(before)
|
|
self.init(n: 0)
|
|
}
|
|
|
|
convenience init(before2: Bool) throws {
|
|
try self.init(n: unwrap(before2))
|
|
}
|
|
|
|
convenience init(before: Bool, before2: Bool) throws {
|
|
try unwrap(before)
|
|
try self.init(n: unwrap(before2))
|
|
}
|
|
|
|
convenience init(during: Bool) throws {
|
|
try self.init(n: 0, after: during)
|
|
}
|
|
|
|
convenience init(before: Bool, during: Bool) throws {
|
|
try unwrap(before)
|
|
try self.init(n: 0, after: during)
|
|
}
|
|
|
|
convenience init(after: Bool) throws {
|
|
self.init(n: 0)
|
|
try unwrap(after)
|
|
}
|
|
|
|
convenience init(before: Bool, after: Bool) throws {
|
|
try unwrap(before)
|
|
self.init(n: 0)
|
|
try unwrap(after)
|
|
}
|
|
|
|
convenience init(during: Bool, after: Bool) throws {
|
|
try self.init(n: 0, after: during)
|
|
try unwrap(after)
|
|
}
|
|
|
|
convenience init(before: Bool, during: Bool, after: Bool) throws {
|
|
try unwrap(before)
|
|
try self.init(n: 0, after: during)
|
|
try unwrap(after)
|
|
}
|
|
|
|
convenience init(before: Bool, before2: Bool, during: Bool, after: Bool) throws {
|
|
try unwrap(before)
|
|
try self.init(n: unwrap(before2), after: during)
|
|
try unwrap(after)
|
|
}
|
|
}
|
|
|
|
class PolarBear : Bear {
|
|
let y: LifetimeTracked
|
|
|
|
/* Designated */
|
|
override init(n: Int) {
|
|
self.y = LifetimeTracked(0)
|
|
super.init(n: n)
|
|
}
|
|
|
|
override init(n: Int, before: Bool) throws {
|
|
if before {
|
|
throw E.X
|
|
}
|
|
self.y = LifetimeTracked(0)
|
|
super.init(n: n)
|
|
}
|
|
|
|
init(n: Int, during: Bool) throws {
|
|
self.y = LifetimeTracked(0)
|
|
try super.init(n: n, before: during)
|
|
}
|
|
|
|
init(n: Int, before: Bool, during: Bool) throws {
|
|
self.y = LifetimeTracked(0)
|
|
if before {
|
|
throw E.X
|
|
}
|
|
try super.init(n: n, before: during)
|
|
}
|
|
|
|
override init(n: Int, after: Bool) throws {
|
|
self.y = LifetimeTracked(0)
|
|
super.init(n: n)
|
|
if after {
|
|
throw E.X
|
|
}
|
|
}
|
|
|
|
init(n: Int, during: Bool, after: Bool) throws {
|
|
self.y = LifetimeTracked(0)
|
|
try super.init(n: n, before: during)
|
|
if after {
|
|
throw E.X
|
|
}
|
|
}
|
|
|
|
override init(n: Int, before: Bool, after: Bool) throws {
|
|
if before {
|
|
throw E.X
|
|
}
|
|
self.y = LifetimeTracked(0)
|
|
super.init(n: n)
|
|
if after {
|
|
throw E.X
|
|
}
|
|
}
|
|
|
|
init(n: Int, before: Bool, during: Bool, after: Bool) throws {
|
|
if before {
|
|
throw E.X
|
|
}
|
|
self.y = LifetimeTracked(0)
|
|
try super.init(n: n, before: during)
|
|
if after {
|
|
throw E.X
|
|
}
|
|
}
|
|
}
|
|
|
|
class GuineaPig<T> : Bear {
|
|
let y: LifetimeTracked
|
|
let t: T
|
|
|
|
init(t: T, during: Bool) throws {
|
|
self.y = LifetimeTracked(0)
|
|
self.t = t
|
|
try super.init(n: 0, before: during)
|
|
}
|
|
}
|
|
|
|
struct Chimera {
|
|
let x: LifetimeTracked
|
|
let y: LifetimeTracked
|
|
|
|
init(before: Bool) throws {
|
|
if before {
|
|
throw E.X
|
|
}
|
|
x = LifetimeTracked(0)
|
|
y = LifetimeTracked(0)
|
|
}
|
|
|
|
init(during: Bool) throws {
|
|
x = LifetimeTracked(0)
|
|
if during {
|
|
throw E.X
|
|
}
|
|
y = LifetimeTracked(0)
|
|
}
|
|
|
|
init(before: Bool, during: Bool) throws {
|
|
if before {
|
|
throw E.X
|
|
}
|
|
x = LifetimeTracked(0)
|
|
if during {
|
|
throw E.X
|
|
}
|
|
y = LifetimeTracked(0)
|
|
}
|
|
|
|
init(after: Bool) throws {
|
|
x = LifetimeTracked(0)
|
|
y = LifetimeTracked(0)
|
|
if after {
|
|
throw E.X
|
|
}
|
|
}
|
|
|
|
init(before: Bool, after: Bool) throws {
|
|
if before {
|
|
throw E.X
|
|
}
|
|
x = LifetimeTracked(0)
|
|
y = LifetimeTracked(0)
|
|
if after {
|
|
throw E.X
|
|
}
|
|
}
|
|
|
|
init(during: Bool, after: Bool) throws {
|
|
x = LifetimeTracked(0)
|
|
if during {
|
|
throw E.X
|
|
}
|
|
y = LifetimeTracked(0)
|
|
if after {
|
|
throw E.X
|
|
}
|
|
}
|
|
|
|
init(before: Bool, during: Bool, after: Bool) throws {
|
|
if before {
|
|
throw E.X
|
|
}
|
|
x = LifetimeTracked(0)
|
|
if during {
|
|
throw E.X
|
|
}
|
|
y = LifetimeTracked(0)
|
|
if after {
|
|
throw E.X
|
|
}
|
|
}
|
|
}
|
|
|
|
func mustThrow<T>(_ f: () throws -> T) {
|
|
do {
|
|
_ = try f()
|
|
preconditionFailure("Didn't throw")
|
|
} catch {}
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("DesignatedInitSuccess_Root") {
|
|
_ = try! Bear(n: 0, before: false)
|
|
_ = try! Bear(n: 0, after: false)
|
|
_ = try! Bear(n: 0, before: false, after: false)
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("DesignatedInitFailure_Root") {
|
|
mustThrow { try Bear(n: 0, before: true) }
|
|
mustThrow { try Bear(n: 0, after: true) }
|
|
mustThrow { try Bear(n: 0, before: true, after: false) }
|
|
mustThrow { try Bear(n: 0, before: false, after: true) }
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("DesignatedInitSuccess_Derived") {
|
|
_ = try! PolarBear(n: 0, before: false)
|
|
_ = try! PolarBear(n: 0, during: false)
|
|
_ = try! PolarBear(n: 0, before: false, during: false)
|
|
_ = try! PolarBear(n: 0, during: false, after: false)
|
|
_ = try! PolarBear(n: 0, before: false, after: false)
|
|
_ = try! PolarBear(n: 0, before: false, during: false, after: false)
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("DesignatedInitFailure_Derived") {
|
|
mustThrow { try PolarBear(n: 0, before: true) }
|
|
mustThrow { try PolarBear(n: 0, during: true) }
|
|
mustThrow { try PolarBear(n: 0, before: true, during: false) }
|
|
mustThrow { try PolarBear(n: 0, before: false, during: true) }
|
|
mustThrow { try PolarBear(n: 0, after: true) }
|
|
mustThrow { try PolarBear(n: 0, during: true, after: false) }
|
|
mustThrow { try PolarBear(n: 0, during: false, after: true) }
|
|
mustThrow { try PolarBear(n: 0, before: true, after: false) }
|
|
mustThrow { try PolarBear(n: 0, before: false, after: true) }
|
|
mustThrow { try PolarBear(n: 0, before: true, during: false, after: false) }
|
|
mustThrow { try PolarBear(n: 0, before: false, during: true, after: false) }
|
|
mustThrow { try PolarBear(n: 0, before: false, during: false, after: true) }
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("DesignatedInitSuccess_DerivedGeneric") {
|
|
_ = try! GuineaPig(t: LifetimeTracked(0), during: false)
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("DesignatedInitFailure_DerivedGeneric") {
|
|
mustThrow { try GuineaPig(t: LifetimeTracked(0), during: true) }
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("ConvenienceInitSuccess_Root") {
|
|
_ = try! Bear(before: false)
|
|
_ = try! Bear(before2: false)
|
|
_ = try! Bear(before: false, before2: false)
|
|
_ = try! Bear(during: false)
|
|
_ = try! Bear(before: false, during: false)
|
|
_ = try! Bear(after: false)
|
|
_ = try! Bear(before: false, after: false)
|
|
_ = try! Bear(during: false, after: false)
|
|
_ = try! Bear(before: false, during: false, after: false)
|
|
_ = try! Bear(before: false, before2: false, during: false, after: false)
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("ConvenienceInitFailure_Root") {
|
|
mustThrow { try Bear(before: true) }
|
|
mustThrow { try Bear(before2: true) }
|
|
mustThrow { try Bear(before: true, before2: false) }
|
|
mustThrow { try Bear(before: false, before2: true) }
|
|
mustThrow { try Bear(during: true) }
|
|
mustThrow { try Bear(before: true, during: false) }
|
|
mustThrow { try Bear(before: false, during: true) }
|
|
mustThrow { try Bear(after: true) }
|
|
mustThrow { try Bear(before: true, after: false) }
|
|
mustThrow { try Bear(before: false, after: true) }
|
|
mustThrow { try Bear(during: true, after: false) }
|
|
mustThrow { try Bear(during: false, after: true) }
|
|
mustThrow { try Bear(before: true, during: false, after: false) }
|
|
mustThrow { try Bear(before: false, during: true, after: false) }
|
|
mustThrow { try Bear(before: false, during: false, after: true) }
|
|
mustThrow { try Bear(before: true, before2: false, during: false, after: false) }
|
|
mustThrow { try Bear(before: false, before2: true, during: false, after: false) }
|
|
mustThrow { try Bear(before: false, before2: false, during: true, after: false) }
|
|
mustThrow { try Bear(before: false, before2: false, during: false, after: true) }
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("ConvenienceInitSuccess_Derived") {
|
|
_ = try! PolarBear(before: false)
|
|
_ = try! PolarBear(before2: false)
|
|
_ = try! PolarBear(before: false, before2: false)
|
|
_ = try! PolarBear(during: false)
|
|
_ = try! PolarBear(before: false, during: false)
|
|
_ = try! PolarBear(after: false)
|
|
_ = try! PolarBear(before: false, after: false)
|
|
_ = try! PolarBear(during: false, after: false)
|
|
_ = try! PolarBear(before: false, during: false, after: false)
|
|
_ = try! PolarBear(before: false, before2: false, during: false, after: false)
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("ConvenienceInitFailure_Derived") {
|
|
mustThrow { try PolarBear(before: true) }
|
|
mustThrow { try PolarBear(before2: true) }
|
|
mustThrow { try PolarBear(before: true, before2: false) }
|
|
mustThrow { try PolarBear(before: false, before2: true) }
|
|
mustThrow { try PolarBear(during: true) }
|
|
mustThrow { try PolarBear(before: true, during: false) }
|
|
mustThrow { try PolarBear(before: false, during: true) }
|
|
mustThrow { try PolarBear(after: true) }
|
|
mustThrow { try PolarBear(before: true, after: false) }
|
|
mustThrow { try PolarBear(before: false, after: true) }
|
|
mustThrow { try PolarBear(during: true, after: false) }
|
|
mustThrow { try PolarBear(during: false, after: true) }
|
|
mustThrow { try PolarBear(before: true, during: false, after: false) }
|
|
mustThrow { try PolarBear(before: false, during: true, after: false) }
|
|
mustThrow { try PolarBear(before: false, during: false, after: true) }
|
|
mustThrow { try PolarBear(before: true, before2: false, during: false, after: false) }
|
|
mustThrow { try PolarBear(before: false, before2: true, during: false, after: false) }
|
|
mustThrow { try PolarBear(before: false, before2: false, during: true, after: false) }
|
|
mustThrow { try PolarBear(before: false, before2: false, during: false, after: true) }
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("InitSuccess_Struct") {
|
|
_ = try! Chimera(before: false)
|
|
_ = try! Chimera(during: false)
|
|
_ = try! Chimera(before: false, during: false)
|
|
_ = try! Chimera(after: false)
|
|
_ = try! Chimera(before: false, after: false)
|
|
_ = try! Chimera(during: false, after: false)
|
|
_ = try! Chimera(before: false, during: false, after: false)
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("InitFailure_Struct") {
|
|
mustThrow { try Chimera(before: true) }
|
|
mustThrow { try Chimera(during: true) }
|
|
mustThrow { try Chimera(before: true, during: false) }
|
|
mustThrow { try Chimera(before: false, during: true) }
|
|
mustThrow { try Chimera(after: true) }
|
|
mustThrow { try Chimera(before: true, after: false) }
|
|
mustThrow { try Chimera(before: false, after: true) }
|
|
mustThrow { try Chimera(during: true, after: false) }
|
|
mustThrow { try Chimera(during: false, after: true) }
|
|
mustThrow { try Chimera(before: true, during: false, after: false) }
|
|
mustThrow { try Chimera(before: false, during: true, after: false) }
|
|
mustThrow { try Chimera(before: false, during: false, after: true) }
|
|
}
|
|
|
|
// Specific regression tests:
|
|
|
|
// <https://bugs.swift.org/browse/SR-1714> - try? self.init(...)` in init? causes overrelease
|
|
class ThrowAndFailRoot {
|
|
let x = LifetimeTracked(0)
|
|
}
|
|
|
|
class ThrowAndFailDerived: ThrowAndFailRoot {
|
|
let name: String
|
|
let y = LifetimeTracked(0)
|
|
|
|
init(name: String) throws {
|
|
self.name = name
|
|
super.init()
|
|
if name.isEmpty {
|
|
struct EmptyError: Error {}
|
|
throw EmptyError()
|
|
}
|
|
}
|
|
|
|
convenience init?(b: Bool) {
|
|
try? self.init(name: b ? "Bob" : "")
|
|
}
|
|
}
|
|
|
|
ThrowingInitTestSuite.test("ThrowsAndFailableTest") {
|
|
_ = ThrowAndFailDerived(b: true)!
|
|
if let x = ThrowAndFailDerived(b: false) { preconditionFailure() }
|
|
}
|
|
|
|
// <https://bugs.swift.org/browse/SR-3132> - Invalid pointer dequeued from free list. Runtime crash on some weird code
|
|
|
|
runAllTests()
|