Swift generics: Non-nominal type does not support explicit initialization
Asked Answered
I

1

3

So I'm trying to understand generic protocols and classes:

protocol ListPresenterType where View.PDO.SW == Dispatcher.SW {
    associatedtype Dispatcher: ListDispatcherType
    associatedtype View: ListViewType

    init(dispatcher: Dispatcher, state: @escaping (_ state: AppState)->(ListState<Dispatcher.SW>))

    func attachView(_ view: View)
    ...
}

And I'm initiating it from another generic class:

class AbstractListViewController<Presenter: ListPresenterType, PDO: ListPDOCommonType, ...>: ListViewType, ... where PDO.SW == Presenter.Dispatcher.SW, ... {
    func configure(withBla: bla) {
        ...
        presenter = Presenter(dispatcher: dispatcher, state: state)
    }

    func someFunc() {
        presenter.attachView(self) // ERROR: Cannot invoke 'attachView' with an argument list of type ...
}

As I understand, I'm trying to initialize a type conforming to a generic protocol, which works just fine, but the type of View must be inconsistent with what I'm trying to feed it in attachView(:).

Then I try to initialize it with concrete view, changing init:

init(dispatcher: Dispatcher, view: View, state: @escaping (_ state: AppState)->(ListState<Dispatcher.SW>)) { 
    self.view = view 
    ... 
}

And in AbstractListViewController:

presenter = Presenter(dispatcher: dispatcher, view: self, state: state)

And getting this infamous error:

Non-nominal type 'Presenter' does not support explicit initialization

Here're gists with relevant playgrounds:

  1. Successful init (though cannot invoke attachView(:)) https://gist.github.com/nikans/0fde838846ffa9ff2da48c923f850625
  2. Init failing with aforementioned error: https://gist.github.com/nikans/53c3ea146ceb12dc8461f7ba8a81793d

Please notice that every empty protocol there is in fact a generic protocol, I've just removed the unnecessary details.


I'd like to understand:

  1. What makes a "nominal" type "non-nominal" all of a sudden (nothing to be surprised of, it's a generic parameter conforming to a generic protocol, but I don't understand the causation).
  2. I heard something about type erasure, but didn't quite get if it is applicable here.

Thanks.

Inconstant answered 7/9, 2017 at 1:3 Comment(7)
Instead of showing snippets of code with no context, could you show enough actual detail to allow someone else to reproduce?Parttime
Good idea, but because of all objects being generic and depending on types of every other it'd probably be either a lot of code or not enough details still. I'll try to create a playground.Inconstant
UPD: I've added the gists with minimal reproducible codeInconstant
Hmm. Does Swift version matter? In your "Init failing with aforementioned error", what I get is cannot invoke initializer for type 'Presenter' with an argument list of type ... expected an argument list of type '(dispatcher: Self.Dispatcher, view: Self.View)' and cannot invoke 'attachView' with an argument list of type ... expected an argument list of type '(Presenter.View)'Parttime
I use swift 3 but compile with xcode 9 beta 6. This whole thing just doesn't work in xcode 8, dunno about the playgrounds. I'll check.Inconstant
True, xcode8 returns Cannot invoke initializer for type 'Presenter' with an argument list of type '(dispatcher: Presenter.Dispatcher!, view: AbstractListViewController<Presenter, Presenter.View.PDO>)', so basically some types are not resolved correctly for some reason. Maybe some constraints are not there.Inconstant
The only constraint I can think of is something like Presenter.View == Self, but that does not compile (obviously?). It says, Expected an argument list of type '(dispatcher: Self.Dispatcher, view: Self.View)'Inconstant
I
3

So it appears that in Xcode9 (beta 6) errors like Non-nominal type '%type' does not support explicit initialization simply equals the mismatching types error in less buggy Xcode (if that's a thing): cannot invoke initializer for type '%type' with an argument list of type '...' expected an argument list of type '...'

Inconstant answered 8/9, 2017 at 10:54 Comment(1)
Thank you this just wasted an hour of my dayEuchology

© 2022 - 2024 — McMap. All rights reserved.