Generated .swiftinterface has wrong content?

I compile RxSwift (v5.0.1) on Xcode 11 beta7 with flags

-enable-library-evolution -emit-parseable-module-interface-path $(BUILT_PRODUCTS_DIR)/arm64.swiftinterface

to get a stable module interface. Then I import the generated arm64.swiftinterface file and the .a to another demo project, I got a compile error.

(update: I also used BUILD_LIBRARY_FOR_DISTRIBUTION flag method, and still got the same result. The detail steps are describe in the reply)

I wonder it may be a bug of compiler. The generated swiftinterface have the wrong content. When I add the missing init() method in the generated swiftinterface file, It runs correctly.

The header in the swiftinterface file:

// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.1 (swiftlang-1100.0.266.1 clang-1100.0.32.1)
// swift-module-flags: -target arm64-apple-ios8.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name RxSwift

The RxSwift source code

/// Base class for all disposables.
public class DisposeBase {
    init() {
#if TRACE_RESOURCES
    _ = Resources.incrementTotal()
#endif
    }
    
    deinit {
#if TRACE_RESOURCES
    _ = Resources.decrementTotal()
#endif
    }
}


public final class DisposeBag: DisposeBase {
    
    private var _lock = SpinLock()
    
    // state
    fileprivate var _disposables = [Disposable]()
    fileprivate var _isDisposed = false
    
    /// Constructs new empty dispose bag.
    public override init() {
        super.init()
    }
2 Likes

This is at least one bug and possibly two. DisposeBase doesn't have a public init, and so calling DisposeBag's init an override is incorrect from outside the module. However, I'm not sure we actually implement this correctly (where calling DisposeBag's init from a convenience initializer works without being able to see DisposeBase's init), so the broken interface is potentially protecting you from this issue.

We have a Radar for this already, but no Jira. Mind filing one? (https://bugs.swift.org)

cc @harlanhaskins, @Slava_Pestov

I tested serval libraries and found it pretty common to get an error:

  • correct: lottie-ios, SnapKit
  • got errors: Alamofire, SwiftyJSON, RxSwift

Here's a detail description to reproduce the errors:

  1. generate a project with a framework target with cocoapods (you can use pod try XXX).
  2. set the build settings of framework target: build library for distribution to YES
  3. build the framework and got the framework file. Delete the the .swiftmodule files in the framework.
  4. make a new blank iOS demo project, and import the framework we modified last step, and add the import XXX in source files
  5. build and got errors

jira bug [SR-11422] Generated .swiftinterface got an error when imported · Issue #53823 · apple/swift · GitHub

2 Likes

@harlanhaskins Is there a way we could opt libraries in the swift source compat suite into swiftinterface support so we can possibly catch some of these issues? I'm not sure it would have caught this specifically but it seems like that may help surface some adoption blockers

2 Likes

Testing RxSwift with Xcode 11.4, still got a lot errors. Report 3 bugs SR-12653 SR-12647 SR-12646. Wish it could be fixed in Swift 5.3.

1 Like

Thank you for the bug reports. The first one is already fixed in swift-5.3-branch and the second is a dupe of a known issue. I'll try to tackle the third one at some point.

In the meantime, there's unfortunately no real workaround for the first bug, other than making the overridden initializer public in the original API.

A possible workaround for bug #2 and #3 is to pass the -module-interface-preserve-types-as-written flag when building the interface file.

2 Likes

Hey where do you set this flag ? sorry I am pretty new to swift but facing a similar problem with module interface files

to pass it to xcodebuild use OTHER_SWIFT_FLAGS="-Xfrontend -module-interface-preserve-types-as-written"