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

Ambiguous initializers #125

Closed
1 of 2 tasks
lhunath opened this issue Nov 12, 2021 · 5 comments · Fixed by #169
Closed
1 of 2 tasks

Ambiguous initializers #125

lhunath opened this issue Nov 12, 2021 · 5 comments · Fixed by #169
Labels
bug Something isn't working
Milestone

Comments

@lhunath
Copy link

lhunath commented Nov 12, 2021

Duplicate initializers for OrderedDictionary cause ambiguity in the compiler when it tries to resolve an initializer, however only under certain circumstances. I'm not 100% certain about what the scope of the issue is, but have included sample code for a data point on where the issue is reproduced.

The issue also reproduces in other scenarios which do not look like the included sample (in more complex projects).

Competing initializers:

Information

  • Package version: 1.0.1
  • Platform version: macOS 11.3.1 (20E241)
  • Swift version: 5.5.1 (swiftlang-1300.0.31.4 clang-1300.0.29.6)

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Steps to Reproduce

let names = ["dylan", "bob", "aaron", "carol"]
let dict1 = OrderedDictionary(uniqueKeysWithValues: names.map { ($0, 0) })
let dict2 = OrderedDictionary(uniqueKeysWithValues: ["dylan", "bob", "aaron", "carol"].map { ($0, 0) })

Expected behavior

Notice that dict1 initialization compiles fine. I expect dict2 initialization to compile fine as well.

Actual behavior

dict2 initialization fails, error:

/Users/lhunath/workspace/local/Sandbox/Sandbox/SandApp.swift:25:17: error: ambiguous use of 'init(uniqueKeysWithValues:)'
    let dict2 = OrderedDictionary(uniqueKeysWithValues: ["dylan", "bob", "aaron", "carol"].map { ($0, 0) })
                ^
/Users/lhunath/Library/Developer/Xcode/DerivedData/Sandbox-cngswxsbmagplshicoojnvdjrear/SourcePackages/checkouts/swift-collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Initializers.swift:79:10: note: found this candidate
  public init<S: Sequence>(
         ^
/Users/lhunath/Library/Developer/Xcode/DerivedData/Sandbox-cngswxsbmagplshicoojnvdjrear/SourcePackages/checkouts/swift-collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Initializers.swift:115:10: note: found this candidate
  public init<S: Sequence>(
         ^
@lhunath lhunath added the bug Something isn't working label Nov 12, 2021
@lhunath
Copy link
Author

lhunath commented Nov 12, 2021

Although I haven't yet been able to reduce it to a reproducible example, the following code also fails:

class X {
    private let coreDaily:   [CppReportWorkDaySummary]
    lazy var daily: OrderedDictionary<Date, ReportMetrics?> = .init(uniqueKeysWithValues: self.coreDaily.map {
        ($0.dayDate, $0.summary.flatMap(CoreReportMetrics.init))
    })
}

In this case, the trigger appears to be $0.summary.flatMap(CoreReportMetrics.init) - replacing it with nil removes the compiler error.

(127, 64) Ambiguous use of 'init(uniqueKeysWithValues:)'

@lorentey
Copy link
Member

Interesting! We have two overloads for these, one for sequences where Element == (Key, Value) and another for Element == (key: Key, value: Value). I'm guessing the tuple labels can be inferred in your second example, which makes the expression ambiguous.

I think the candidate that requires inferring tuple labels ought to be considered less favored than the one where labels line up, so this is arguably a compiler issue -- cc @hborla what do you think?

@lhunath
Copy link
Author

lhunath commented Nov 13, 2021

My naive expectation was that the labels are mostly sugar and a distinction between them is unnecessary; though I was surprised the compiler even allowed overloading method signatures where labels are the only distinguishing feature.

@lorentey
Copy link
Member

lorentey commented Dec 1, 2021

I wrote up the issue in https://bugs.swift.org/browse/SR-15539. While the type checker problem is being investigated, we can use the non-public, underscored @_disfavoredOverload attribute to work around this bug. That attribute isn't stable, so using it needs to be weighed against the possibility of source compatibility problems with future versions of the Swift compiler.

The client-level workaround is to move the dictionary literal into its own variable, as you have shown above. This eliminates the type inference case that triggers the issue.

@lorentey lorentey added this to the 1.0.3 milestone Aug 31, 2022
@lorentey lorentey linked a pull request Sep 1, 2022 that will close this issue
7 tasks
@lorentey
Copy link
Member

lorentey commented Sep 2, 2022

This is now fixed on the release/1.0 branch. (Merge to main will happen after 1.0.3 is tagged.)

@lorentey lorentey closed this as completed Sep 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants