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

Default subscript implementation added via a protocol is used instead type's own subscripts #62866

Open
snb opened this issue Jan 5, 2023 · 0 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself overload resolution Area → compiler → type checker: Overload resolution (ranking) overloading Feature: Overloading symbol names regression type checker Area → compiler: Semantic analysis

Comments

@snb
Copy link

snb commented Jan 5, 2023

Description

I have a project that began crashing at runtime upon upgrading to Xcode 14. I narrowed the problem down to a protocol we wrote and some extensions adding conformance to this protocol to library types, like Dictionary. The protocol also has a default implementation of subscripts, and prior to the upgrade to Xcode 14, Dictionary would still use its own subscripts. After the upgrade, now Dictionary seems to use the default subscript from our protocol instead, which happened to lead to circular calls and a stack overflow.

Steps to reproduce

Small code example that should demonstrate the problem more clearly:

import Foundation
    
protocol KeyValueStore {
    func value(forKey key: String) -> Any?
}

extension KeyValueStore {
    subscript(key: String) -> Any? {
        get {
            value(forKey: key)
        }
    }
}

extension Dictionary: KeyValueStore where Key == String, Value == Any {
    func value(forKey key: String) -> Any? {
        self[key]
    }
}

let d: [String: Any] = [:]
_ = d.value(forKey: "asdf")

print("could successfully use value()")

Expected behavior

With Xcode 13.4, the above code sample will run and print "could successfully use value()". On Xcode 14.2, it will crash before reaching the print statement. Checking the stack in the debugger shows that Dictionary.value(forKey:) invokes KeyValueStore's subscript implementation rather than Dictionary's own, which in turn calls Dictionary.value(forKey:) again and so on.

I'm not sure if Dictionary or KeyValueStore's subscript implementation should be used here, or if this is not actually defined behavior. It's easy enough to work around in my code but since the behaviour of Swift changed here between versions I figured I should report it in case there is a bug.

Environment

The sample code above runs fine on Xcode 13.4.1/Swift 5.6.1

> swiftc -version
swift-driver version: 1.45.2 Apple Swift version 5.6.1 (swiftlang-5.6.0.323.66 clang-1316.0.20.12)
Target: arm64-apple-macosx12.0
> xcodebuild -version
Xcode 13.4.1
Build version 13F100

The code crashes on Xcode 14.2/Swift 5.7.2

> swiftc -version
swift-driver version: 1.62.15 Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)
Target: arm64-apple-macosx12.0
> xcodebuild -version 
Xcode 14.2
Build version 14C18
@snb snb added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels Jan 5, 2023
@AnthonyLatsis AnthonyLatsis added compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis regression overload resolution Area → compiler → type checker: Overload resolution (ranking) overloading Feature: Overloading symbol names and removed triage needed This issue needs more specific labels labels Jan 8, 2023
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 overload resolution Area → compiler → type checker: Overload resolution (ranking) overloading Feature: Overloading symbol names regression type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

3 participants