<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><br><br>Sent from my iPad</div><div><br>On Jun 3, 2016, at 6:20 PM, Greg Parker &lt;<a href="mailto:gparker@apple.com">gparker@apple.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><br class=""><div><blockquote type="cite" class=""><div class="">On Jun 1, 2016, at 5:42 PM, Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><div class=""><div class=""><br class=""><blockquote type="cite" class="">On Jun 1, 2016, at 5:02 PM, Vladimir.S 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="">in other words, we could consider allowing this:<br class=""> &nbsp;&nbsp;func foo(bar: (.fit | .fill)) {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;baz(bar: bar)<br class=""> &nbsp;&nbsp;}<br class=""> &nbsp;&nbsp;func baz(bar: (.fit | .fill | .florp) { ... }<br class=""><br class="">In other words, an ad hoc enum T can be used wherever an ad hoc enum U is<br class="">expected if T ⊆ U.<br class=""></blockquote><br class="">Can't agree with this. Just because the same analogue with tuples : differently defined tuples are different types. Tuples with different order of types in declaration - are different types. So I expect here instance of (.fit | .fill) `bar` is not of the same type as (.fit | .fill | .florp)<br class=""></blockquote><br class="">They are not the same type but there is a structural subtype relationship between them. &nbsp;All values of type (.fit | .fill) are also values of type (.fit | .fill | .florp).</div></div></blockquote><br class=""></div><div>What about disjoint types? Some values of type (.fit | .fill) are values of type (.fit | .florp) and some are not. I'm not a type system expert but my understanding is that this capability gets very complicated very fast.</div></div></blockquote><div><br></div><div><span style="background-color: rgba(255, 255, 255, 0);">It feels like the only sane way to model these is as union types where each member of the union has a single literal value like '.fit'. &nbsp;This is where structural subtyping would come from.</span></div><div><br></div><div>In your example I would say there is no subtype relationship there, just as a union of 'Fit | Fill' would not have any subtype / supertype relationship with 'Fit | Florp' in a language like Ceylon that has union types. &nbsp;</div><div><div><br></div><div>Without the structural subtyping these types would be way too fragile to be considered IMO.</div><div><br><div><blockquote type="cite"><div><div><br class=""></div><div><br class=""></div><div>What about the ABI? This sounds expensive to implement.</div><div><br class=""></div><div>Consider this set of ad-hoc enum types:</div><div><br class=""></div><div>&nbsp; (.a | .b)</div><div>&nbsp; (.c | .d)</div><div><br class=""></div><div>Naive implementation: we'll represent these things as ints, with .a=1, .b=2, .c=1, .d=2.</div><div><br class=""></div><div>The naive implementation breaks when a newly-loaded shared library or some library evolution adds this type:</div><div><br class=""></div><div>&nbsp; (.a | .b | .c | .d)</div><div><br class=""></div><div>In order to provide ABI stability in the face of arbitrary ad-hoc enum types we must ensure that every ad-hoc enum value has a globally unique ABI representation.&nbsp;</div><div><br class=""></div><div>You could constrain ad-hoc enum values to module or class boundaries and prevent creation of types that use values from different places. For example, if Foundation defines (.a | .b) then you can't define your own ad-hoc enum (.a | .b | .c) that is compatible with Foundation's value for .a. Then the implementation could use ordinary symbols. If usage of ad-hoc enums is not constrained then ordinary symbols don't work because there is no universally agreed-upon place where .a is defined.</div><div><br class=""></div><div>An implementation like ObjC's @selector or C/C++ weak definition would work, but those are expensive in memory overhead and launch time.&nbsp;</div><div><br class=""></div><div>You could give each linkage unit its own copy of the value that includes a string of the value's name plus an == operator that compares the name strings; that would avoid uniquing but would make some operations slow.&nbsp;</div><div><br class=""></div><div>In any case the performance of these things will not be comparable to ints nor to typical Swift enums that are encoded as ints.</div></div></blockquote><div><br></div><div>You bring up very good points. &nbsp;I'm not saying we *should* do this. &nbsp;Only that if we do introduce ad-hoc enums this seems like the only sane way to do it. &nbsp;I would want to be able to declare declare variables, etc that use the type without having every mention of the type break when the author of the function adds a new option.</div><div><br></div><div>My opinion is that everything you bring up is a pretty solid argument against ad-hoc enums. &nbsp;Maybe is Swift ever gets union types we could revisit the idea under that umbrella (but that is sounding unlikely, and is definitely not something that will happen soon).</div><br><blockquote type="cite"><div><div><br class=""></div><div><br class=""></div><div>--&nbsp;</div><div>Greg Parker &nbsp; &nbsp; <a href="mailto:gparker@apple.com" class="">gparker@apple.com</a>&nbsp; &nbsp; &nbsp;Runtime Wrangler</div><div><br class=""></div><div><br class=""></div></div></blockquote></div></div></div></body></html>