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-6108] "ambiguous use" on generic method after migration to swift 4 #48663

Open
swift-ci opened this issue Oct 10, 2017 · 6 comments
Open
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-6108
Radar None
Original Reporter tal952 (JIRA User)
Type Bug
Environment

xcode 8.0.2, swift 3.0.2.

xcode 9, swift 4 results.

Additional Detail from JIRA
Votes 2
Component/s Compiler
Labels Bug
Assignee @xedin
Priority Medium

md5: abbf0f3a13f9cc840bd37a00ebc73850

Issue Description:

This is a follow up to my stackoverflow question:

https://stackoverflow.com/questions/46649106/ambiguous-use-on-generic-method-after-migration-to-swift-4

I am trying to migrate my code from xcode 8.2 swift 3.0.2 to xcode 9 swift 4, and i have problem with this code:

func test<T0, TRet>(_ fn: (T0) -> TRet) -> Void {
    print("foo1")
    print(T0.self)
}

func test<T0, T1, TRet>(_ fn: (T0, T1) -> TRet) -> Void {
    print("foo2")
    print(T0.self)
    print(T1.self)
}


let fn2 : (Int, Int) -> Int = { (x:Int, y:Int)->Int in
    return x+y
}

test(fn2)

xcode 8.0.2, swift 3.0.2 results with:

foo2
Int
Int

xcode 9, swift 4 results with:

Playground execution failed:

error: MyPlayground.playground:12:1: error: ambiguous use of 'test'
test(fn2)
^

MyPlayground.playground:1:6: note: found this candidate
func test<T0, T1, TRet>(_ fn: (T0, T1) -> TRet) -> Void {
^

Am I missing something? Is there any new feature in swift 4 that causes this error?

@belkadan
Copy link
Contributor

@xedin, seems like a case where SE-0110 behaves worse in Swift 4 mode?

@xedin
Copy link
Member

xedin commented Oct 11, 2017

Looks like like a problem with ranking in the swift-version 4 mode because in compatibility mode we still find both of the solutions but somehow `test<T0, T1, TRet>` ranks higher than `test<T0, TRet>`. I'll try to take a closer look at this soon.

@swift-ci
Copy link
Collaborator Author

Comment by Petro Korienev (JIRA)

Observing similar issue, argument labels make the difference, this can be considered as temporary workaround: https://gist.github.com/soxjke/6c2dff8a8c255ff386f3c325d09300cf

@swift-ci
Copy link
Collaborator Author

swift-ci commented Apr 9, 2018

Comment by Sebastian Shanus (JIRA)

Hi there! Any update on this issue?

This is currently blocking our DI framework from upgrading to swift4 because we generate factory functions like:

```

public func to<P_1>(factory: @escaping (P_1) > Input) > BindingReceipt<Input> { ... }

public func to<P_1,P_2>(factory: @escaping (P_1,P_2) > Input) > BindingReceipt<Input> { ... }

```

etc.

@xedin
Copy link
Member

xedin commented Apr 10, 2018

sebastianv1 (JIRA User) Unfortunately you'd have to use a workaround for now, by adding labels as suggested or changing function names, ideally we'd have the second overload to match unambiguously but we need to do more refactoring of function type representation to get there.

@swift-ci
Copy link
Collaborator Author

Comment by Jeremy Lew (JIRA)

I ran into the same problem, and stumbled across a workaround that is (for my purposes) nicer than disambiguating via naming. Take the original repro code above, and alter it as follows:

func test<T0, TRet>( fn: (T0) -> TRet) -> Void
...to...
func test<T0, TRet>( fn: ((T0)) -> TRet) -> Void
(note the extra pair of parens around the T0 callback parameter, which explicitly makes it into a tuple-of-1)

After this change, test(fn2) compiles and calls the test<T0,T1,TRet>

It seems like the compiler is able to treat a function with N arguments as a function with one N-way-tuple argument. Hence, both the (T0) -> TRet and (T0,T1) -> TRet overloads are candidates for fn2, and the call is ambiguous. Adding 2nd pair of parens ((T0)) -> TRet limits that overload to an argument with a single parameter or 1-way tuple.

sebastianv1 (JIRA User): My problem was with a DI framework as well, perhaps this will help your case.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
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
Projects
None yet
Development

No branches or pull requests

3 participants