<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="">Le 6 août 2017 à 08:15, Karl Wagner &lt;<a href="mailto:razielim@gmail.com" class="">razielim@gmail.com</a>&gt; a écrit :</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=""><br class="Apple-interchange-newline">On 4. Aug 2017, at 20:15, 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="" 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;"><blockquote type="cite" class=""><div class=""><br class="Apple-interchange-newline">On Aug 4, 2017, at 1:19 PM, Félix Cloutier 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="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">That's not a concern with the `let` case that Robert brought up, since you can't mutate a `let` array at all.<div class=""><br class=""></div><div class="">The big thing is that unconstrained escape analysis is uncomputable. Since Swift array storage is COW, any function that receives the array as a parameter is allowed to take a reference on its storage. If the storage lives on the stack and that reference outlives the stack frame, you've got a problem. It's the same problem that motivated @escaping for closures.</div><div class=""><br class=""></div><div class="">You could allow storage to be on the stack by forcing user to make a pessimistic copy, which is possibly not an improvement.</div></div></div></blockquote><div class=""><br class=""></div>Right. &nbsp;I think maybe the name people keeping using for this feature is misleading; a better name would be "inline arrays" or "directly-stored arrays". &nbsp;Having a fixed size is a necessary condition for storing the array elements directly, but the people asking for this feature are really asking for the different representation, not just the ability to statically constrain the size of an array.</div><div class="" 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;"><br class=""></div><div class="" 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;">That representation difference comes with a lot of weaknesses and trade-offs, but it's also useful sometimes.</div><div class="" 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;"><br class=""></div><div class="" 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;">John.</div><div class="" 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;"><br class=""></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="">Right, and the question I’ve been asking (indirectly) is: why is this only useful for arrays?</span></div></blockquote><div><br class=""></div><div>One special thing about fixed-size arrays is that they address the sore spot of C interop.</div><br class=""><blockquote type="cite" class=""><div class=""><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="">Doesn’t it really apply to any value-type which allocates storage which it manages with COW semantics (e.g. Dictionary, Set, Data, your own custom types…)? Really, we want to inform the compiler that the dynamically-allocated memory is part of the value - and if it sees that the storage is only allocated once, it should be allowed to allocate that storage inline with the value, on the stack.</span></div></blockquote><div><br class=""></div><div>Assuming that fixed-size arrays are a different type (like FixedSizeArray&lt;T, N&gt; vs Array&lt;T&gt;), the feature work that supports them would likely be sufficient to support fixed-size whatever collections, too. However (and I'm talking a bit through my hat here, that's not my area of expertise), I think that there could be some drawbacks to implementing some other collections in a fixed amount of memory. For instance, you have to decide on a fixed number of buckets for sets and dictionaries, regardless of what ends up in the collection. Dictionaries and sets also tend to use more memory than arrays, which could cause storage size to balloon up to degrees that are not immediately obvious.</div><br class=""><blockquote type="cite" class=""><div class="" 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;">As I understand it, the only problem with this is when a function takes such a value as a parameter and assigns it to some escaping reference (an ivar, global, or capturing it inside an escaping closure).</div><div class="" 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;"><br class=""></div><div class="" 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;">So why can’t such assignments simply check if the value has inline storage and copy it to the heap if necessary? The compiler should be able to optimise the function so the check (which is really cheap anyway) only needs to happen once per function. Because the entire type has value semantics, we can substitute the original value with the copy for the rest of the function (preventing further copies down the line).</div></blockquote><div><br class=""></div><div>The rest of the function might not be enough, especially if you use the same array for multiple calls. See:</div><div><br class=""></div><div><div></div><blockquote type="cite" class=""><div>var globalArray = [[Int]]</div><div>func append(array: [Int])</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>globalArray.append(array)</div><div>}</div><div><br class=""></div><div>func foo() {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>let bar = [1,2,3]</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>append(array: bar)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>append(array: bar)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>append(array: bar)</div><div>}</div></blockquote><div><br class=""></div><div>The function that escapes the array is `append(array:)`, so you'd get one copy per call to `append(array:)`, unless functions start annotating the escaping behavior of each parameter. That could work in many cases, but the compiler would still have to be pessimistic in common instances, like when calls to virtual functions are involved, including closures and calls to methods of objects represented as protocol instances. (Also, the amount of work required is likely to be significant.)</div><div><br class=""></div><div>Félix</div><div><br class=""></div></div></div></body></html>