Can @dynamicMemberLookup be applied to protocols?

The Swift language reference says this about @dynamicMemberLookup (emphasis mine):

dynamicMemberLookup
Apply this attribute to a class, structure, enumeration, or protocol to enable members to be looked up by name at runtime.

When I try this with a protocol, I get an error:

// error: @dynamicMemberLookup attribute requires 'P'
// to have a 'subscript(dynamicMember:)' member with
// a string index
@dynamicMemberLookup
protocol P {
    subscript(dynamicMember member: String) -> String { get }
}

(Tested in Xcode 10b2 and with the Swift-Development-Snapshot-2018-06-20-a toolchain.)

Is this a missing implementation in the compiler or a bug in the documentation? Should @dynamicMemberLookup be supported on protocol declarations?

SE-0195 doesn't say so explicitly (nor does it explicitly reject it), and I don't remember if this came up in the discussion.

2 Likes

Looks like a bug.

This test is passing, however.

1 Like

Thanks. Ah yes, providing a default implementation does indeed fix the error. You can even keep the subscript as a protocol requirement (as long as you keep the default implementation), so this compiles:

@dynamicMemberLookup
protocol P {
    subscript(dynamicMember member: String) -> String { get }
}

extension P {
    subscript(dynamicMember member: String) -> String {
        return ""
    }
}

This behavior is not clearly specified though. @Chris_Lattner3, should it require a default implementation?

Someone mentioned this behavior in the SE-0216 User-defined dynamically callable types thread as well.

Currently, the implementation of @dynamicMemberLookup only looks for concrete subscript(dynamicMember:) methods; subscript(dynamicMember:) as a protocol requirement isn't handled.
I believe it should be handled, however, for expected behavior. The necessary changes shouldn't be too drastic.

Agreed, this looks like a bug to me.

Thanks! I filed SR-8077.

1 Like

The fix worked however on Xcode 11 beta 5, with SE-0252, the autocompletion for properties is broken when conforming a protocol that has @dynamicMemberLookup with default implementation.