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-7108] Generic usage complication thru nesting leads to Compilation error: Generic parameter could not be inferred #49656

Closed
swift-ci opened this issue Mar 2, 2018 · 4 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself diagnostics QoI Bug: Diagnostics Quality of Implementation type checker Area → compiler: Semantic analysis

Comments

@swift-ci
Copy link
Collaborator

swift-ci commented Mar 2, 2018

Previous ID SR-7108
Radar rdar://problem/38143705
Original Reporter melifaro (JIRA User)
Type Bug
Status Resolved
Resolution Done
Environment

macOS 10.13.3 (17D102)
Xcode 9.2
Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2)

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, DiagnosticsQoI, TypeChecker
Assignee melifaro (JIRA)
Priority Medium

md5: 9a7b97c03b4c56d3ca38833b490a79ec

Issue Description:

Consider following two examples. They are abstract. The first one is more complicated and produces compilation error: "Generic parameter could not be inferred" while the second - simplified version of the first compiles fine.

I expect no errors with the first example compilation as the type can be inferred in fact (and should).

First example (compiles with the error):

protocol FooProtocol {
    
    associatedtype Bar
    
    func doFoo(with bar: Bar)
}

class Bar {
    
}

class Foo: FooProtocol {
    
    func doFoo(with bar: Bar) {
        
        //..
    }
}

protocol ContainerProtocol {
    
    associatedtype Something
    
    func process(entity: Something)
}


class FooService<F: FooProtocol> {
    
    func doService<C>(container: C) -> C where C: ContainerProtocol, C.Something == F.Bar {
        
        return container
    }
}

protocol SomethingProtocol {
    
    associatedtype SomeType
    
    func doSomething(with value: SomeType)
}

class Container<S: SomethingProtocol>: ContainerProtocol {
    
    func process(entity: S) {
        //...
    }
}

class Something<S>: SomethingProtocol {
    
    func doSomething(with value: S) {
        //...
    }
}

class Client {
    
    init() {
        //ERROR HERE: Generic parameter 'C' could not be inferred
        let container: Container<Something<Bar>> = FooService<Foo>().doService(container: Container<Something<Bar>>())
    }
}

Second example (simplified, compiles fine):

protocol FooProtocol {
    
    associatedtype Bar
    
    func doFoo(with bar: Bar)
}

class Bar {
    
}

class Foo: FooProtocol {
    
    func doFoo(with bar: Bar) {
        
        //..
    }
}

protocol ContainerProtocol {
    
    associatedtype Something
    
    func process(entity: Something)
}


class FooService<F: FooProtocol> {
    
    func doService<C>(container: C) -> C where C: ContainerProtocol, C.Something == F.Bar {
        
        return container
    }
}

class Container<S>: ContainerProtocol {
    
    func process(entity: S) {
        
        //...
    }
}


class Client {
    
    init() {
        
        FooService<Foo>().doService(container: Container<Bar>())
    }
}
@belkadan
Copy link
Contributor

belkadan commented Mar 5, 2018

There actually is a problem in your code: C.Something is 'Something<Bar>', but F.Bar is just 'Bar'. But it would be nice if the diagnostic were clearer, or at least didn't say the wrong thing.

cc @xedin

@xedin
Copy link
Member

xedin commented Mar 5, 2018

@swift-ci create

@swift-ci
Copy link
Collaborator Author

swift-ci commented Mar 6, 2018

Comment by Igor Botov (JIRA)

Thanks Jordan! I'm apparently got confused with my own code - but agree that error message could be better)

@xedin
Copy link
Member

xedin commented Sep 10, 2021

Diagnostic has been improved in Xcode 13:

error: instance method 'doService(container:)' requires the types 'Bar' and 'Something<Bar>' be equivalent
        let container: Container<Something<Bar>> = FooService<Foo>().doService(container: Container<Something<Bar>>())
                                                   ^
note: where 'F.Bar' = 'Bar', 'C.Something' = 'Something<Bar>'
    func doService<C>(container: C) -> C where C: ContainerProtocol, C.Something == F.Bar {
         ^

Please use either Xcode 13 or main branch snapshot to verify and close.

@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 diagnostics QoI Bug: Diagnostics Quality of Implementation type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

3 participants