<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 Aug 2, 2017, at 6:29 PM, Karl Wagner &lt;<a href="mailto:razielim@gmail.com" class="">razielim@gmail.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=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 3. Aug 2017, at 00:21, 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=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Aug 2, 2017, at 6:10 PM, John McCall via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; 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="">On Aug 2, 2017, at 5:56 PM, Karl Wagner &lt;<a href="mailto:razielim@gmail.com" class="">razielim@gmail.com</a>&gt; wrote:</div><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="">On 31. Jul 2017, at 21:09, John McCall via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><blockquote type="cite" class="">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="">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.<br class=""><br class="">That is, it would not be okay to have a type like:<br class="">&nbsp;struct Widget {<br class="">&nbsp;&nbsp;&nbsp;let length: Int<br class="">&nbsp;&nbsp;&nbsp;var array: [length x Int]<br class="">&nbsp;}<br class="">because the value of the bound cannot be computed independently of a specific value.<br class=""><br class="">But it is absolutely okay to have a type like:<br class="">&nbsp;struct Widget {<br class="">&nbsp;&nbsp;&nbsp;var array: [(isRunningOnIOS15() ? 20 : 10) x Int]<br class="">&nbsp;}<br class="">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.<br class=""></div></div></blockquote></div><br class=""><div class="">Do we really want to make that guarantee about heap/stack allocation? C99’s VLAs are not very loop-friendly:</div><div class=""><br class=""></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Menlo" class="">echo "int main() {&nbsp;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; for(int i = 0; i&lt;1000000; i++) {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int myArray[i * 1000]; myArray[0] = 32;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; return 0;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; }" | clang -x c&nbsp;- &amp;&amp; ./a.out</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">Segmentation Fault: 11</font></div></blockquote><div class=""><font face="Menlo" class=""><br class=""></font></div><div class="">C compilers also do not inline code with VLAs by default. If you force it, you expose yourself to possible stack overflows:</div><div class=""><font face="Menlo" class=""><br class=""></font></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Menlo" class="">echo "static inline void doSomething(int i) {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; int myArray[i * 1000]; myArray[0] = 32;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; int main() {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; for(int i = 0;&nbsp;i&lt;1000000; i++) {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; doSomething(i);</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; return 0;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; }" | clang -x c - &amp;&amp; ./a.out</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><span class="" style="font-family: Menlo;">Segmentation Fault: 11</span></div></blockquote><div class=""><br class=""></div><div class="">I wouldn’t like us to import these kinds of issues in to Swift</div></div></div></blockquote><div class=""><br class=""></div></div><span style="font-family: Helvetica; font-size: 12px; 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;" class="">We probably would not make an absolute guarantee of stack allocation, no.</span></div></blockquote><div class=""><br class=""></div>Although I will note that the problem in your example has nothing to do with it being a loop and everything to do with it asking for an almost 4GB array. :)</div><div class=""><br class=""></div><div class="">John.</div></div></div></blockquote></div><br class=""><div class=""><br class=""></div><div class="">Yeah, apologies - it was a bit of a poorly-written example.</div><div class=""><br class=""></div><div class="">The root cause, of course, is that the VLAs require new stack allocations each time, and the stack is only deallocated as one lump when the frame ends.</div></div></div></blockquote><div><br class=""></div><div>That is true of alloca(), but not of VLAs. &nbsp;VLAs are freed when they go out of scope. &nbsp;Your example crashes only because it is doing a huge stack allocation.</div><div><br class=""></div><div><div>#include &lt;unistd.h&gt;</div><div>#include &lt;fcntl.h&gt;</div><div><br class=""></div><div>void foo(size_t n) {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>int fd = open("/dev/null", O_RDONLY);</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>for (int i = 0; i &lt; 10000000; ++i) {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>char buffer[n];</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>read(fd, buffer, n);</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>close(fd);</div><div>}</div><div><br class=""></div><div>int main() {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>foo(100000);</div><div>}</div><div><br class=""></div></div><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="">A fixed-size object could be allocated once and re-used. Inlining prevents new stack frames being created and hence defers deallocation of those objects until the outer function ends, pushing up the high-water mark of the stack.</div><div class=""><br class=""></div><div class="">The problem also happens with an outer loop of only 10_000, so only 38MB. Still, enough to blow it up.</div></div></div></blockquote><div><br class=""></div></div>Operating systems generally impose limits on both the total size of the stack and the amount by which it can grow at once; 38MB is still likely large enough.<div class=""><br class=""></div><div class="">John.</div><div class=""><br class=""></div></body></html>