swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.57k stars 10.35k forks source link

[SR-7126] Swift 4.1 protocol overlap ambiguous property #49674

Open keith opened 6 years ago

keith commented 6 years ago
Previous ID SR-7126
Radar rdar://problem/38394638
Original Reporter @keith
Type Bug
Environment Xcode 9.3b4
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug, 4.1Regression, TypeChecker | |Assignee | None | |Priority | Medium | md5: 4da24ed90ea99125ba6a2319ee32474e

relates to:

Issue Description:

With this code:

class Foo {
    var bar: String?
}

protocol ProtocolA {
    var foo: Foo? { get }
}

protocol ProtocolB {
    var foo: Foo? { get }
}

extension ProtocolB where Self: ProtocolA {
    func baz() {
        _ = self.foo // compiles
        _ = self.foo?.bar // compiles
        _ = self.foo?.bar != nil // compiles
        if self.foo?.bar != nil {} // doesn't compile
    }
}

With Xcode 9.3b4 and Swift 4.1 you get this error at compile time:

bar.swift:18:12: error: ambiguous use of 'foo'
        if self.foo?.bar != nil {}
           ^
bar.swift:10:9: note: found this candidate
    var foo: Foo? { get }
        ^
bar.swift:6:9: note: found this candidate
    var foo: Foo? { get }
        ^

This doesn't error with Xcode 9.2 and Swift 4.0.

jckarter commented 6 years ago

@swift-ci create

jckarter commented 6 years ago

All of these ought to be ambiguous in principle. We really shouldn't have different behavior in different contexts, and ideally 4.1 would preserve whatever behavior 4.0 had.

xwu commented 6 years ago

Wait, why? Any type that conforms to both `ProtocolA` and `ProtocolB` would be required by the compiler to implement an unambiguous `foo` that fulfills both requirements, no?

jckarter commented 6 years ago

I suppose in practice since ProtocolA and ProtocolB are in the same module here, you wouldn't in practice be able to make a type that has a different witness for both (without using @_implements). In full generality the conformances for ProtocolA and ProtocolB could have been formed independently, and we may expose the ability to map implementations to conformances explicitly with user-facing syntax.