Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example of https://bugs.swift.org/browse/SR-6004, and instructions on how to work around it #38

Merged
merged 14 commits into from
Feb 7, 2019
27 changes: 27 additions & 0 deletions App/ViewController.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import UIKit
import Swift2
import Swift3
import Swift4
import CryptoSwift
import Objc1
import SwiftAndObjc
Expand Down Expand Up @@ -61,6 +62,32 @@ class ViewController: UIViewController {
// This line will crash if the assets from SwiftWithAssets haven't been bundled into the app
_ = Catalog.buck.image

// Without an object explicitly typed as `MyPublicClass`, an instance of `MyPublicClass` won't
// exhibit conformance to `MyPublicProtocol`. `MyPublicClass` is defined in `Swift4`.
// `MyPublicProtocol` and the conformance of `MyPublicClass` to `MyPublicProtocol` is defined in
// `Swift3`.
//
// One workaround when possible is to make sure the object is explictly typed as `MyPublicClass`
// and avoid type erasure. You can see this in action by swapping the way that we are creating
// `myObject` below to be `MyPublicClass()` instead of `MyFactory.myPublicObject()`.
//
// Avoiding type erasure is not always possible though. Another way to workaround this bug is to
// annotate `MyPublicProtocol` with `@objc`. We pass `-ObjC` to "Other Linker Flags", which will
// cause this conformance to not be stripped. Annotating the actual conformance of
// `MyPublicClass` to `MyPublicProtocol` will also work and is a bit less invasive.
//
// `-force_load`ing the module where the conformance exists also works.
//
// This is tracked by https://bugs.swift.org/browse/SR-6004. This seems to indicate that
// `-all_load` will work too, but we haven't verified that.
// let myObject = MyPublicClass()
let myObject = MyFactory.myPublicObject()
if (myObject as? MyPublicProtocol) == nil {
print("Incorrect: `MyPublicProtocol` conformance is being erroneously stripped")
} else {
print("Correct: `MyPublicProtocol` conformance is not being stripped")
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it worth writing the above as a unit test?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a good idea. I'm gonna leave as-is for now but something to think about down the road. 🤞 Apple fixes this soon since it's affecting both Airbnb and Lyft (and this presumably other big companies as well!)


print("All good!")
}
}
15 changes: 15 additions & 0 deletions Libraries/Swift3/Sources/MyPublicClass+MyPublicProtocol.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// MyPublicClass+MySecondPublicProtocol.swift
// Swift3
//
// Created by Michael Bachand on 2/6/19.
//

import Foundation
import Swift4

extension MyPublicClass: MyPublicProtocol {
public var currrentThought: String {
return "This should be visible in the main module!"
}
}
12 changes: 12 additions & 0 deletions Libraries/Swift3/Sources/MyPublicProtocol.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// MySecondPublicProtocol.swift
// Swift3
//
// Created by Michael Bachand on 2/6/19.
//

import Foundation

public protocol MyPublicProtocol {
var currrentThought: String { get }
}
15 changes: 15 additions & 0 deletions Libraries/Swift4/Sources/MyFactory.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// MyFactory.swift
// Swift4
//
// Created by Michael Bachand on 2/6/19.
//

import Foundation

public class MyFactory {
/// Returns a type-erased instance of `MyPublicClass`.
public static func myPublicObject() -> Any {
return MyPublicClass()
}
}
12 changes: 12 additions & 0 deletions Libraries/Swift4/Sources/MyPublicClass.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// MyPublicClass.swift
// Swift4
//
// Created by Michael Bachand on 2/6/19.
//

import Foundation

public final class MyPublicClass {
public init() { }
}