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-7319] Function invocations returning generics fail with ambiguous use after Swift 4.1 upgrade #49867

Closed
iby opened this issue Mar 31, 2018 · 9 comments
Assignees
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

@iby
Copy link

iby commented Mar 31, 2018

Previous ID SR-7319
Radar rdar://problem/39143215
Original Reporter @iby
Type Bug
Status Resolved
Resolution Invalid

Attachment: Download

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

md5: 3f77184580bbb57ed556d04b7eaea88e

Issue Description:

This code used to work yesterday:

struct G<X> { var x: X? }

func g1<T>(key: String) -> G<T> { return G() }
func g1<T>(key: String) -> G<T?> { return G() }

func g2<T>(key: T) -> T { return key }
func g2<T>(key: T) -> T? { return key }

let x1: G<String> = g1(key: "foo")
let x2: G<String?> = g1(key: "foo")
let y1: String = g2(key: "foo")
let y2: String? = g2(key: "foo")

Now it reports:

error: Playground.playground:4:22: error: ambiguous use of 'g1(key:)'
let x2: G<String?> = g1(key: "foo")

It appears it doesn't see difference between optional and non-optional generic parameters in return and treats them equally. This however doesn't apply to regular optional/non-optional generic return type – it invokes correct function in case with g2. Changing function signature makes this go away. Is there any other workaround?

@belkadan
Copy link
Contributor

belkadan commented Apr 3, 2018

cc @xedin, @rudkx

@swift-ci create

@rudkx
Copy link
Member

rudkx commented Apr 3, 2018

@iby, what is the output of running swiftc --version with the compiler that worked as expected vs. the one that did not?

@iby
Copy link
Author

iby commented Apr 3, 2018

One that ships with latest Xcode 9.2:

Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2)
Target: x86_64-apple-macosx10.9

@rudkx
Copy link
Member

rudkx commented May 11, 2018

@iby, I tried your example with Xcode 9.2 (and earlier Xcodes) and see the same error about the call to g1 being ambiguous.

I agree offhand this seems like something we should be able to disambiguate, but I don't think this is a regression from Xcode 9.2.

Are you sure this code is representative of what you had compiled successfully with Xcode 9.2?

@iby
Copy link
Author

iby commented May 12, 2018

@rudkx yes, I missed elephant in the room. Frankly, this all comes down to Equatable conformance:

@rudkx
Copy link
Member

rudkx commented May 15, 2018

The difference in behavior here is a result of {Optional} becoming {Equatable}. Previously there was a single overload that worked for type checking:

let x2: G<String?> = g1(key: "foo")

but now both overloads work, and neither is considered better.

@rudkx
Copy link
Member

rudkx commented May 15, 2018

The only workaround that comes to mind for disambiguating here is somewhat ugly. You could add a dummy protocol requirement and extensions for the (non-Optional) types that you'd like to use this with, e.g.:

protocol P {}
extension String : P {}

func g1<T: Equatable & P>(key: String) -> G<T> { return G() }
func g1<T: Equatable & P>(key: String) -> G<T?> { return G() }

let x2: G<String?> = g1(key: "foo")

@iby
Copy link
Author

iby commented May 15, 2018

Thanks for looking into and suggestions. I didn't realise the issue was so broad and not just a regression. The fact that it was working all that time is just me being lucky. I'll refactor the code, but I think it's a good idea to be able to disambiguate these things.

@rudkx
Copy link
Member

rudkx commented May 15, 2018

Yes I agree it would be good if we could find a principled way to disambiguate here.

Thanks for reporting this.

@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