<div dir="ltr">I did paint ARC as the sole culprit, didn&#39;t I? It makes sense that there are other complications and it is interesting to note that ARC isn&#39;t the the primary reason.<div><br></div><div><div class="gmail_extra"><div class="gmail_quote">On Sat, Dec 5, 2015 at 9:00 PM, Joe Groff <span dir="ltr">&lt;<a href="mailto:jgroff@apple.com" target="_blank">jgroff@apple.com</a>&gt;</span> wrote:<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word"><div><br></div><div>- only allowing self-recursive tail calls, which avoid some of the stack and memory management problems with arbitrary tail calls,</div><div>- only allowing tail calls between functions in the same module, so that the compiler has enough information to use the tail-callable convention only where needed,</div><div>- only allowing tail calls between functions in the same module or external functions marked with a &#39;@tail_callable&#39; attribute.</div><font color="#888888"><br></font></div></blockquote><div><br></div><div>Even if none of these can be supported immediately, there is a case for adding the attribute with the note that there are almost no supported cases. Guaranteed support for self recursive tail calls, even if that is all we added, would be a huge addition, in my opinion. </div><div><br></div><div>I don&#39;t know how useful the third option would be but the second case is compelling. I am thinking of parser combinators in particular being a case where the second option could help.</div></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Dec 5, 2015 at 9:00 PM, Joe Groff <span dir="ltr">&lt;<a href="mailto:jgroff@apple.com" target="_blank">jgroff@apple.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Requiring an explicit &#39;tail&#39; annotation for tail calls is definitely the right way to approach this. However, ARC is not the only (or even the primary) reason tail recursion is problematic for Swift. ARC operations are not strictly ordered, unlike C++ destructors; the compiler is free to release values at any point after their last use. As long as a tail-callable function uses a convention where the callee takes ownership of all of its refcounted parameters, then ARC can avoid interfering with tail calls. However, there are other low-level resources that need to be managed in the case of an arbitrary tail call, such as space on the callstack and memory for indirectly-passed parameters. Being able to manage these would require a special machine-level calling convention that would have overhead we don&#39;t want to spend pervasively to make arbitrary functions tail-callable. Because of this, we&#39;d have to put further restrictions on what can be tail-called. Some options, in rough order of complexity, include:<div><br></div><div>- only allowing self-recursive tail calls, which avoid some of the stack and memory management problems with arbitrary tail calls,</div><div>- only allowing tail calls between functions in the same module, so that the compiler has enough information to use the tail-callable convention only where needed,</div><div>- only allowing tail calls between functions in the same module or external functions marked with a &#39;@tail_callable&#39; attribute.</div><span class="HOEnZb"><font color="#888888"><div><br></div><div>-Joe</div></font></span><div><br><div><blockquote type="cite"><div><div class="h5"><div>On Dec 5, 2015, at 5:55 AM, T.J. Usiyan &lt;<a href="mailto:griotspeak@gmail.com" target="_blank">griotspeak@gmail.com</a>&gt; wrote:</div><br></div></div><div><div><div class="h5"><div dir="ltr"><div><div>## Introduction</div><div><br></div><div>Tail call optimization can be a powerful tool when implementing certain types of algorithms. Unfortunately, ARC&#39;s semantics interfere with our ability to handle all possible cases of tail call recursion. An attribute, similar to Scala&#39;s `tailrec`, along with LLVM warnings, could allow a clear indicator of when such optimizations are not guaranteed to work.</div><div><br></div><div>## Motivation</div><div><br></div><div>LLVM will, currently, perform tail call optimization when possible cannot guarantee such optimizations. ARC can interfere with tail call recursion by inserting a method call after the intended &#39;last&#39; recursive call. The ability to insert this call is fundamental to ARC and, because of this, swift developers currently have no insight into when TCO can/will occur.</div><div><br></div><div>``` swift</div><div>func fact(input: Int) -&gt; Int {</div><div>    func _fact(n: Int, value: Int) -&gt; (n: Int, value:Int) {</div><div>        if n &lt;= 0 {</div><div>            return (0, value)</div><div>        } else {</div><div>            return _fact(n - 1, value: n * value)</div><div>        }</div><div>    }</div><div><br></div><div>    return _fact(input, value: 1).value</div><div>}</div><div>```</div><div>In the provided example, the developer can be sure that tail call optimization is possible but, without either a universal guarantee or something like the proposed attribute, there is no wait to be sure that such an optimization will occur.</div><div><br></div><div>## Proposed solution</div><div><br></div><div>Providing an attribute would provide developers with concrete klnowledge of when TCO can and will be performed by LLVM in compiling their swift code. </div><div><br></div><div>``` swift</div><div>func fact(input: Int) -&gt; Int {</div><div><span style="white-space:pre-wrap">        </span>@tailrec</div><div>    func _fact(n: Int, value: Int) -&gt; (n: Int, value:Int) {</div><div>        ...</div><div>```</div><div>With this attribute, the developer can express the desire for TCO and warnings can be emitted if TCO cannot be guaranteed. If there are currently only a few such cases, developers are made aware of what those cases are and can design implementations with this information at hand. As LLVM&#39;s ability to provide TCO increases, the allowed cases simply grow with no effect for the initial narrow cases.</div><div><br></div><div><br></div><div>## Detailed design</div><div>In an ideal situation, implementation of this feature can consist solely of the attribute and output from LLVM indicating whether or not the requested ptimization can be guaranteed. This proposal does not call for an expansion of accepted cases.</div><div><br></div><div>## Impact on existing code</div><div><br></div><div>This should not have any breaking impact as it is strictly additive and diagnostic.</div><div><br></div></div></div>
</div></div><span class=""><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=RoDF4MveSEMYBIqIJA6ub1g8cOZ-2BVYvqV-2FqygPhjPn-2B5aNYGJ3A3RQO6-2BeOzDFKEqWTykhyMRTmH-2BVuypfOD4XPp-2BVwYCdn1Q-2Bj0HXwAyGxCSFWo4CTiYSDdecclWBli0PlqexpKV0kHj9r7MGUIvlCE-2FTfzH9-2F8QaJlF3S8Grdp0DnYHALK5Wrp1tOfnTPfnv-2FcOCkr6TKNHGn3ZMiFQPS4e0emOjJEcQGAywQ2Baw-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></span></div></blockquote></div><br></div></div></blockquote></div><br></div>