Bad diagnostics and code completion, caused by Swift bug?


(Jens Persson) #1

In the screenshot example, I'd expect only methodOnAllThings() and methodOnThingsWhereFooIsInt() to show up in the list of code completions, but Xcode will list all methods in all extensions, including methodOnThingsWhereFooIsBool() even though thing is clearly an instance of a type where Foo is Int, not Bool.
I know this might be something Xcode specific and thus OT here, but the error message in the code example below the screenshot makes me wonder if it's caused by something in the Swift implementation?


struct Thing<Foo, Bar> {
    func methodOnAllThings() {}
}

extension Thing where Foo == Int {
    func methodOnThingsWhereFooIsInt() {}
}

extension Thing where Foo == Bool {
    func methodOnThingsWhereFooIsBool() {}
}

func test() {
    
    let thing = Thing<Int, Double>()
    
    thing.methodOnThingsWhereFooIsBool() // ERROR: Generic parameter 'Bar'
                                         //        could not be inferred
    
}
test()

(Anthony Latsis) #2

Hi Jens! This is a code completion bug, meaning it is a Swift bug. I filed the same issue almost a year ago, and probably there are some dupes roaming on JIRA as well. The senseless error message is a separate issue that also deserves a SR number.


(Jens Persson) #3

Thank's! I noticed that you're the assignee (as well as reporter) of that issue, does that mean you are working on fixing it?

I've filed SR-9396 for the nonsensical error message and linked it to yours even though I'm not sure if they might be related.


(Anthony Latsis) #4

I assigned myself just now because I figured I'd give it a go in the nearish future.


(Jens Persson) #5

I tried the protocol-workaround mentioned in this comment to SR-7046. But (disappointingly) this only works as long as all code is in the same file.

An example:

Start a new command line app project (in Xcode 10.1).

Create these files:

Library.swift:

protocol LibraryProtocol {
    associatedtype Kind
}

struct Library<Kind> : LibraryProtocol {}

Foo.swift:

enum Foo {}

extension LibraryProtocol where Kind == Foo {
    func onlyIfKindIsFoo() {}
}

Bar.swift

enum Bar {}

extension LibraryProtocol where Kind == Bar {
    func onlyIfKindIsBar() {}
}

main.swift:

func test() {
    let barLib = Library<Bar>()
    barLib.
}

Here's what the list of code completions looks for after barLib.:


: (
As can be seen, onlyIfKindIsFoo() is there even though it shouldn't. But cutting and pasting all the code into main.swift will result in the expected single entry list of completions:


The project we're currently working on relies heavily on a code construct like this but this issue takes away much of the joy of using it (veeery long lists of code completions where 90% of the entries are useless/irrelevant). So a fix for this would be greatly appreciated!