<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 4 août 2017 à 11:39, Robert Bennett <<a href="mailto:rltbennett@icloud.com" class="">rltbennett@icloud.com</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=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class=""></div><div class=""><blockquote type="cite" class="">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></blockquote></div><div class=""><br class=""></div><div class="">Good point. If this is only problematic when multiple threads are accessing an array, then it could still be worthwhile if all accesses are (provably) on the thread that created the array.</div></div></div></div></blockquote><div><br class=""></div><div>To be clear, it's a problem independently of multi-threading. `func foo() -> [Int] { return [1, 2, 3] }` is the most basic representation of it: you can't store the array in the stack frame if you return it. (To be fair, that one would be caught by escape analysis of any quality.) `func foo() { bar([1, 2, 3, 4]) }` is another example: if you don't know what `bar` does with the array, you can't store it on the stack because it might pass it to an object that lives on the heap and outlives `foo`, for instance. @escaping solves that problem for closures by specifically annotating parameters when the assigned closure could still be referenced after the called function returns.</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 dir="auto" class=""><div class="">And pessimistic copying might still be worth it for arrays below a certain size — for instance, copying an Array<Int> of length 1 (and recall that the array in question is a constant so its size is known at compile time) would definitely be worth not having that array in heap memory.</div></div></div></div></blockquote><div><br class=""></div><div>You only need pessimistic copies when that copy escapes, and since it escapes, it needs to live on the heap by definition. Right now an array of size 1 passed to 4 objects on the heap has one single backing representation. With pessimistic copies, you'd get 4 times that buffer of size 1, which is definitely not an improvement.</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 dir="auto" class=""><div class="">Going back to the literal notion of FSAs — fixed size arrays not necessarily on the stack — I think that simply copying Array’s implementation sans RangeReplaceableCollection conformance is not a bad way to go. Any optimizations used for `let` Arrays could probably be applied to this type of FSA.</div></div></div></div></blockquote></div><br class=""><div class="">We're actually splitting this in multiple directions. John talks of variable-sized arrays necessarily on the stack. :)</div><div class=""><br class=""></div><div class="">I see two useful characteristics to fixed-size arrays, which, uncoincidentally, are what it takes to use them for C interop:</div><div class=""><br class=""></div><div class=""><ul class="MailOutline"><li class="">Their storage is inlined into their container (whether it be the stack or an object)</li><li class="">Their length is part of their type (and not directly included with the data itself)</li></ul><div class=""><br class=""></div></div><div class="">This is also enough to implement fixed-size arrays not necessarily on the stack, mind you.</div><div class=""><br class=""></div><div class="">Félix</div></body></html>