Issue #935: Mutual recursion of pausing functions across two files of a project fails in rustc (“Recursion in an async fn requires boxing”)

Open and answer this issue on GitHub.

ready · opened 2026-10-29 · updated 2026-10-29 · 1 comment

Found while changing the converter (crates/rs2nika/convert): todo in tr_core.nika started calling expr in tr_expr.nika, which already called todo. rustc then refused the lowered code. Once todo was moved into tr_expr.nika, the same code compiled.

Probe (a project; nikaia run):

src/main.nika

use std::fs

fn down(n: i64) -> i64 {
    if n == 99 {
        let s = fs::read_to_string("x", fs::Root::Anywhere) catch { "" }
        return s.len()
    }
    if n <= 0 {
        return 0
    }
    return up(n - 1) + 1
}

fn main() {
    println(f"{down(5)}")
}

src/other.nika

fn up(n: i64) -> i64 {
    if n <= 0 {
        return 0
    }
    return down(n - 1) + 1
}

What happens:

error: Recursion in an async fn requires boxing.
  --> src/main.nika:3:1

What should happen: it prints 5.

The variations narrow it down:

So the lowering finds the recursion cycle of pausing functions, and boxes their futures, only within one file. A cycle that crosses files is missed.

To build

Comments

keywan-ghadami, 2026-10-29

Triage (#982), class B: waits for the rest of emit/mod.rs (E11 / E13, with_contracts’ analyses). emit/mod.rs:826 computes pausing_reach from one file’s items. Still reproduces at de0bb82.


Generated by Claude Code

Back to Open Issues