mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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
275 lines
7.8 KiB
Swift
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
|
|
}
|
|
}
|