Overloaded constructors in 2331 now fail to compile (Silver/Cooper)?

(Jon Nermut) #1

This valid swift used to compile as recently as .2321, but doesn’t in .2331, it gives a “Duplicate constructor” error. Which I’m guessing is fair enough in Java where you can’t overload constructors, but it used to work fine?

/// Used when an API can return String data or a fatal error.
open class DataOrError: NSObject
    fileprivate(set) open var error: String?
    fileprivate(set) open var data: String?
    public init(data: String)
        self.data = data
    public init(error: String)
        self.error = error
    open class func data(_ data: String) -> DataOrError
        return DataOrError(data: data)
    open class func error(_ error: String) -> DataOrError
        return DataOrError(error: error)

Similarly, all calls to DataOrError(error: ‘blah’) also fail to compile.

(Carlo Kok) #2

This is an unfortunate limitation of java itself. Constructors can’t be named there so they’ll match on their types. You can create a private init method that takes both error and data, and public convenience constructors that call those to get around this.

(Jon Nermut) #3

Thanks Carlo.
Interestingly the convenience inits suffered the same problem, but I will just change all the calling code to call the existing statics anyway:

(RemObjects) #4

Thanks, logged as bugs://81138

(Carlo Kok) #5

Yeah it’s a bit tricky. I thought convenience did a trick here but was confused. I’m going to see how to best solve this but for now your workaround will have to do.

(Jon Nermut) #6

Thanks, in this case there were only a dozen or so callers, so no big deal

(Jon Nermut) #7

Carlo, got more strangeness with constructors in 2331. This looks like a reasonably serious regression in 2331, and possibly related to the above.

The attached project is a small repro of a problem I’m having with constructors of Swift superclass and Java base class.

consoleapplication79999.zip (208.3 KB)

public typealias OpaquePointer = Int32
public class BasePtrWrapper
    internal var address: OpaquePointer

    public required init(ptr: OpaquePointer)
        self.address = ptr


open class AuthToken  : BasePtrWrapper
    public required init(ptr: OpaquePointer)
        super.init(ptr: ptr)

let at = AuthToken(ptr: 333)

Running it gives
!> Fatal exception of type java.lang.VerifyError on thread 0001 ()
!> Message: java.lang.VerifyError: (class: consoleapplication79999/__Global, method: main$ signature: ([Ljava/lang/String;)I) Call to wrong initialization method

If you uncomment out the overridden constructor, you get a similar error.
I can’t work out what’s actually the determining factor here.

In my actual project I end up with decompiled code that looks like this:

public class AuthToken extends BasePtrWrapper {
    public AuthToken(int ptr) {
        Object Result = null;
        return Result;

Where returning a value from a constructor is the bytecode problem I guess.

Any workarounds appreciated, as its yet another blocker trying to upgrade to Fire 10, which I’ve been on for ~6 weeks now.

(RemObjects) #8

bugs://81138 got closed with status fixed.

(Carlo Kok) #9

Curious issue. For Island/Darwin we added Cocoa support and different class models. @Objc makes a class into those, and it confused the compiler. Fixed now.

(Jon Nermut) #10

Ah, thanks. The @objc is for the XCode cross compile. I’ll comment them out FTB so I can keep moving.