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

[SR-7078] Swift 4.1 Type Checker: Ambiguous init #49626

Closed
swift-ci opened this issue Feb 26, 2018 · 5 comments
Closed

[SR-7078] Swift 4.1 Type Checker: Ambiguous init #49626

swift-ci opened this issue Feb 26, 2018 · 5 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 4.1 type checker Area → compiler: Semantic analysis

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-7078
Radar None
Original Reporter benasher44 (JIRA User)
Type Bug
Status Closed
Resolution Cannot Reproduce
Environment

Xcode 9.3 beta 3 (and tried swift-DEVELOPMENT-SNAPSHOT-2018-02-25-a)

macOS 10.13.3

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, 4.1Regression, TypeChecker
Assignee None
Priority Medium

md5: 084197e72d572e4b37aaf525ea44cb15

Issue Description:

I've found a case where Swift 4.0's type checker doesn't error, but Swift 4.1 can't decide which init to use. That said, I can only reproduce it in our large project in Xcode (so it goes). I've done my best to try to recreate it in a small file, but this file compiles just fine. I'm hoping that by describing this, maybe someone with more knowledge of the type checker will be able to suss out what's going on here:

import Foundation

protocol ProtocolD {
    static var v: String { get }
}

protocol ProtocolA: ProtocolD {
    associatedtype T
    var s: String { get }
}

protocol ProtocolB {
    var t: String { get }
}

@objc protocol ProtocolC: NSObjectProtocol {
    var s: String { get }
}

final class A: NSObject, ProtocolA, ProtocolB, ProtocolC {
    static let v = ""
    typealias T = A
    let t: String = ""
    var s: String { return self.t }
}

struct B {
    let s: String

    init<E: ProtocolA>(_ a: E) {
        self.s = a.s
    }

    // Candidate 1
    init<E: ProtocolA & ProtocolB>(_ a: E) {
        self.s = a.s
    }


    // Candidate 2
    init<E: ProtocolA & ProtocolB & ProtocolC>(_ a: E) {
        self.s = a.s
    }

    // Candidate 3
    init(_ b: ProtocolB) {
        self.s = b.t
    }
}

let a = A()

_ = B(a)

It failed on the last line trying to decide between the marked candidates 1 and 2 in my larger project. This file compiles fine on its own though.

FWIW, I would expect the type checker to pick candidate 2 because its the most specific, but it appears to pick candidate 3 (in Swift 4.1 and Swift 4.0 in this actual scenario where it compiles and runs fine).

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

If no leads can be made here on this information alone, let me know if there's any other info I can provide.

@belkadan
Copy link
Contributor

@xedin, @rudkx, any ideas?

@rudkx
Copy link
Member

rudkx commented Feb 26, 2018

Without a way to reproduce the ambiguity, it's difficult to know what's going on here.

As to why we select the overload that we do in the code you've pasted in, it's because we always prefer non-generic declarations at this time.

As your example shows, that choice may not be ideal. If we want to consider changing this at some point, we would have to do so under a particular Swift version and above, and would have to evaluate how much positive impact it would have versus how much code would break as a result, and what if anything we can do to automatically migrate code.

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

That makes sense and seems reasonable to me. Since I filed this, I figured out a way forward to improve our protocol situation here and reduce the number of initializers in our code. If I can come up with anything new, I'll be sure to update the ticket and reopen. Feel free to close!

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

We feel like we're well past this issue at this point, and we haven't been able to reproduce. Going to close.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 4.1 type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

4 participants