Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot explicitly specialize a generic function when using closures

Tags:

generics

swift

I have a function like this:

func register<T: Routable>(_ action: Action, withCallback callback: @escaping (T?) -> Void) {
    notificationCenter.addObserver(forName: actionMap[action], object: nil, queue: .main, using: { notification in
    let routable = T(userInfo: notification.userInfo)
        callback(routable)
    })
}

Where Routable is defined like:

protocol Routable {
    init?(userInfo: [AnyHashable: Any]?)
}

When I try to use it, I receive

Cannot explicitly specialize a generic function

This is the usage:

controller.register<Navigate>(Action.navigate) { [unowned self] navigate in
    // do something
}

Any idea to make the compiler happy?

like image 462
Lorenzo B Avatar asked Apr 11 '26 20:04

Lorenzo B


1 Answers

I believe this is purely a syntax issue. You can't pass the type parameter directly like this. You need to "fill in the type hole" instead. To do that, you need to add the type to navigate:

controller.register(Action.navigate) { [unowned self] (navigate: Navigate?) in ... }

Sometimes that syntax is annoying because it buries the type. You can improve it by rewriting the signature of register this way:

func register<T: Routable>(action: Action, returning: T.type,
                           withCallback callback: @escaping (T?) -> Void)

You'd then call it this way:

controller.register(action: .navigate, returning: Navigate.self) { 
    [unowned self] navigate in 
    // ...
}

The returning parameter isn't directly used in the function. It just provides a more explicit way to specialize the function.

like image 58
Rob Napier Avatar answered Apr 14 '26 12:04

Rob Napier