[swift-evolution] Proposal: Tail Call Optimization keyword/attribute

Slava Pestov spestov at apple.com
Mon Dec 7 13:00:25 CST 2015


> On Dec 7, 2015, at 10:58 AM, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
> 
>> 
>> On Dec 5, 2015, at 10:52 AM, Joe Groff <jgroff at apple.com <mailto:jgroff at apple.com>> wrote:
>> 
>>> 
>>> On Dec 5, 2015, at 10:45 AM, T.J. Usiyan <griotspeak at gmail.com <mailto:griotspeak at gmail.com>> wrote:
>>> 
>>> I did paint ARC as the sole culprit, didn't I? It makes sense that there are other complications and it is interesting to note that ARC isn't the the primary reason.
>>> 
>>> On Sat, Dec 5, 2015 at 9:00 PM, Joe Groff <jgroff at apple.com <mailto:jgroff at apple.com>> wrote:
>>> 
>>> - only allowing self-recursive tail calls, which avoid some of the stack and memory management problems with arbitrary tail calls,
>>> - 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,
>>> - only allowing tail calls between functions in the same module or external functions marked with a '@tail_callable' attribute.
>>> 
>>> 
>>> 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. 
>>> 
>>> I don'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.
>> 
>> This seems like a reasonable evolution path. Getting only self-tail-calls working is indeed much simpler, and can likely be implemented mostly in SILGen by jumping to the entry block, without any supporting backend work. Arbitrary tail calls can be supported in the fullness of time.
> 
> One small thing: for completeness, any tail call proposal would have to describe how it interacts with `defer`. As currently specified, `defer` would have to block tail calling, since the deferred blocks occur after the return expression is evaluated. Either we accept this (which seems reasonable to me), or allow deferred blocks to be executed before the expression in a `tail return`, if there's a motivating reason.

Wouldn't the latter potentially break code?

func f() -> String {
  let fd = open(...)
  defer { close(fd) }
  return read(fd)
}

In other languages with TCO, defer-like constructs inhibit the optimization, and I see no reason to deviate from that here.

Slava

> 
> -Joe
> 
>  _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151207/10b4d2bf/attachment.html>


More information about the swift-evolution mailing list