DioxusLabs / DioxusLabs/dioxus
#[component] with `Signal` props + axum 0.8 in same crate → rustc trait-resolution infinite loop via `&objc2::Retained<T>: IntoIterator` (aarch64-darwin)
- Dominant language
- Rust
- Stars
- 39.1k
- Forks
- 1.9k
- Avg merge
- 4d 10h
- Merged PRs (30d)
- 4
Description
**Environment**
- rustc 1.97.1 (8bab26f4f 2026-07-14), stable
- Host: `aarch64-apple-darwin` (macOS Darwin 24.6.0)
- `dioxus = "0.7.9"` with features `["router", "html", "hooks", "signals", "document", "fullstack", "server"]`
- Transitively pulls `manganis 0.7.9` → `objc2 0.6.4` (macOS-only)
## Summary
When a crate has `axum = "0.8"` in its dependency graph **and** defines a `#[component]` composition using `Form { Field { Input { value: Signal } } }` (nested `Signal`-carrying components), rustc enters an unbounded trait-resolution loop while trying to prove `IntoIterator for &objc2::rc::Retained`. The search recurses through `Retained>>` and never terminates.
- With rustc's default thread stack: **SIGBUS** during `rustc_trait_selection` (backtrace hits `TypeFoldable::fold_with` → `OpportunisticVarResolver`).
- With `RUST_MIN_STACK=134217728` (128 MiB): no SIGBUS, but E0275 reports "N redundant requirements hidden". Bumping `#![recursion_limit = "1024"]` yields "1021 redundant requirements hidden" — genuinely unbounded, not just under-quota.
Does **not** reproduce with the same components + Dioxus 0.7.9 on `axum = "0.7"` — the trigger requires axum 0.8 specifically.
Does **not** reproduce if any of `Form`, `Field`, or `Input` is removed from the composition. Simpler `#[component]` fns with `Signal` props (e.g. a lone `Button { onclick }`) compile fine.
## Bisected trigger
Reduction ladder (each `+` compiles, each `SIGBUS` fails):
| Crate contents | Result |
|------------------------------------------------------|----------|
| axum 0.8 + our JSON handlers, no `ui::*` | + |
| … + `pub mod ui;` (empty App component) | + |
| … + dashboard view (Card, Alert, Badge only) | + |
| … + tenants view (DataTable, no Form) | + |
| … + login view with `Form { on_submit }` only | + |
| … + login view with `Form { Field { Input { ... }}}` | **SIGBUS** |
Minimal repro shape (~30 LOC on top of a fresh `cargo new`):
```rust
// packages/ui/src/lib.rs
use dioxus::prelude::*;
#[component]
pub fn Form(on_submit: EventHandler, children: Element) -> Element {
rsx! { form { onsubmit: move |e| on_submit.call(e), {children} } }
}
#[component]
pub fn Field(label: String, children: Element) -> Element {
rsx! { div { label { "{label}" } {children} } }
}
#[component]
pub fn Input(value: Signal) -> Element {
rsx! { input { value: "{value}", oninput: move |e| value.set(e.value()) } }
}
```
```rust
// packages/repro/src/lib.rs — a crate with axum 0.8 in its dep graph
use axum::Router; // 0.8 required
use dioxus::prelude::*;
use ui::{Form, Field, Input};
#[component]
pub fn LoginView() -> Element {
let email = use_signal(String::new);
let on_submit = move |_e: FormEvent| {};
rsx! {
Form { on_submit,
Field { label: "Email".into(),
Input { value: email }
}
}
}
}
pub fn build() -> Router { Router::new() }
```
`Cargo.toml` (repro crate):
```toml
[dependencies]
axum = "0.8"
dioxus = { version = "0.7.9", features = ["router", "html", "hooks", "signals", "document"] }
ui = { path = "../ui" }
```
Then: `cargo check -p repro` on `aarch64-apple-darwin` → SIGBUS during trait resolution.
## Full rustc error tail
With `RUST_MIN_STACK=134217728` and `#![recursion_limit = "1024"]`:
```
error[E0275]: overflow evaluating the requirement `&itertools::groupbylazy::GroupBy<_, _, _>: IntoIterator`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "2048"]` attribute
= note: required for `&Retained>` to implement `IntoIterator`
= note: 1021 redundant requirements hidden
= note: required for `&Retained>>>>>` to implement `IntoIterator`
```
The `Retained` in the trace is `objc2::rc::Retained` — reached transitively via `manganis` → `objc2`. `itertools::groupbylazy::GroupBy` comes in through `prost-derive 0.14`, which is a proc-macro-time dep of the axum 0.8 → tonic → prost chain.
## Hypothesis
axum 0.8 introduced a blanket impl or associated-type projection in the extractor/handler machinery that opens a new trait-search path when combined with Dioxus 0.7.9's `#[derive(Props)]` on `Signal`-carrying props. rustc walks every impl of `IntoIterator` — including `Retained`'s blanket `impl IntoIterator for &Retained` (or similar shape). Because the impl is unconditional in `T`, the answer to `&Retained: IntoIterator?` recurses into `&Retained>: IntoIterator?` with no fixed point.
## Workarounds tried
- `RUST_MIN_STACK=256MB` — clears the SIGBUS but does not clear the E0275 loop
- `#![recursion_limit = "2048"]` — hits "N redundant requirements hidden" up to N-1
- Removing `chorale-dioxus` (which had `itertools::GroupBy` in its own generics) — no change; `prost-derive` still pulls `itertools` in
- Downgrading to axum 0.7 — clears everything
Currently working around by staying on axum 0.7 across the whole workspace and using `dioxus-ssr` (no fullstack, no server functions) to render Dioxus components into `Html` from hand-written axum handlers.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the minimal repro in packages/ui/src/lib.rs and packages/repro/src/lib.rs, then run cargo check -p repro on aarch64-apple-darwin with axum 0.8 and compare it with axum 0.7. Trace the trait-resolution path involving Signal props, Retained, and IntoIterator. Done means the axum 0.8 composition no longer reaches SIGBUS or an unbounded E0275 overflow.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- full-stack
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100