mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
When a subclass inherits from a superclass that declares a no-args desginated initializer and no other visible inits, the subclass may elide calls to 'super.init()'. The way this was enforced was by looking into the superclass *from the subclass' init*, not from the subclass. This ensured that not only would we get results for initializers, we'd get results for initializers that were actually _callable_ from the subclass. The changes in apple/swift#33515 accidentally swapped the decl context here, which caused this lookup to start returning additional results. In that case, we consider it ambiguous as to which designated initializer we should synthesize, and so we bail. The net result is DI errors where there previously were none. Let's put this back in order. rdar://67560590, rdar://67686660, rdar://67690116, SR-13427
281 lines
8.9 KiB
Swift
281 lines
8.9 KiB
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/OtherModule.swiftmodule %S/Inputs/definite_init_cross_module/OtherModule.swift
|
|
// RUN: %target-swift-frontend -emit-sil -verify -I %t -swift-version 5 %s > /dev/null -enable-objc-interop -disable-objc-attr-requires-foundation-module -import-objc-header %S/Inputs/definite_init_cross_module/BridgingHeader.h
|
|
|
|
// RUN: %empty-directory(%t)
|
|
// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/OtherModule.swiftmodule %S/Inputs/definite_init_cross_module/OtherModule.swift
|
|
// RUN: %target-swift-frontend -emit-sil -verify -I %t -swift-version 5 %s > /dev/null -enable-objc-interop -disable-objc-attr-requires-foundation-module -import-objc-header %S/Inputs/definite_init_cross_module/BridgingHeader.h
|
|
|
|
import OtherModule
|
|
|
|
extension Point {
|
|
init(xx: Double, yy: Double) {
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
self.y = yy // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
|
|
init(xx: Double) {
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
|
|
init(xxx: Double, yyy: Double) {
|
|
// This is OK
|
|
self.init(x: xxx, y: yyy)
|
|
}
|
|
|
|
init(other: Point) {
|
|
// This is OK
|
|
self = other
|
|
}
|
|
|
|
init(other: Point, x: Double) {
|
|
// This is OK
|
|
self = other
|
|
self.x = x
|
|
}
|
|
|
|
init(other: Point, xx: Double) {
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
self = other
|
|
}
|
|
|
|
init(other: Point, x: Double, cond: Bool) {
|
|
// This is OK
|
|
self = other
|
|
if cond { self.x = x }
|
|
}
|
|
|
|
init(other: Point, xx: Double, cond: Bool) {
|
|
if cond { self = other }
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
self.y = 0 // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
|
|
// Test failable initializer.
|
|
init?(p: Point) {
|
|
if p.x > 0 {
|
|
self = p
|
|
}
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
}
|
|
|
|
extension GenericPoint {
|
|
init(xx: T, yy: T) {
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
self.y = yy // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
|
|
init(xxx: T, yyy: T) {
|
|
// This is OK
|
|
self.init(x: xxx, y: yyy)
|
|
}
|
|
|
|
init(other: GenericPoint<T>) {
|
|
// This is OK
|
|
self = other
|
|
}
|
|
|
|
init(other: GenericPoint<T>, x: T) {
|
|
// This is OK
|
|
self = other
|
|
self.x = x
|
|
}
|
|
|
|
init(other: GenericPoint<T>, xx: T) {
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
self = other
|
|
}
|
|
|
|
init(other: GenericPoint<T>, x: T, cond: Bool) {
|
|
// This is OK
|
|
self = other
|
|
if cond { self.x = x }
|
|
}
|
|
|
|
init(other: GenericPoint<T>, xx: T, cond: Bool) {
|
|
if cond { self = other }
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
self.y = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
}
|
|
|
|
extension GenericPoint where T == Double {
|
|
init(xx: Double, yy: Double) {
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
self.y = yy // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
|
|
init(xxx: Double, yyy: Double) {
|
|
// This is OK
|
|
self.init(x: xxx, y: yyy)
|
|
}
|
|
|
|
init(other: GenericPoint<Double>) {
|
|
// This is OK
|
|
self = other
|
|
}
|
|
|
|
init(other: GenericPoint<Double>, x: Double) {
|
|
// This is OK
|
|
self = other
|
|
self.x = x
|
|
}
|
|
|
|
init(other: GenericPoint<Double>, xx: Double) {
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
self = other
|
|
}
|
|
|
|
init(other: GenericPoint<Double>, x: Double, cond: Bool) {
|
|
// This is OK
|
|
self = other
|
|
if cond { self.x = x }
|
|
}
|
|
|
|
init(other: GenericPoint<Double>, xx: Double, cond: Bool) {
|
|
if cond { self = other }
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
self.y = 0 // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
}
|
|
|
|
typealias MyGenericPoint<Q> = GenericPoint<Q>
|
|
|
|
extension MyGenericPoint {
|
|
init(myX: T, myY: T) {
|
|
self.x = myX // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
self.y = myY // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
}
|
|
|
|
extension CPoint {
|
|
init(xx: Double, yy: Double) {
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}} expected-note {{use "self.init()" to initialize the struct with zero values}} {{5-5=self.init()\n}}
|
|
self.y = yy // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
|
|
init(xxx: Double, yyy: Double) {
|
|
// This is OK
|
|
self.init(x: xxx, y: yyy)
|
|
}
|
|
|
|
init(other: CPoint) {
|
|
// This is OK
|
|
self = other
|
|
}
|
|
|
|
init(other: CPoint, x: Double) {
|
|
// This is OK
|
|
self = other
|
|
self.x = x
|
|
}
|
|
|
|
init(other: CPoint, xx: Double) {
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}} expected-note {{use "self.init()" to initialize the struct with zero values}} {{5-5=self.init()\n}}
|
|
self = other
|
|
}
|
|
|
|
init(other: CPoint, x: Double, cond: Bool) {
|
|
// This is OK
|
|
self = other
|
|
if cond { self.x = x }
|
|
}
|
|
|
|
init(other: CPoint, xx: Double, cond: Bool) {
|
|
if cond { self = other }
|
|
self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
self.y = 0 // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
}
|
|
|
|
|
|
extension NonnullWrapper {
|
|
init(p: UnsafeMutableRawPointer) {
|
|
self.ptr = p // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
|
|
// No suggestion for "self.init()" because this struct does not support a
|
|
// zeroing initializer.
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
}
|
|
|
|
|
|
extension PrivatePoint {
|
|
init(xxx: Double, yyy: Double) {
|
|
// This is OK
|
|
self.init(x: xxx, y: yyy)
|
|
}
|
|
|
|
init(other: PrivatePoint) {
|
|
// This is OK
|
|
self = other
|
|
}
|
|
|
|
init(other: PrivatePoint, cond: Bool) {
|
|
if cond { self = other }
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
|
|
init() {
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
}
|
|
|
|
extension Empty {
|
|
init(x: Double) {
|
|
// This is OK
|
|
self.init()
|
|
}
|
|
|
|
init(other: Empty) {
|
|
// This is okay
|
|
self = other
|
|
}
|
|
|
|
init(other: Empty, cond: Bool) {
|
|
if cond { self = other }
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
|
|
init(xx: Double) {
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
}
|
|
|
|
extension GenericEmpty {
|
|
init(x: Double) {
|
|
// This is OK
|
|
self.init()
|
|
}
|
|
|
|
init(other: GenericEmpty<T>) {
|
|
// This is okay
|
|
self = other
|
|
}
|
|
|
|
init(other: GenericEmpty<T>, cond: Bool) {
|
|
if cond { self = other }
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
|
|
init(xx: Double) {
|
|
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
|
|
}
|
|
|
|
class AcceptsVisibleNoArgsDesignatedInit: VisibleNoArgsDesignatedInit {
|
|
var y: Float
|
|
init(y: Float) {
|
|
self.y = y
|
|
// no error
|
|
}
|
|
}
|
|
|
|
open class InModuleVisibleNoArgsDesignatedInit {
|
|
var x: Float
|
|
public init() { x = 0.0 }
|
|
|
|
// Add a designated init the subclass cannot see.
|
|
private init(x: Float) { self.x = x }
|
|
}
|
|
|
|
class AcceptsInModuleVisibleNoArgsDesignatedInit: InModuleVisibleNoArgsDesignatedInit {
|
|
var y: Float
|
|
init(y: Float) {
|
|
self.y = y
|
|
// no error
|
|
}
|
|
}
|