Files
swift-mirror/test/decl/init/failable.swift
Chris Lattner f8c6e46e03 remove the Failure::IsNotOptional failure mode, as CSDiags does a better job
of providing contextual diagnostics (e.g. producing the warning in 
Constraints/dynamic_lookup.swift).  This drops a specific diagnostic about
force casting the result of as! which was added in the Swift 1.2 timeframe
to explain the change in cast semantics.  Now that as! has been around for
a long time, it is more confusing than helpful.



Swift SVN r31887
2015-09-11 04:40:13 +00:00

275 lines
7.8 KiB
Swift

// RUN: %target-parse-verify-swift
struct S0 {
init!(int: Int) { }
init! (uint: UInt) { }
init !(float: Float) { }
init?(string: String) { }
init ?(double: Double) { }
init ? (char: Character) { }
}
struct S1<T> {
init?(value: T) { }
}
class DuplicateDecls {
init!() { } // expected-note{{'init()' previously declared here}}
init?() { } // expected-error{{invalid redeclaration of 'init()'}}
init!(string: String) { } // expected-note{{'init(string:)' previously declared here}}
init(string: String) { } // expected-error{{invalid redeclaration of 'init(string:)'}}
init(double: Double) { } // expected-note{{'init(double:)' previously declared here}}
init?(double: Double) { } // expected-error{{invalid redeclaration of 'init(double:)'}}
}
// Construct via a failable initializer.
func testConstruction(i: Int, s: String) {
let s0Opt = S0(string: s)
assert(s0Opt != nil)
var _: S0 = s0Opt // expected-error{{value of optional type 'S0?' not unwrapped; did you mean to use '!' or '?'?}} {{20-20=!}}
let s0IUO = S0(int: i)
assert(s0IUO != nil)
_ = s0IUO
}
// ----------------------------------------------------------------------------
// Superclass initializer chaining
// ----------------------------------------------------------------------------
class Super {
init?(fail: String) { }
init!(failIUO: String) { }
init() { } // expected-note 2{{non-failable initializer 'init()' overridden here}}
}
class Sub : Super {
override init() { super.init() } // okay, never fails
init(nonfail: Int) { // expected-note{{propagate the failure with 'init?'}}{{7-7=?}}
super.init(fail: "boom") // expected-error{{a non-failable initializer cannot chain to failable initializer 'init(fail:)' written with 'init?'}}
// expected-note@-1{{force potentially-failing result with '!'}}{{29-29=!}}
}
convenience init(forceNonfail: Int) {
self.init(nonfail: forceNonfail)! // expected-error{{cannot force unwrap value of non-optional type '()'}} {{37-38=}}
}
init(nonfail2: Int) { // okay, traps on nil
super.init(failIUO: "boom")
}
init(nonfail3: Int) {
super.init(fail: "boom")!
}
override init?(fail: String) {
super.init(fail: fail) // okay, propagates ?
}
init?(fail2: String) { // okay, propagates ! as ?
super.init(failIUO: fail2)
}
init?(fail3: String) { // okay, can introduce its own failure
super.init()
}
override init!(failIUO: String) {
super.init(failIUO: failIUO) // okay, propagates !
}
init!(failIUO2: String) { // okay, propagates ? as !
super.init(fail: failIUO2)
}
init!(failIUO3: String) { // okay, can introduce its own failure
super.init()
}
}
// ----------------------------------------------------------------------------
// Initializer delegation
// ----------------------------------------------------------------------------
extension Super {
convenience init(convenienceNonFailNonFail: String) { // okay, non-failable
self.init()
}
convenience init(convenienceNonFailFail: String) { // expected-note{{propagate the failure with 'init?'}}{{19-19=?}}
self.init(fail: convenienceNonFailFail) // expected-error{{a non-failable initializer cannot delegate to failable initializer 'init(fail:)' written with 'init?'}}
// expected-note@-1{{force potentially-failing result with '!'}}{{44-44=!}}
}
convenience init(convenienceNonFailFailForce: String) {
self.init(fail: convenienceNonFailFailForce)!
}
convenience init(convenienceNonFailFailIUO: String) { // okay, trap on failure
self.init(failIUO: convenienceNonFailFailIUO)
}
convenience init?(convenienceFailNonFail: String) {
self.init() // okay, can introduce its own failure
}
convenience init?(convenienceFailFail: String) {
self.init(fail: convenienceFailFail) // okay, propagates ?
}
convenience init?(convenienceFailFailIUO: String) { // okay, propagates ! as ?
self.init(failIUO: convenienceFailFailIUO)
}
convenience init!(convenienceFailIUONonFail: String) {
self.init() // okay, can introduce its own failure
}
convenience init!(convenienceFailIUOFail: String) {
self.init(fail: convenienceFailIUOFail) // okay, propagates ? as !
}
convenience init!(convenienceFailIUOFailIUO: String) { // okay, propagates !
self.init(failIUO: convenienceFailIUOFailIUO)
}
}
struct SomeStruct {
init(nonFail: Int) { // expected-note{{propagate the failure with 'init?'}}{{8-8=?}}
self.init(fail: nonFail) // expected-error{{a non-failable initializer cannot delegate to failable initializer 'init(fail:)' written with 'init?'}}
// expected-note@-1{{force potentially-failing result with '!'}}{{29-29=!}}
}
init(nonFail2: Int) {
self.init(fail: nonFail2)!
}
init?(fail: Int) {}
}
// ----------------------------------------------------------------------------
// Initializer overriding
// ----------------------------------------------------------------------------
class Sub2 : Super {
override init!(fail: String) { // okay to change ? to !
super.init(fail: fail)
}
override init?(failIUO: String) { // okay to change ! to ?
super.init(failIUO: failIUO)
}
override init() { super.init() } // no change
}
// Dropping optionality
class Sub3 : Super {
override init(fail: String) { // okay, strengthened result type
super.init()
}
override init(failIUO: String) { // okay, strengthened result type
super.init()
}
override init() { } // no change
}
// Adding optionality
class Sub4 : Super {
override init?(fail: String) { super.init() }
override init!(failIUO: String) { super.init() }
override init?() { // expected-error{{failable initializer 'init()' cannot override a non-failable initializer}}
super.init()
}
}
class Sub5 : Super {
override init?(fail: String) { super.init() }
override init!(failIUO: String) { super.init() }
override init!() { // expected-error{{failable initializer 'init()' cannot override a non-failable initializer}}
super.init()
}
}
// ----------------------------------------------------------------------------
// Initializer conformances
// ----------------------------------------------------------------------------
protocol P1 {
init(string: String)
}
@objc protocol P1_objc {
init(string: String)
}
protocol P2 {
init?(fail: String)
}
protocol P3 {
init!(failIUO: String)
}
class C1a : P1 {
required init?(string: String) { } // expected-error{{non-failable initializer requirement 'init(string:)' cannot be satisfied by a failable initializer ('init?')}}
}
class C1b : P1 {
required init!(string: String) { } // okay
}
class C1b_objc : P1_objc {
@objc required init!(string: String) { } // expected-error{{non-failable initializer requirement 'init(string:)' in Objective-C protocol cannot be satisfied by a failable initializer ('init!')}}
}
class C2a : P2 {
required init(fail: String) { } // okay to remove failability
}
class C2b : P2 {
required init?(fail: String) { } // okay, ? matches
}
class C2c : P2 {
required init!(fail: String) { } // okay to satisfy init? with init!
}
class C3a : P3 {
required init(failIUO: String) { } // okay to remove failability
}
class C3b : P3 {
required init?(failIUO: String) { } // okay to satisfy ! with ?
}
class C3c : P3 {
required init!(failIUO: String) { } // okay, ! matches
}
// ----------------------------------------------------------------------------
// Initiating failure
// ----------------------------------------------------------------------------
struct InitiateFailureS {
init(string: String) { // expected-note{{use 'init?' to make the initializer 'init(string:)' failable}}{{7-7=?}}
return (nil) // expected-error{{only a failable initializer can return 'nil'}}
}
init(int: Int) {
return 0 // expected-error{{'nil' is the only return value permitted in an initializer}}
}
init?(double: Double) {
return nil // ok
}
init!(char: Character) {
return nil // ok
}
}