Generic initializer's parameter type not being resolved


(Andrey Fidrya) #1

Hi All,

I've encountered a very strange problem where generic initializer's parameter type isn't resolved correctly unless explicitly casted.

Below is playground code for reproducing the problem and compiler error I'm getting.
After removing "as! Type.Parent" cast the code won't compile anymore...

It expects Type.Parent and I'm passing Monster, but Parent is typealiased to Monster.
Why can't it infer the type automatically?

public protocol PluginDataProtocol: class {
    associatedtype Parent
    init(parent: Parent)
}

public class Monster {
    public var pluginsData = [ObjectIdentifier: AnyObject]()
    
    public func pluginData<Type>(id: ObjectIdentifier = ObjectIdentifier(Type.self)) -> Type
                where Type: PluginDataProtocol {
        if let data = pluginsData[id] as? Type {
            return data
        } else {
            let data = Type(parent: self as! Type.Parent)
            pluginsData[id] = data
            return data
        }
    }
}

final class MyMonsterPluginData: PluginDataProtocol {
    typealias Parent = Monster
    
    weak var parent: Parent?
    
    init(parent: Parent) {
        self.parent = parent
    }
}

Compiler error:

Playground execution failed: error: Generics.playground:14:24: error: cannot invoke initializer for type 'Type' with an argument list of type '(parent: Monster)'
            let data = Type(parent: self /* as! Type.Parent */)
                       ^

Generics.playground:14:24: note: expected an argument list of type '(parent: Self.Parent)'
            let data = Type(parent: self /* as! Type.Parent */)

Regards,
Andrey


(Hooman Mehr) #2

Update your where clause to:

        where Type: PluginDataProtocol, Type.Parent == Monster {

···

On Jan 31, 2017, at 10:36 AM, Andrey Fidrya via swift-users <swift-users@swift.org> wrote:

Hi All,

I've encountered a very strange problem where generic initializer's parameter type isn't resolved correctly unless explicitly casted.

Below is playground code for reproducing the problem and compiler error I'm getting.
After removing "as! Type.Parent" cast the code won't compile anymore...

It expects Type.Parent and I'm passing Monster, but Parent is typealiased to Monster.
Why can't it infer the type automatically?

public protocol PluginDataProtocol: class {
    associatedtype Parent
    init(parent: Parent)
}

public class Monster {
    public var pluginsData = [ObjectIdentifier: AnyObject]()
    
    public func pluginData<Type>(id: ObjectIdentifier = ObjectIdentifier(Type.self)) -> Type
                where Type: PluginDataProtocol {
        if let data = pluginsData[id] as? Type {
            return data
        } else {
            let data = Type(parent: self as! Type.Parent)
            pluginsData[id] = data
            return data
        }
    }
}

final class MyMonsterPluginData: PluginDataProtocol {
    typealias Parent = Monster
    
    weak var parent: Parent?
    
    init(parent: Parent) {
        self.parent = parent
    }
}

Compiler error:

Playground execution failed: error: Generics.playground:14:24: error: cannot invoke initializer for type 'Type' with an argument list of type '(parent: Monster)'
            let data = Type(parent: self /* as! Type.Parent */)
                       ^

Generics.playground:14:24: note: expected an argument list of type '(parent: Self.Parent)'
            let data = Type(parent: self /* as! Type.Parent */)

Regards,
Andrey

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Andrey Fidrya) #3

Update your where clause to:
        where Type: PluginDataProtocol, Type.Parent == Monster {

Thank you, '==' works! I tried "Type.Parent: Monster" before which didn't compile.

Regards,
Andrey

···

On 1 Feb 2017, at 00:27, Hooman Mehr <hooman@mac.com> wrote:

Update your where clause to:

        where Type: PluginDataProtocol, Type.Parent == Monster {

On Jan 31, 2017, at 10:36 AM, Andrey Fidrya via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

Hi All,

I've encountered a very strange problem where generic initializer's parameter type isn't resolved correctly unless explicitly casted.

Below is playground code for reproducing the problem and compiler error I'm getting.
After removing "as! Type.Parent" cast the code won't compile anymore...

It expects Type.Parent and I'm passing Monster, but Parent is typealiased to Monster.
Why can't it infer the type automatically?

public protocol PluginDataProtocol: class {
    associatedtype Parent
    init(parent: Parent)
}

public class Monster {
    public var pluginsData = [ObjectIdentifier: AnyObject]()
    
    public func pluginData<Type>(id: ObjectIdentifier = ObjectIdentifier(Type.self)) -> Type
                where Type: PluginDataProtocol {
        if let data = pluginsData[id] as? Type {
            return data
        } else {
            let data = Type(parent: self as! Type.Parent)
            pluginsData[id] = data
            return data
        }
    }
}

final class MyMonsterPluginData: PluginDataProtocol {
    typealias Parent = Monster
    
    weak var parent: Parent?
    
    init(parent: Parent) {
        self.parent = parent
    }
}

Compiler error:

Playground execution failed: error: Generics.playground:14:24: error: cannot invoke initializer for type 'Type' with an argument list of type '(parent: Monster)'
            let data = Type(parent: self /* as! Type.Parent */)
                       ^

Generics.playground:14:24: note: expected an argument list of type '(parent: Self.Parent)'
            let data = Type(parent: self /* as! Type.Parent */)

Regards,
Andrey

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users