> On Feb 18, 2017, at 3:16 PM, Haravikk <[email protected]> wrote: > > >> On 18 Feb 2017, at 16:28, Matthew Johnson <[email protected] >> <mailto:[email protected]>> wrote: >> >>> >>> On Feb 18, 2017, at 4:54 AM, Brent Royal-Gordon via swift-evolution >>> <[email protected] <mailto:[email protected]>> wrote: >>> >>>> On Feb 18, 2017, at 2:18 AM, Haravikk via swift-evolution >>>> <[email protected] <mailto:[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. > > Did you get as far as putting up anywhere to look at? > > It may be relevant to Swift 4 stage 2, though I'll admit I'm confused as hell > what is and is not in scope; but I believe the ABI compatibility stuff has > been pushed back so it might be accepting more general proposals again, I was > going to re-submit some of mine that were out-of-scope before.
No, it’s in a kind of mid-draft state. I’ll try to get it into a reasonable place and post a link sometime soon, but I don’t plan to officially propose it unless there is a lot of support, especially from the core team. This feels like something that is probably out of scope so I don’t want to invest too much time into it right now unless that proves to be wrong. >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
