Protocol conformance not recognized in generic function

I would appreciate any insight on this issue I'm having. I'm trying to create a generic function in Swift that accepts any type that conforms to a specific protocol. However, when I pass a conforming type into this method, I get a compiler error saying the class doesn't conform.

Here's my protocol:

protocol SettableTitle {
    static func objectWithTitle(title: String)
}

And here's a class I've made that conforms to this protocol:

class Foo: SettableTitle {
    static func objectWithTitle(title: String) {
        // Method implementation
    }
}

Finally, here's my generic function that lives in a different class:

class SomeClass {
    static func dynamicMethod<T: SettableTitle>(type: T, title: String) {
        T.objectWithTitle(title: title)
    }
}


Now, when I invoke the method like this:

SomeClass.dynamicMethod(type: Foo.self, title: "Title string!")


I get the following compiler error:

error: argument type 'Foo.Type' does not conform to expected type 'SettableTitle' SomeClass.dynamicMethod(type: Foo.self, title: "Title string!")


I can't understand why this would happen when the class

Foo
declares and implements
SettableTitle
conformance.


All this is in a simple playground in Xcode 8.3 (latest non-beta). Can anyone see anything I'm doing wrong here?

Accepted Reply

When you want to pass a type itself (metatype, `T.self`) to a function, you do not declare the param type as `T`.


For example, if you want to pass `Int.self`, you do not declare the param type as `Int`:

func metaFunc(_ typeParam: Int) {
    print(typeParam)
}
metaFunc(Int.self) //->error: cannot convert value of type 'Int.Type' to expected argument type 'Int'


You need to use `Int.Type`:

func metaFunc(_ typeParam: Int.Type) {
    print(typeParam)
}
metaFunc(Int.self) //->Int


When you want to pass generic type `T.self` (specialized to `Foo.self` in your case), use `T.Type`:

class SomeClass {
    static func dynamicMethod<T: SettableTitle>(type: T.Type, title: String) {
        T.objectWithTitle(title: title)
    }
}
SomeClass.dynamicMethod(type: Foo.self, title: "Title string!")

Replies

When you want to pass a type itself (metatype, `T.self`) to a function, you do not declare the param type as `T`.


For example, if you want to pass `Int.self`, you do not declare the param type as `Int`:

func metaFunc(_ typeParam: Int) {
    print(typeParam)
}
metaFunc(Int.self) //->error: cannot convert value of type 'Int.Type' to expected argument type 'Int'


You need to use `Int.Type`:

func metaFunc(_ typeParam: Int.Type) {
    print(typeParam)
}
metaFunc(Int.self) //->Int


When you want to pass generic type `T.self` (specialized to `Foo.self` in your case), use `T.Type`:

class SomeClass {
    static func dynamicMethod<T: SettableTitle>(type: T.Type, title: String) {
        T.objectWithTitle(title: title)
    }
}
SomeClass.dynamicMethod(type: Foo.self, title: "Title string!")

You nailed it! Thanks a lot! I guess I need to go re-read that chapter on Generics now...