<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 Jul 31, 2017, at 11:52 PM, John McCall &lt;<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</a>&gt; wrote:</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=""><div class=""><blockquote type="cite" class=""><div class="">On Jul 31, 2017, at 4:37 PM, Gor Gyolchanyan &lt;<a href="mailto:gor.f.gyolchanyan@icloud.com" class="">gor.f.gyolchanyan@icloud.com</a>&gt; wrote:</div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class="">On Jul 31, 2017, at 11:23 PM, John McCall &lt;<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On Jul 31, 2017, at 4:00 PM, Gor Gyolchanyan &lt;<a href="mailto:gor.f.gyolchanyan@icloud.com" class="">gor.f.gyolchanyan@icloud.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jul 31, 2017, at 10:09 PM, John McCall &lt;<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><blockquote type="cite" class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">On Jul 31, 2017, at 3:15 AM, Gor Gyolchanyan &lt;<a href="mailto:gor.f.gyolchanyan@icloud.com" class="">gor.f.gyolchanyan@icloud.com</a>&gt; wrote:<br class=""><blockquote type="cite" class="">On Jul 31, 2017, at 7:10 AM, John McCall 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 Jul 30, 2017, at 11:43 PM, Daryle Walker &lt;<a href="mailto:darylew@mac.com" class="">darylew@mac.com</a>&gt; wrote:<br class="">The parameters for a fixed-size array type determine the type's size/stride, so how could the bounds not be needed during compile-time? The compiler can't layout objects otherwise.<span class="Apple-converted-space">&nbsp;</span><br class=""></blockquote><br class="">Swift is not C; it is perfectly capable of laying out objects at run time. &nbsp;It already has to do that for generic types and types with resilient members. &nbsp;That does, of course, have performance consequences, and those performance consequences might be unacceptable to you; but the fact that we can handle it means that we don't ultimately require a semantic concept of a constant expression, except inasmuch as we want to allow users to explicitly request guarantees about static layout.<br class=""></blockquote><br class="">Doesn't this defeat the purpose of generic value parameters? We might as well use a regular parameter if there's no compile-time evaluation involved. In that case, fixed-sized arrays will be useless, because they'll be normal arrays with resizing disabled.<br class=""></blockquote><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">You're making huge leaps here. &nbsp;The primary purpose of a fixed-size array feature is to allow the array to be allocated "inline" in its context instead of "out-of-line" using heap-allocated copy-on-write buffers. &nbsp;There is no reason that that representation would not be supportable just because the array's bound is not statically known; the only thing that matters is whether the bound is consistent for all instances of the container.</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">That is, it would not be okay to have a type like:</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">&nbsp;struct Widget {</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">&nbsp;&nbsp;&nbsp;let length: Int</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">&nbsp;&nbsp;&nbsp;var array: [length x Int]</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">&nbsp;}</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">because the value of the bound cannot be computed independently of a specific value.</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">But it is absolutely okay to have a type like:</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">&nbsp;struct Widget {</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">&nbsp;&nbsp;&nbsp;var array: [(isRunningOnIOS15() ? 20 : 10) x Int]</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">&nbsp;}</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">It just means that the bound would get computed at runtime and, presumably, cached. &nbsp;The fact that this type's size isn't known statically does mean that the compiler has to be more pessimistic, but its values would still get allocated inline into their containers and even on the stack, using pretty much the same techniques as C99 VLAs.</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"></div></div></blockquote><div class=""><br class=""></div><div class="">I see your point. Dynamically-sized in-place allocation is something that completely escaped me when I was thinking of fixed-size arrays. I can say with confidence that a large portion of private-class-copy-on-write value types would greatly benefit from this and would finally be able to become true value types.</div></div></div></div></blockquote><div class=""><br class=""></div>To be clear, it's not obvious that using an inline array is always a good move for performance! &nbsp;But it would be a tool available for use when people felt it was important.</div></div></blockquote><div class=""><br class=""></div><div class="">That's why I'm trying to push for compile-time execution system. All these problems (among many others) could be designed out of existence and the compiler would be incredibly simple in the light of all the different specific features that the community is asking for. But I do feel your urge to avoid inventing a bulldozer factory just for digging a hole in a sandbox. It doesn't have to be relied upon by the type checker or generic resolution mechanism. It would be purely auxiliary. But that would single-handedly move a large chunk of the compiler into stdlib and a huge portion of various little incidental proposals would fade away because they can now easily be implemented in Swift for specific purposes.</div></div></div></div></blockquote><div class=""><br class=""></div>My point here had nothing to do with compile-time vs. dynamic-time evaluation of array bounds. &nbsp;Inline array storage is not a performance panacea even if everything about them is static. &nbsp;The exact balance point will vary by element type, machine, and the overall load on the memory system in your program, but even for an array of bytes, as the size of the array grows it will eventually become the case that retaining a buffer pointer will be cheaper than copying the buffer contents.</div></div></div></blockquote><div><br class=""></div>Yeah, the compile-time stuff is completely off-topic at this point. I'll make a new thread with a more elaborate explanation of details some time in the near future. For now, considering the above conversation, I think implementing fixed-size arrays as a magical (and the only) way of in-place dynamic allocation is a great idea that would require very (relatively) little prerequisite work.<br class=""><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=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">As far as I know, the pinnacle of uses for fixed-size arrays is having a compile-time pre-allocated space of the necessary size (either literally at compile-time if that's a static variable, or added to the pre-computed offset of the stack pointer in case of a local variable).<br class=""></blockquote><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">The difference between having to use dynamic offsets + alloca() and static offsets + a normal stack slot is noticeable but not nearly as extreme as you're imagining. &nbsp;And again, in most common cases we would absolutely be able to fold a bound statically and fall into the optimal path you're talking about. &nbsp;The critical guarantee, that the array does not get heap-allocated, is still absolutely intact.</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"></div></div></blockquote><div class=""><br class=""></div><div class="">Yet again, Swift (specifically - you in this case) is teaching me to trust the compiler to optimize, which is still an alien feeling to me even after all these years of heavy Swift usage. Damn you, C++ for corrupting my brain 😀.</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Well. &nbsp;Trust but verify. 🙂</div></div></div></blockquote><div class=""><br class=""></div><div class="">The only good way I can think of doing that is hand-crafting a lightning-fast implementation LLVM IR, then doing the same in Swift, decompiling the bitcode and then doing a diff. It's going to be super tedious and painful, but it seems to be the only way to prove that Swift can (hopefully, some day...) replace C++ in sheer performance potential.</div></div></div></div></blockquote><div class=""><br class=""></div>Or just run a benchmark and complain if the performance isn't as good as you expect?</div></div></div></blockquote><div><br class=""></div><div>That will work too, but field testing is dependent on the hardware and code equivalence can prove performance superiority on a theoretical level. But that's probably overkill if the goal is to convert Crusty's cousin Bernie the pre-standard C++ guy to start using Swift. 🙂</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=""><div class=""><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=""><div class=""><blockquote type="cite" class=""><div class=""><div style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class="">In the specific case of having dynamic-sized in-place-allocated value types this will absolutely work. But this raises a chicken-and-the-egg problem: which is built in what: in-place allocated dynamic-sized value types, or specifically fixed-size arrays? On one hand I'm tempted to think that value types should be able to dynamically decide (inside the initializer) the exact size of the allocated memory (no less than the static size) that they occupy (no matter if on the heap, on the stack or anywhere else), after which they'd be able to access the "leftover" memory by a pointer and do whatever they want with it. This approach seems more logical, since this is essentially how fixed-size arrays would be implemented under the hood. But on the other hand, this does make use of unsafe pointers (and no part of Swift currently relies on unsafe pointers to function), so abstracting it away behind a magical fixed-size array seems safer (with a hope that a fixed-size array of UInt8 would be optimized down to exactly the first case).</div></div></div></div></blockquote><div class=""><br class=""></div>Representationally, I think we would have a builtin fixed-sized array type that. &nbsp;But "fixed-size" means "the size is an inherent part of the type", not "we actually know that size statically". &nbsp;Swift would just be able to use more optimal code-generation patterns for types whose bounds it was actually able to compute statically.</div></div></blockquote><div class=""><br class=""></div><div class="">Well, yeah, knowing its size statically is not a requirement, but having a guarantee of in-place allocation is. As long as non-escaped local fixed-size arrays live on the stack, I'm happy. 🙂</div></div></div></div></blockquote><div class=""><br class=""></div>I figured.</div><div class=""><br class=""></div><div class="">John.</div><div class=""><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=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">John.</div><div style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class="">Value equality would still affect the type-checker, but I think we could pretty easily just say that all bound expressions are assumed to potentially resolve unequally unless they are literals or references to the same 'let' constant.<br class=""></blockquote><br class="">Shouldn't the type-checker use the Equatable protocol conformance to test for equality?<br class=""></blockquote><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">The Equatable protocol does guarantee reflexivity.</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Moreover, as far as I know, Equatable is not recognized by the compiler in any way, so it's just a regular protocol.<br class=""></blockquote><div class=""><br class=""></div><span class="" style="font-family: AvenirNext-Regular;">That's not quite true: we synthesize Equatable instances in several places.</span></div></div></blockquote><blockquote type="cite" class=""><div class=""><br class=""></div></blockquote><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">What would make it special? Some types would implement operator == to compare themselves to other types, that's beyond the scope of Equatable. What about those? And how are custom operator implementations going to serve this purpose at compile-time? Or will it just ignore the semantics of the type and reduce it to a sequence of bits? Or maybe only a few hand-picked types will be supported?<br class=""></blockquote><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="">The seemingly simple generic value parameter concept gets vastly complicated and/or poorly designed without an elaborate compile-time execution system... Unless I'm missing an obvious way out.<br class=""></blockquote><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">The only thing the compiler really *needs* to know is whether two types are known to be the same, i.e. whether two values are known to be the same.<span class="Apple-converted-space">&nbsp;</span></span></div></div></blockquote><div class=""><br class=""></div><div class="">I think having arbitrary value-type literals would be a great place to start. Currently there are only these types of literals:</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>* nil</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>* boolean</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>* integer</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>* floating-point</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>* string, extended grapheme cluster, unicode scalar</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>* array</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>* dictionary</div><div class=""><br class=""></div><div class="">The last three of which are kinda weird because they're not really literals, because they can contains dynamically generated values.</div><div class="">If value types were permitted to have a special kind of initializer (I'll call it literal initializer for now), which only allows directly assigning to its stored properties or self form parameters with no operations, then that initializer could be used to produce a compile-time literal of that value type. A similar special equality operator would only allow directly comparing stored properties between two literal-capable value types.</div><div class=""><br class=""></div><div class="">struct Foo {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>literal init(one: Int, two: Float) {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>self.one = one</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>self.two = two<span class="Apple-tab-span" style="white-space: pre;">        </span></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let one: Int</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let two: Float</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">literal static func == &nbsp;(_ some: Foo, _ other: Foo) -&gt; Bool {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>return&nbsp;some.one == other.one &amp;&amp; some.two == other.two</div><div class="">}</div><div class=""><br class=""></div><div class="">only assignment would be allowed in the initializer and only equality check and boolean operations would be allowed inside the equality operator. These limitations would guarantee completely deterministic literal creation and equality conformance at compile-time.</div><div class="">Types that conform to _BuiltinExpressibleBy*Literal would be magically equipped with both of these.</div><div class="">String, array and dictionary literals would be unavailable.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class=""><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">An elaborate compile-time execution system would not be sufficient here, because again, Swift is not C or C++: we need to be able to answer that question even in generic code rather than relying on the ability to fold all computations statically. &nbsp;We do not want to add an algebraic solver to the type-checker. &nbsp;The obvious alternative is to simply be conservatively correct by treating independent complex expressions as always yielding different values.</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"></div></div></blockquote><div class=""><br class=""></div><div class="">How exactly does generic type resolution happen? Obviously, it's not all compile-time, since it has to deal with existential containers. Without customizable generic resolution, I don't see a way to implement satisfactory generic value parameters. But if we settle on magical fixed-size arrays, we wouldn't need generic value parameters, we would only need to support constraining the size of the array with Comparable operators:</div><div class=""><br class=""></div><div class="">func &nbsp;foo&lt;T&gt;(_ array: T) where T: [Int], T.count == 5 {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// ...</div><div class="">}&nbsp;</div><div class=""><br class=""></div><div class="">let array: [5 of Int] = [1, 2, 3, 4, 5]</div><div class="">foo(array)</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class="">The only hard constraint is that types need to be consistent, but that just means that we need to have a model in which bound expressions are evaluated exactly once at runtime (and of course typically folded at compile time).<br class=""></blockquote><br class="">What exactly would it take to be able to execute select piece of code at compile-time? Taking the AST, converting it to LLVM IR and feeding it to the MCJIT engine seems to be easy enough. But I'm pretty sure it's more tricky than that. Is there a special assumption or two made about the code that prevents this from happening?<br class=""></blockquote><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">We already have the ability to fold simple expressions in SIL; we would just make sure that could handle anything that we considered really important and allow everything else to be handled dynamically.</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"></div></div></blockquote><div class=""><br class=""></div><div class="">So, with some minor adjustments, we could get a well-defined subset of Swift that can be executed at compile-time to yield values that would pass as literals in any context?</div><div class="">This would some day allow relaxing the limitations on literal initializers and literal equality operators by pre-computing and caching values at compile-time outside the scope of the type checker, allowing the type checker to stay simple, while essentially allowing generics with complex resolution logic.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><span class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">John.</span><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class="" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""><blockquote type="cite" class="">John.<br class=""><br class=""><blockquote type="cite" class="">Or do you mean that the bounds are integer literals? (That's what I have in the design document now.)<br class=""><br class="">Sent from my iPhone<br class=""><br class="">On Jul 30, 2017, at 8:51 PM, John McCall &lt;<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</a>&gt; wrote:<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">On Jul 29, 2017, at 7:01 PM, Daryle Walker via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class="">The “constexpr” facility from C++ allows users to define constants and functions that are determined and usable at compile-time, for compile-time constructs but still usable at run-time. The facility is a key step for value-based generic parameters (and fixed-size arrays if you don’t want to be stuck with integer literals for bounds). Can figuring out Swift’s story here be part of Swift 5?<br class=""></blockquote><br class="">Note that there's no particular reason that value-based generic parameters, including fixed-size arrays, actually need to be constant expressions in Swift.<br class=""><br class="">John.<br class=""></blockquote></blockquote><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></blockquote></blockquote></div></div></blockquote></div></div></div></blockquote></div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></body></html>