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-1422] Swift uses wrong default implementation for function defined in constrained and unconstrained protocol extensions #44031

Closed
swift-ci opened this issue May 5, 2016 · 1 comment

Comments

@swift-ci
Copy link
Collaborator

@swift-ci swift-ci commented May 5, 2016

Previous ID SR-1422
Radar None
Original Reporter armadsen (JIRA User)
Type Bug
Status Resolved
Resolution Invalid
Environment

Version 7.3 (7D175), default Swift toolchain (Swift 2.2).

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

md5: 0098b0c022008b618a21975f5c6952d4

Issue Description:

Take a protocol, with a protocol extension providing a default implementation of function A, which in turn calls function B. Function B has two default implmentations: one in an extension of the protocol which is constrained to a particular type, another in an unconstrained extension.

When calling function B directly on an instance of the type which matches the constrained extension's constraint, the correct implementation is used. That is, the implementation in the constrained extension.

However, when function A is called, it's call to function B always uses the implementation in the unconstrained extension.

This seems counter to the following in the Swift book:

If a conforming type satisfies the requirements for multiple constrained extensions that provide implementations for the same method or property, Swift will use the implementation corresponding to the most specialized constraints.

The following code demonstrates this (can be run in a playground):

class Bar: Foo {}
class Qux: Foo {}

protocol Foo {}

extension Foo {
    func callFooFromExtension() {
        foo()
    }
}

extension Foo {
    func foo() {
        NSLog("Plain foo")
    }
}

extension Foo where Self: Qux {
    func foo() {
        NSLog("Qux foo")
    }
}

let b = Bar()
let q = Qux()

b.foo() // Logs "Plain foo"
b.callFooFromExtension() // Logs "Plain foo"

q.foo() // Logs "Qux foo"
q.callFooFromExtension() // Logs "Plain foo", which is unexpected

If foo() is declared in the protocol itself, this problem does not occur:

protocol Foo {
    func foo()
}

q.callFooFromExtension() // Logs "Qux foo", as expected
@belkadan
Copy link
Contributor

@belkadan belkadan commented May 5, 2016

Overload resolution is done at compile-time, not at run-time.

@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
Projects
None yet
Development

No branches or pull requests

2 participants