www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.ideas - Explicit tail calls

reply Guillaume Piolat <first.name gmail.com> writes:
The goal is ensuring tail-calls without compiler extension, it's 
useful only for interpreters and VM AFAIK.

There is a proposal for C here: 
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2920.pdf


     float fun1(int, int, int);

     int fun2 (int a, int b, int c)
     {
         return goto fun1(c, b, a); // "return goto" ensures a 
tail call
     }

Now, such a simple syntax tweak probably has large effects on the 
language.

- ` live` should disallow returning a live object.
- `pure` works if fun1 is `pure`
- `nothrow` works if fun1 is `nothrow`
- ` nogc` works if fun1 is ` nogc`
- Not sure how destructors inside fun2 get handled...
- interacts with exceptions: can't throw inside return goto 
expressions and get back to the place you were. I would limit the 
possibility to nothrow functions?
- function pointers?
- delegates?
Apr 09
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 10/04/2026 3:22 AM, Guillaume Piolat wrote:
 The goal is ensuring tail-calls without compiler extension, it's useful 
 only for interpreters and VM AFAIK.
 
 There is a proposal for C here: https://www.open-std.org/jtc1/sc22/wg14/ 
 www/docs/n2920.pdf
 
 
      float fun1(int, int, int);
 
      int fun2 (int a, int b, int c)
      {
          return goto fun1(c, b, a); // "return goto" ensures a tail call
      }
 
 Now, such a simple syntax tweak probably has large effects on the language.
 
 - ` live` should disallow returning a live object.
 - `pure` works if fun1 is `pure`
 - `nothrow` works if fun1 is `nothrow`
 - ` nogc` works if fun1 is ` nogc`
 - Not sure how destructors inside fun2 get handled...
 - interacts with exceptions: can't throw inside return goto expressions 
 and get back to the place you were. I would limit the possibility to 
 nothrow functions?
 - function pointers?
 - delegates?
I've been reviewing dmd's backends tail call optimization. Without reviewing the literature, I cannot come up with any improvements to it. Moving tail call optimization, from an optimization to the calling convention is a much bigger ask than an alteration on the return statement. For LLVM at least, its function wide, you cannot guarantee it on the statement. I don't see a way to progress this at this point in time.
Apr 09
parent Serg Gini <kornburn yandex.ru> writes:
On Friday, 10 April 2026 at 06:14:55 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 Without reviewing the literature, I cannot come up with any 
 improvements to it.

 Moving tail call optimization, from an optimization to the 
 calling convention is a much bigger ask than an alteration on 
 the return statement.

 For LLVM at least, its function wide, you cannot guarantee it 
 on the statement.

 I don't see a way to progress this at this point in time.
adding info to the context: - link with discussion and PR for LDC https://github.com/ldc-developers/ldc/discussions/4355 - recent blog about Rust implementation https://www.mattkeeter.com/blog/2026-04-05-tailcall/ - nice overview of other langs (incl GCC/LLVM) https://blog.reverberate.org/2025/02/10/tail-call-updates.html
Apr 09