Skip to content

Remove IntoIterator bound from KeyedSubfield#4605

Open
tysen wants to merge 1 commit intoleptos-rs:mainfrom
tysen:main
Open

Remove IntoIterator bound from KeyedSubfield#4605
tysen wants to merge 1 commit intoleptos-rs:mainfrom
tysen:main

Conversation

@tysen
Copy link
Copy Markdown
Contributor

@tysen tysen commented Mar 1, 2026

The KeyedSubfield struct previously had a struct-level bound:

pub struct KeyedSubfield<Inner, Prev, K, T>
where
for<'a> &'a T: IntoIterator,
{ ... }

This causes infinite trait resolution when used alongside, for example, bevy_ecs. The root cause is that bevy_ecs has a blanket implementation:

impl<'w, 's, T: Resource> IntoIterator for &Res<'w, 's, T> { ... }

During compilation we end up recursing infinitely checking Res<..>, Res<Res<..>>, Res<Res<Res<..>>> and so on.

This commit replaces that bound w/ a new trait KeyedIterable and moves the IntoIterator bound to the impl blocks where it's actually needed.

The downside of this is that reactive_stores must now explicitly impl this trait for supported collections, so support for 3rd-party collections (e.g. DashMap) will need to be added here as requested (because of the orphan rule).


This is of course a big breaking change for this crate. I think it's warranted as bevy is pretty popular, there is plenty of bevy + leptos interest (see 1, 2), and this problem is not unique to bevy_ecs but would happen when combining reactive_stores w/ any crate that has a blanket IntoIterator impl on a wrapper type (like Res).

Were this to be merged, impls of KeyedIterable for 3rd party collections will have to live here, gated behind feature flags. This is a fairly common practice but if that's too big of a change and/or you'd rather not, feel free to close as wontfix and I'll keep using my fork.

The `KeyedSubfield` struct previously had a struct-level bound:

```
pub struct KeyedSubfield<Inner, Prev, K, T>
where
for<'a> &'a T: IntoIterator,
{ ... }
```

This causes infinite trait resolution when used alongside, for example, `bevy_ecs`.
The root cause is that `bevy_ecs` has a blanket implementation:

```
impl<'w, 's, T: Resource> IntoIterator for &Res<'w, 's, T> { ... }
```

During compilation we end up recursing infinitely checking `Res<..>`,
`Res<Res<..>>`, `Res<Res<Res<..>>>` and so on.

This commit replaces that bound w/ a new trait `KeyedIterable` and moves
the `IntoIterator` bound to the impl blocks where it's actually needed.

The downside of this is that `reactive_stores` must now explicitly impl
this trait for supported collections, so support for 3rd-party
collections (e.g. `DashMap`) will need to be added here as requested
(because of the orphan rule).
@tysen
Copy link
Copy Markdown
Contributor Author

tysen commented Mar 3, 2026

Fixes #4612

@gbj
Copy link
Copy Markdown
Collaborator

gbj commented Mar 4, 2026

I think I'm fine with this in principle, although I haven't read through the PR in detail. In practice I think we already need support within the crate for collection types to be used as KeyedSubfield because we need KeyedAccess implemented anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants