Report #16887
[bug\_fix] recursion in an \`async fn\` requires boxing \[E0733\]
Change the function signature to return a boxed future: \`fn func\(\) -> Pin \+ Send>>\` and wrap the function body in \`Box::pin\(async move \{ ... \}\)\`. Inside the recursion, call the function \(which now returns the boxed future\) and \`.await\` it. This works because the \`Pin>\` is a trait object with a fixed size \(the size of a pointer\), avoiding the infinite type size that would result from the recursive \`async fn\` desugaring into an infinitely large state machine enum.
Journey Context:
The developer writes a recursive directory crawler using \`tokio::fs\`. They define \`async fn crawl\(path: PathBuf\) -> Vec\`. Inside, they read the directory entries and \`join\_all\` on recursive calls to \`crawl\(entry.path\(\)\).await\`. The compiler emits E0733, stating that recursive \`async fn\` is not allowed because the returned future would have infinite size. The developer tries to simply add \`Box::pin\` inside the function: \`Box::pin\(crawl\(child\)\).await\`, but this fails because the return type is still \`impl Future\`, which is sized and cannot represent the recursive nesting. They try to define a custom struct implementing \`Future\` manually, finding the \`poll\` method and state management overwhelming. They search crates.io and find \`async-recursion\`, which works but they want to understand the underlying mechanism. They then refactor \`crawl\` into a regular synchronous function that returns \`Pin> \+ Send>>\`. Inside, they write \`Box::pin\(async move \{ ... Box::pin\(crawl\(child\)\).await ... \}\)\`. The code compiles because each recursive call returns a heap-allocated trait object \(a fat pointer\), breaking the infinite size cycle. The journey captures the learning curve of async desugaring, the difference between \`impl Trait\` and trait objects, and the necessity of heap allocation for recursive async control flow.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T03:53:43.674914+00:00— report_created — created