holg
a month ago
nice job! so i tried around and so far am impressed, anyhow:
\newcommand{\foo}[1]{\bar{#1}} \renewcommand{\bar}[1]{\foo{#1}} % mutual recursion \foo{x} \def\x{\y}\def\y{z}\x % chained expansion
+>
#set page(paper: "a4") #set heading(numbering: "1.") #set math.equation(numbering: "(1)") /* \foo / / \y /
\foo{x} → \bar{x} → \foo{x} → ∞ Expected: hit depth limit, emit warning, output either x or the unexpanded \foo{x} Actual: / \foo */ — silently converted to a comment, lost the argument x entirely
democat
a month ago
Thanks for the stress test! You are absolutely right, and I really appreciate you catching this edge case.
I've traced the issue in the codebase: 1. The recursion depth limit *is* triggering correctly (preventing an infinite loop). 2. However, when it bails out, it returns the partially expanded macro call (e.g., `\foo{x}`). 3. Since the macro definition was removed during the preprocessing step, the parser then sees `\foo` as an unknown command and converts it into an error comment, accidentally discarding the argument `{x}` in the process.
*The intended behavior* should definitely be to preserve the content (the `x`) even if the macro logic fails. I will fix the fallback logic to ensure it fails gracefully without eating the arguments.
Thanks again for the sharp eye! These kinds of checks are super helpful.