Files
swift-mirror/test/Inputs/resilient_class.swift
Slava Pestov 194b80049c Sema: Lazy property setters should not be transparent
A lazy property setter stores a value to the underlying storage
of the lazy property. The underlying storage is private, and it
is not proper for a public transparent function body to reference
a private member.

In practice, this only failed if the private member had a
non-constant offset, which only occurs with subclasses of @objc
classes, and resilient classes.

For @objc classes we already had a workaround where no accessors
for stored properties are ever transparent. I put this in to fix
this very issue with lazy properties, but now I realize it was
the wrong workaround, because we still had this problem with
resilient classes.

Note that I'm keeping the logic which made @objc accessors
non-transparent in place, because there's a good chance we will
decide that field offset globals should always be private.

Also, to make this issue reproducible in the test, I changed the
resilience execution tests to build the resilient library as a
dylib and link against that instead of just linking .o files
together. This is because .o files can see each other's internal
symbols, so I was not able to reproduce the original failure
this way. I went ahead and updated the other resilient tests to
do this as well. Also, each test now builds in WMO and non-WMO
mode, to exercise different SIL linking behavior. Again, the
WMO variant was needed to reproduce the issue fixed by this
commit, because without WMO we currently discard serialized SIL,
so no cross-module inlining of the lazy property setter was
taking place.
2017-08-29 01:22:11 -07:00

221 lines
4.6 KiB
Swift

import resilient_struct
// Fixed-layout, fixed-size base class
@_fixed_layout
open class OutsideParent {
open var property: String = "OutsideParent.property"
open class var classProperty: String {
return "OutsideParent.classProperty"
}
public init() {
print("OutsideParent.init()")
}
open func method() {
print("OutsideParent.method()")
}
open class func classMethod() {
print("OutsideParent.classMethod()")
}
}
// Fixed-layout, resiliently-sized base class
@_fixed_layout
open class OutsideParentWithResilientProperty {
public let p: Point
public let s: Size
public let color: Int32
public final lazy var laziestNumber = 0
public init(p: Point, s: Size, color: Int32) {
self.p = p
self.s = s
self.color = color
}
}
// Resilient base class
open class ResilientOutsideParent {
open var property: String = "ResilientOutsideParent.property"
public final var finalProperty: String = "ResilientOutsideParent.finalProperty"
open class var classProperty: String {
return "ResilientOutsideParent.classProperty"
}
public init() {
print("ResilientOutsideParent.init()")
}
open func method() {
print("ResilientOutsideParent.method()")
}
open class func classMethod() {
print("ResilientOutsideParent.classMethod()")
}
}
// Fixed-layout, fixed-size subclass
@_fixed_layout
open class OutsideChild : OutsideParent {
open override func method() {
print("OutsideChild.method()")
super.method()
}
open override class func classMethod() {
print("OutsideChild.classMethod()")
super.classMethod()
}
}
// Resilient subclass
open class ResilientOutsideChild : ResilientOutsideParent {
open override func method() {
print("ResilientOutsideChild.method()")
super.method()
}
open override class func classMethod() {
print("ResilientOutsideChild.classMethod()")
super.classMethod()
}
}
// Fixed-layout, dependently-sized, generic base class
@_fixed_layout
open class GenericOutsideParent<A> {
open var property: A
public init(property: A) {
self.property = property
print("GenericOutsideParent.init()")
}
open func method() {
print("GenericOutsideParent.method()")
}
open class func classMethod() {
print("GenericOutsideParent.classMethod()")
}
}
// Resilient generic base class
open class ResilientGenericOutsideParent<A> {
open var property: A
public init(property: A) {
self.property = property
print("ResilientGenericOutsideParent.init()")
}
open func method() {
print("ResilientGenericOutsideParent.method()")
}
open class func classMethod() {
print("ResilientGenericOutsideParent.classMethod()")
}
}
// Fixed-layout, dependently-sized, generic subclass
@_fixed_layout
open class GenericOutsideChild<A> : GenericOutsideParent<A> {
public override init(property: A) {
print("GenericOutsideGenericChild.init(a: A)")
super.init(property: property)
}
open override func method() {
print("GenericOutsideChild.method()")
super.method()
}
open override class func classMethod() {
print("GenericOutsideChild.classMethod()")
super.classMethod()
}
}
// Resilient generic subclass
open class ResilientGenericOutsideChild<A> : ResilientGenericOutsideParent<A> {
public override init(property: A) {
print("ResilientGenericOutsideGenericChild.init(a: A)")
super.init(property: property)
}
open override func method() {
print("ResilientGenericOutsideChild.method()")
super.method()
}
open override class func classMethod() {
print("ResilientGenericOutsideChild.classMethod()")
super.classMethod()
}
}
// Fixed-layout, fixed-size subclass of generic class
@_fixed_layout
open class ConcreteOutsideChild : GenericOutsideParent<String> {
public override init(property: String) {
print("ConcreteOutsideChild.init(property: String)")
super.init(property: property)
}
open override func method() {
print("ConcreteOutsideChild.method()")
super.method()
}
open override class func classMethod() {
print("ConcreteOutsideChild.classMethod()")
super.classMethod()
}
}
// Resilient subclass of generic class
open class ResilientConcreteOutsideChild : ResilientGenericOutsideParent<String> {
public override init(property: String) {
print("ResilientConcreteOutsideChild.init(property: String)")
super.init(property: property)
}
open override func method() {
print("ResilientConcreteOutsideChild.method()")
super.method()
}
open override class func classMethod() {
print("ResilientConcreteOutsideChild.classMethod()")
super.classMethod()
}
}