SE-0261: Identifiable Protocol

I'm coming a bit late to the heavy discussion above about naming conflicts with the id property, but I had some related thoughts that might make the idea more palatable, with a little bit more help from the language.

I agree with the folks who think that it's a non-goal to try to come up with a name for this property that isn't going to collide with someone's existing code. While it's nice if that can be done, the overall design and readability of the protocol shouldn't have to suffer by being made more obfuscated.

The Swift language has an internal attribute that almost lets us have the best of both worlds: @_implements lets you declare that a property, method, or associated type implements a particular requirement of a protocol even if it has a different name (this is similar to C#'s explicit interface implementation concept).

Right now, there's just one problem: if that other name still happens to be an existing declaration on the conforming type, you end up with an ambiguity:

protocol Identifiable {
  var id: String { get }
}

struct Record {
  var id: String { return "Record.id" }
}

extension Record: Identifiable {
  @_implements(Identifiable, id)
  var idForIdentifiable: String { return "Record(Identifiable).id" }
}

let r = Record()
print(r.id)  // Desired: "Record.id", but error below 🙁 

let i: Identifiable = r
print(i.id)  // Desired: "Record(Identifiable).id"
main.swift:15:7: error: ambiguous use of 'id'
print(r.id)
      ^
main.swift:6:7: note: found this candidate
  var id: String { return "Record.id" }
      ^
main.swift:11:7: note: found this candidate
  var idForIdentifiable: String { return "Record(Identifiable).id" }

I would propose two things (which certainly shouldn't be combined with this proposal, but which offer a path that may ease the concerns in the discussion above):

  1. @_implements should be made public.
  2. Modify the behavior of @_implements to remove the ambiguity; in the example above if you refer to id on an instance of the concrete type Record, then it would only refer to the concrete type's property and not the renamed protocol requirement.
8 Likes