<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 18, 2017, at 3:16 PM, Haravikk &lt;<a href="mailto:swift-evolution@haravikk.me" class="">swift-evolution@haravikk.me</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 18 Feb 2017, at 16:28, Matthew Johnson &lt;<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class="Apple-interchange-newline">On Feb 18, 2017, at 4:54 AM, Brent Royal-Gordon via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""><blockquote type="cite" class="">On Feb 18, 2017, at 2:18 AM, Haravikk via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class="">This is an idea I had while working with collections, and is particularly inspired by those that use common index types.<br class=""><br class="">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.<br class=""><br class="">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.<br class=""></blockquote><br class="">I've encountered the same problem in essentially the same place, so I'd like to see a solution too.<br class=""><br class="">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) -&gt; Int`, you don't want `func + (lhs: Index, rhs: Index) -&gt; Index`; you want `func + (lhs: Index, rhs: Int) -&gt; Index`.)<br class=""><br class="">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:<br class=""><br class="">* The enum is conformed to `RawRepresentable` with a `RawValue` of the concrete type.<br class="">* Each case is associated with a raw value, specified by a literal attached to the case.<br class="">* `init?(rawValue:)` and `var rawValue { get }` are automatically generated.<br class=""><br class="">There is currently no equivalent for structs, but I suggest we add one.<br class=""><br class="">If you say:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>struct Index: Int {}<br class=""><br class="">This is automatically equivalent to saying:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>struct Index: RawRepresentable {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var rawValue: Int<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>init(rawValue: Int) { self.rawValue = rawValue }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><br class="">And a special rule is applied: You may not declare any other stored properties.<br class=""><br class="">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.)<br class=""><br class="">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.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">A lot of this is very similar to the protocol-based forwarding proposal I worked on last year. &nbsp;That proposal would avoid the problems you describe around not being able to properly encapsulate `RawRepresentable`. &nbsp;It was also able to handle many nuances around forwarding of self and associated type requirements. &nbsp;It even had an example of how something like `newtype` could be defined in terms of the mechanisms it provides.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I was mid-way through a second draft when it became clear it was not in scope for Swift 3. &nbsp;At that point I deferred further work until the time is right. &nbsp;I would like to revisit it eventually, but it is clearly out of scope for Swift 4 as well.</span></div></blockquote><br class=""></div><div class="">Did you get as far as putting up anywhere to look at?</div><div class=""><br class=""></div><div class="">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.</div></div></div></blockquote><div><br class=""></div>No, it’s in a kind of mid-draft state. &nbsp;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. &nbsp;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.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""></div></div></blockquote></div><br class=""></body></html>