Swift 1.1 and 1.2: accessing members of protocol type value XXX.Type' is unimplemented

Originator:gwendal.roue
Number:rdar://20119848 Date Originated:
Status: Resolved:
Product:Developer Tools Product Version:Xcode 6.3b2
Classification: Reproducible:
 
Hi,

Swift 1.1 and 1.2 won't let the programmer call a class method defined in a protocol.

The use case is the following:

I'm developping a Swift implementation (https://github.com/groue/GRMustache.swift) of the Mustache template engine (https://mustache.github.io).

Mustache is a template engine which turns "Hello {{name}}!" into "Hello Tom Selleck!" when given ["name": "Tom Selleck"]. It replaces Mustache tags with the values it extracts from its input.

GRMustache.swift performs key extraction from NSObject values with the valueForKey: method. The "problem" with valueForKey: is that it can execute any method that does not take any argument, including methods that have side effects. When one renders an untrusted template, this is a security issue. To alleviate this problem, GRMustache.swift will only execute valueForKey: for "safe" keys. Those safe keys are, by default, the names of properties. However, there is a protocol, named "SafeKeyAccess", which lets a developper expose its own custom list of safe keys:

@objc protocol SafeKeyAccess {
    static func safeKeys() -> Set<String>
}

The problem is that it is impossible, in Swift, to call this method, given an input of type AnyObject:

func safeValueForKey(key: String, inObject object: AnyObject) -> AnyObject? {
    if let safe = object as? SafeKeyAccess {
        // error: accessing members of protocol type value 'SafeKeyAccess.Type' is unimplemented
        let safeKeys = safe.dynamicType.safeKeys()
        if find(safeKeys, key) != nil {
            return object.valueForKey?(key)
        }
    }
    return nil
}

Since Swift won't help, the GRMustache library has to escape to Objective-C in order to implement this "safe key-value coding".

In the following lines of code, the GRMustacheKeyAccess.isSafeMustacheKey  method is written in Objective-C: https://github.com/groue/GRMustache.swift/blob/ddabbcd9f0cf9e49d685141133753cdb6241e57e/Mustache/Rendering/MustacheBox.swift#L1447-L1462

Since there is an Objective-C workaround, the problem is not so big. But you know how things go: now that the library contains a mix of Swift and Objective-C, it can not be shipped as a CocoaPod (the dependency manager), because CocoaPod does not support this kind of project yet, etc. etc. So this limitation is not so nice in the end.

Thanks for reading!

Steps to Reproduce:
Compile this Swift code:

@objc protocol SafeKeyAccess {
    static func safeKeys() -> Set<String>
}

func safeValueForKey(key: String, inObject object: AnyObject) -> AnyObject? {
    if let safe = object as? SafeKeyAccess {
        // error: accessing members of protocol type value 'SafeKeyAccess.Type' is unimplemented
        let safeKeys = safe.dynamicType.safeKeys()
        if find(safeKeys, key) != nil {
            return object.valueForKey?(key)
        }
    }
    return nil
}


Expected Results:
The above code compiles.

Actual Results:
The compiler fails with error "accessing members of protocol type value 'SafeKeyAccess.Type' is unimplemented".

Version:
Xcode Version 6.3 (6D532l)

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!