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-4908] Protocol default init implementation not working for generic type #47485

Open
ffried opened this issue May 16, 2017 · 1 comment
Open
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 regression swift 4.0 type checker Area → compiler: Semantic analysis

Comments

@ffried
Copy link
Contributor

ffried commented May 16, 2017

Previous ID SR-4908
Radar None
Original Reporter @ffried
Type Bug

Attachment: Download

Environment

$ swift --version:
Apple Swift version 4.0-dev (LLVM f175cad503, Clang 51f7aba0dc, Swift 79b6334)
Target: x86_64-apple-macosx10.9

Toolchain: 4.0-DEVELOPMENT-SNAPSHOT-2017-05-15-a

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, 4.0Regression, DiagnosticsQoI, TypeChecker
Assignee None
Priority Medium

md5: 9943bb86056cf89636b8a1dfd73dbcc1

relates to:

  • SR-4909 Closure with generic type (being void) requires explicitly ignoring

Issue Description:

In the following example, the default initializer implementation for init(block: @escaping Block) is not used and the call results in an error stating that an argument is missing:

protocol BlockHandlerProtocol {
    associatedtype Object
    typealias Block = (Object) -> ()

    init(str: String, block: @escaping Block)
    init(block: @escaping Block)
}

extension BlockHandlerProtocol {
    init(block: @escaping Block) {
        self.init(str: "", block: block)
    }
}

struct BlockHandler<T>: BlockHandlerProtocol {
    typealias Object = T

    init(str: String, block: @escaping Block) {}
}

let handler = BlockHandler {} // correctly inferred as BlockHandler<()>
let handler2 = BlockHandler<()> {}

let handler3 = BlockHandler(block: {}) // correctly inferred as BlockHandler<()>
let handler4 = BlockHandler<()>(block: {})

This is the output I get:

s4_protocolInit.swift:21:27: error: missing argument for parameter 'str' in call
let handler = BlockHandler {} // correctly inferred as BlockHandler<()>
                          ^
                          (str: <#String#>)
s4_protocolInit.swift:18:5: note: 'init(str:block:)' declared here
    init(str: String, block: @escaping Block) {}
    ^
s4_protocolInit.swift:22:32: error: missing argument for parameter 'str' in call
let handler2 = BlockHandler<()> {}
                               ^
                               (str: <#String#>)
s4_protocolInit.swift:18:5: note: 'init(str:block:)' declared here
    init(str: String, block: @escaping Block) {}
    ^
s4_protocolInit.swift:24:29: error: missing argument for parameter 'str' in call
let handler3 = BlockHandler(block: {}) // correctly inferred as BlockHandler<()>
                            ^
                            str: <#String#>, 
s4_protocolInit.swift:18:5: note: 'init(str:block:)' declared here
    init(str: String, block: @escaping Block) {}
    ^
s4_protocolInit.swift:25:33: error: missing argument for parameter 'str' in call
let handler4 = BlockHandler<()>(block: {})
                                ^
                                str: <#String#>, 
s4_protocolInit.swift:18:5: note: 'init(str:block:)' declared here
    init(str: String, block: @escaping Block) {}
    ^

I've also attached the file with the sample code.

Here are a few observations I made while trying to narrow this down:

  • It works fine when using two normal func's instead of an initializer.

  • As soon as I make the struct non-generic (also removing the associatedtype from the protocol), it seems to work.

  • The closure also seems to play its role in it. If I use the associated type directly (instead of the closure Block), it works fine. Together with the first point, this could hint at a problem with generics, but explicitly declaring the generic parameter (as with handler2) doesn't help.

@belkadan
Copy link
Contributor

I think the underlying problem here is just SR-4909—that is, these are not "correctly inferred"—but then the diagnostics are definitely wrong on top of that. You can see this by using "{ _ in }" instead of "{}" for your callback—only the errors for 'handler' and 'handler3' are produced (but are still wrong).

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

No branches or pull requests

3 participants