[m-dev.] require_tail_recursion(name/arity, [none])

Julien Fischer jfischer at opturion.com
Sun Jun 7 03:12:50 AEST 2026


On Sat, 6 Jun 2026 at 16:33, Zoltan Somogyi <zoltan.somogyi at runbox.com> wrote:
>
>
> On Fri, 05 Jun 2026 16:21:34 +1000 (AEST), "Zoltan Somogyi" <zoltan.somogyi at runbox.com> wrote:
> > The existing require_tail_recursion pragma controls diagnostics in one of two ways:
> >
> > - in the usual case where --warn-non-tail-recursion is not set, it ENABLES diagnostics
> >   about non-tail recursion for a pred or func, and
> >
> > - in the case where --warn-non-tail-recursion IS set, it can DISABLE those very same
> >   diagnostics for a pred or func.
> >
> > People can now do the latter by specifying the option "none". This option is completely
> > different from all the other options, and is also incompatable with all of them.
> > Instead of trying to describe this clusterfck in the manual, I would prefer to
> > simply describe a simple pragma that disables these diagnostics for a pred or func
> > in the presence of --warn-non-tail-recursion.
>
> After working on this more, I find that the above is what the documentation said
> the pragmas and options would do, but is not what they ACTUALLY do. The reality
> is that to print a report about non-tail recursion, you need both a require_tail_recursion
> pragma AND the --warn-non-tail-recursion option. In other words, not specifying
> --warn-non-tail-recursion shuts up warnings about recursive calls that are not tail recursive
> even in predicates that have require_tail_recursion pragmas. (It does let through diagnostics
> about require_tail_recursion pragmas for predicates that contain no recursive calls, which
> seems a bit strange.)
>
> I would prefer to change this to something like what I described in the quoted email,
> meaning that
>
> - if a predicate has a require_tail_recursion pragma, then it gets both reports about recursive calls
>   that are not TAIL recursive, and about the predicate containing no recursive calls at all
>   (which makes the pragma useless), while
>
> - if a predicate does not have a require_tail_recursion pragma, but --warn-non-tail-recursion
>   is set (to either self or self-and-mutual), then it also gets reports about non-tail recursion
>   (of the requested types), but does not get reports about no recursive calls at all.
>   And any reports it does get could be disabled by a disable_non_tail_recursion_report pragma.
>
> Would anyone object to this?

No objection from me.

> And would this scheme require a new option that users
> can specify to shut up all the reports that the above can generate? (I don't think so,
> but I am open to arguments in favor of such an option.)
>
> On a separate but related note: mark_tail_calls.m does two jobs: it generates reports about
> non-tail recursion, and it marks tail calls. Diagnostics generation is backend-agnostic, but
> the MLDS backend needs tail calls marked much, much more than the LLDS backend.
> In the MLDS backend, tail call markings are essential for enabling tail recursion. In the LLDS
> backend, they are not needed at all, with one minor exception: when --exec-trace-tail-rec
> is enabled, which is rare in my experience.
>
> Despite this, it is the LLDS backend that *always* invokes mark_tail_calls.m, while the MLDS
> backend does so only if --enable-tailcalls is set. (That option is used only by the MLDS backend,
> so this name is somewhat misleading.) Since --enable-tailcalls is enabled at optimization level 1,
> and the default 2, this is functionally equivalent to the LLDS case, with the complication of that
> things behave differently with -O0. I would like to avoid this complication (to avoid the need
> to document it) by making the MLDS backend also invoke mark_tail_calls.m without consulting
> that option. Would anyone object to that?

Again, no objection from me.

> I am in two minds about whether users should have access to --no-enable-tailcalls at all.

The actual options are either --no-optimize-tailcalls or
--pessimize-tailcalls. (Why do
we have two?) According to the usage message for the latter, it exists to reduce
code size at the expense of runtime -- that's almost certainly not
useful any more
(if it ever was).

> The only circumstance in which it would be useful to them is when the implementation
> of tail-recursive-SCCs in the MLDS code generator has a bug, but the rest of the MLDS
> code generator is ok. Other than that situation, which most users would not be able to recognize,
> --enable-tailcalls is clearly better for them.
>
> For us developers, such an option can help debug changes to the code generator, and it can
> help with benchmarking, but for that, a private, developer-only option is sufficient, and we can
> tweak the operation of a private option more freely. We could also give it a less misleading
> and more descriptive name. What do you guys think?

I think we make it a developer-only option.

Julien.


More information about the developers mailing list