<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="">If there's any interest in going down that road, it seems to me that the only viable option is to allow subsets to be convertible to their superset. Items of (.foo | .bar) would be convertible to (.foo | .bar | .baz), but not the opposite (and not necessarily, although preferably, through a simple bitcast).<div class=""><div class=""><div class="">
<br class="Apple-interchange-newline"><span style="color: rgb(0, 0, 0); font-family: 'Lucida Grande'; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; display: inline !important; float: none;" class="">Félix</span>
</div>
<br class=""><div><blockquote type="cite" class=""><div class="">Le 3 juin 2016 à 16:20:18, Greg Parker via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> a écrit :</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" 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 Jun 1, 2016, at 5:42 PM, Matthew Johnson via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> 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 <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class=""><blockquote type="cite" class="">in other words, we could consider allowing this:<br class=""> func foo(bar: (.fit | .fill)) {<br class=""> baz(bar: bar)<br class=""> }<br class=""> 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. All values of type (.fit | .fill) are also values of type (.fit | .fill | .florp).</div></div></blockquote><br class=""></div><div class="">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 class=""><br class=""></div><div class=""><br class=""></div><div class="">What about the ABI? This sounds expensive to implement.</div><div class=""><br class=""></div><div class="">Consider this set of ad-hoc enum types:</div><div class=""><br class=""></div><div class=""> (.a | .b)</div><div class=""> (.c | .d)</div><div class=""><br class=""></div><div class="">Naive implementation: we'll represent these things as ints, with .a=1, .b=2, .c=1, .d=2.</div><div class=""><br class=""></div><div class="">The naive implementation breaks when a newly-loaded shared library or some library evolution adds this type:</div><div class=""><br class=""></div><div class=""> (.a | .b | .c | .d)</div><div class=""><br class=""></div><div class="">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. </div><div class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">An implementation like ObjC's @selector or C/C++ weak definition would work, but those are expensive in memory overhead and launch time. </div><div class=""><br class=""></div><div class="">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. </div><div class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class=""><br class=""></div><div class="">-- </div><div class="">Greg Parker <a href="mailto:gparker@apple.com" class="">gparker@apple.com</a> Runtime Wrangler</div><div class=""><br class=""></div><div class=""><br class=""></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></div></body></html>