> On Feb 18, 2017, at 4:54 AM, Brent Royal-Gordon via swift-evolution > <[email protected]> wrote: > >> On Feb 18, 2017, at 2:18 AM, Haravikk via swift-evolution >> <[email protected]> wrote: >> >> This is an idea I had while working with collections, and is particularly >> inspired by those that use common index types. >> >> Consider for example an array; for indices it simply uses an integer, >> however, while this is a perfectly valid type to use it opens up the >> possibility of integers from any number of different sources being passed in >> by mistake and causing run-time errors. The same is true for wrapping types >> that use AnyIndex, or really any type that uses Any* to hide underlying >> types, as on the surface all AnyIndex instances give the illusion of being >> compatible when they're not, and will only produce errors at run-time when a >> conflict arises. >> >> The idea to combat this is simple; a new attribute that can be applied to a >> typealias, my working name is @unique, but there's probably a much better >> name for it. When applied to a type-alias it indicates to the type-checker >> that the type being aliased should be treated as a unique type outside of >> the scope in which it is declared. > > I've encountered the same problem in essentially the same place, so I'd like > to see a solution too. > > This sounds like a slight variation on what, in previous discussions, has > been called `newtype`. IIRC, one of the reasons we've never done `newtype` is > that it's not clear which features you want to bring over from the base type, > or which types should be used for things like operators. (If you have `func + > (lhs: Int, rhs: Int) -> Int`, you don't want `func + (lhs: Index, rhs: Index) > -> Index`; you want `func + (lhs: Index, rhs: Int) -> Index`.) > > I'd like to suggest a design that I don't think has been considered before. > Currently, if the first type in an enum's inheritance clause is a concrete > type, a set of magical behaviors occur: > > * The enum is conformed to `RawRepresentable` with a `RawValue` of the > concrete type. > * Each case is associated with a raw value, specified by a literal attached > to the case. > * `init?(rawValue:)` and `var rawValue { get }` are automatically generated. > > There is currently no equivalent for structs, but I suggest we add one. > > If you say: > > struct Index: Int {} > > This is automatically equivalent to saying: > > struct Index: RawRepresentable { > var rawValue: Int > init(rawValue: Int) { self.rawValue = rawValue } > } > > And a special rule is applied: You may not declare any other stored > properties. > > Additionally, for both `enum`s and `struct`s with raw types, I would suggest > that, if you conform to a protocol which the raw type conforms to and then > fail to fulfill its (non-defaulted) requirements, Swift should generate a > member which forwards to the raw value's implementation. It might even be > nice to do the same when an initializer, method, property, or subscript is > declared without providing a body. This would make it easy to decide which > functionality should be exposed and how it should be provided--and it would > provide a partial way to fulfill the frequent request for syntactic sugar for > `Equatable`, `Hashable`, and `Comparable` conformances. (I could imagine this > being generalized later on.) > > The main drawback I can see is that the `rawValue` could not be encapsulated, > since the conformance to the public `RawRepresentable` protocol could not be > made private. That might be acceptable in a convenience feature, or we might > decide (perhaps for both `struct`s and `enum`s) that Swift should generate > the members without actually conforming the type unless explicitly asked to.
A lot of this is very similar to the protocol-based forwarding proposal I worked on last year. That proposal would avoid the problems you describe around not being able to properly encapsulate `RawRepresentable`. It was also able to handle many nuances around forwarding of self and associated type requirements. It even had an example of how something like `newtype` could be defined in terms of the mechanisms it provides. I was mid-way through a second draft when it became clear it was not in scope for Swift 3. At that point I deferred further work until the time is right. I would like to revisit it eventually, but it is clearly out of scope for Swift 4 as well. > > -- > Brent Royal-Gordon > Architechies > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
