Skip to content

Fix recursion limits with next solver - #9953

Merged
ErichDonGubler merged 3 commits into
gfx-rs:v30from
nazar-pc:fix-recursion-limits-next-solver
Aug 27, 2026
Merged

Fix recursion limits with next solver#9953
ErichDonGubler merged 3 commits into
gfx-rs:v30from
nazar-pc:fix-recursion-limits-next-solver

Conversation

@nazar-pc

Copy link
Copy Markdown
Contributor

Connections

#9608, #9609

Description

This is a much better alternative to #9609 that solves the same underlying issue. The root cause is that next solver has a really hard time figuring out auto traits and ultimately fails with default recursion limit.

I later discovered that this is infectious, meaning not only wgpu needs to raise limits, but any crate that uses a lot of its types. The solution is to help solver a little bit and implement the traits manually. The code is more or less a macro expansion from https://crates.io/crates/non_structural_derive applied to the core type that is used basically everywhere.

This small change removes the need to increase recursion limits both here and for downstream users and I believe should help with compilation time as well.

Testing

Checked whether workspace compiles with cargo clippy.

Checklist

  • I self-reviewed and fully understand this PR.
  • WebGPU implementations built with wgpu may be affected behaviorally.
  • Validation and feature gates are in place to confine behavioral changes.
  • Tests demonstrate the validation and altered logic works.
  • CHANGELOG.md entries for the user-facing effects of this change are present.
  • The PR is minimal, and doesn't make sense to land as multiple PRs.
  • Commits are logically scoped and individually reviewable.
  • The PR description has enough context to understand the motivation and solution implemented.

@nazar-pc
nazar-pc force-pushed the fix-recursion-limits-next-solver branch 2 times, most recently from e1928b5 to d7c5a2c Compare July 28, 2026 15:01
@nazar-pc

This comment was marked as resolved.

@nazar-pc
nazar-pc force-pushed the fix-recursion-limits-next-solver branch from d7c5a2c to 38dc8c9 Compare July 28, 2026 15:02
Comment thread wgpu-core/src/global.rs Outdated
Comment thread wgpu-core/src/global.rs Outdated
jimblandy

This comment was marked as outdated.

jimblandy

This comment was marked as resolved.

@nazar-pc
nazar-pc force-pushed the fix-recursion-limits-next-solver branch from caf0552 to ab22123 Compare July 29, 2026 15:57
@nazar-pc
nazar-pc requested a review from jimblandy July 29, 2026 15:57
Comment thread wgpu-core/src/global.rs Outdated
@nazar-pc
nazar-pc requested a review from kpreid July 31, 2026 04:29
@kpreid
kpreid force-pushed the fix-recursion-limits-next-solver branch from 3207e16 to acc16f5 Compare July 31, 2026 16:26
@kpreid

This comment was marked as resolved.

@andyleiserson andyleiserson added the area: core Issues related to wgpu-core label Aug 5, 2026
@inner-daemons
inner-daemons removed their request for review August 5, 2026 23:17
@nazar-pc

This comment was marked as resolved.

@ErichDonGubler

This comment was marked as resolved.

@ErichDonGubler ErichDonGubler left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty self-contained (minus a licensing issue I noticed), so I see no objection with it.

@jimblandy, @kpreid: I'm going to merge this in the next day or so (pending conversation in fee1-dead/non_structural_derive#1 (comment)), unless you have an objection.

Comment thread wgpu-core/src/global.rs
Comment on lines +297 to +300
/// This improves compilation performance and avoids a risk of dependents running into the default
/// [`recursion_limit`] when checking types containing [`Global`]. This risk will become greater
/// when Rust’s “next solver” is stabilized.
///

@ErichDonGubler ErichDonGubler Aug 11, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question(non-blocking): Is there anything we can do to quantitatively substantiate this? Removing the recusion_limit attributes is enough to justify this, OFC, I was just curious if this significantly affected build timings at all (which is how I'd interpret "compilation performance" here).

Comment thread wgpu-core/src/global.rs
///
/// [`recursion_limit`]: https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute
#[cfg(send_sync)]
mod global_send_sync {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: Oooh, I really like keeping this all contained in a module with a single cfg. 😀

Comment thread wgpu/src/lib.rs
Comment on lines -219 to -220
// `-Znext-solver` requires deeper recursion limits (at least for now) to prove Send/Sync
#![recursion_limit = "256"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: It's always nice to avoid recursion_limit attributes. I know that this is the same topic that introduced them in #9609, it's just nice to bend the trade-off curve.

Comment thread wgpu-core/src/global.rs Outdated
@ErichDonGubler ErichDonGubler added the changelog: released entry changed Allows the PR to modify released. This is uncommon. label Aug 11, 2026
@ErichDonGubler
ErichDonGubler force-pushed the fix-recursion-limits-next-solver branch from acc16f5 to 1c380d1 Compare August 11, 2026 08:55
@ErichDonGubler

Copy link
Copy Markdown
Member

Rebased strictly to resolve the conflict that was present in the CHANGELOG.

@ErichDonGubler
ErichDonGubler dismissed jimblandy’s stale review August 11, 2026 08:56

Feedback appears satisfied.

@kpreid

kpreid commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Today I was doing some work with nightly, and surprised to find that this PR hasn’t yet been merged.

I tried to rebase it to help it along, but I find that I do not know how it should interact with the recent wgpu-core-remote work, most particularly, #10074 saying "Global does not need to be Send or Sync".

@andyleiserson

Copy link
Copy Markdown
Contributor

I guess the question is, if Global is no longer Send / Sync, what types are now causing problems with the new solver? Or do we need to put something (PhantomData<*const ()>?) in Global to help the solver conclude !Send/!Sync?

@ErichDonGubler ErichDonGubler moved this from To triage to Small in Triage Aug 26, 2026
@kpreid

kpreid commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

From discussion in today’s meeting:

  • This change in its current form should be applied to the v30 branch, for the benefit of people who are using wgpu v30.

  • On trunk, Global is now part of wgpu-core-remote and is not used by wgpu. Therefore, the remaining question is: do we need to address any recursion limit issues in the new architecture?

    I am testing with my application all-is-cubes and it seems that the answer is yes. For example, with a recursion_limit slightly reduced to 100 (to get a more useful report than one that shows only non-wgpu types in a different case):

warning: overflow evaluating the requirement `wgpu::Device: Sync`
  --> all-is-cubes-gpu/src/lib.rs:29:13
   |
29 | static FOO: wgpu::Device = todo!();
   |             ^^^^^^^^^^^^
   |
   = note: which requires `wgpu::dispatch::DispatchDevice: Sync`
   = note: which requires `Arc<wgpu::backend::wgpu_core::CoreDevice>: Sync`
   = note: which requires `wgpu::backend::wgpu_core::CoreDevice: Send`
   = note: which requires `wgpu::backend::wgpu_core::ContextWgpuCore: Send`
   = note: which requires `Arc<wgpu::wgpu_core::instance::Instance>: Send`
   = note: which requires `wgpu::wgpu_core::instance::Instance: Send`
   = note: which requires `wgpu::wgpu_core::instance::InstanceDevices: Send`
   = note: which requires `wgc::lock::vanilla::Mutex<wgc::weak_vec::WeakVec<wgpu::wgpu_core::device::Device>>: Send`
   = note: which requires `lock_api::mutex::Mutex<wgpu_sync::mutex::RawMutex, wgc::weak_vec::WeakVec<wgpu::wgpu_core::device::Device>>: Send`
   = note: which requires `wgc::weak_vec::WeakVec<wgpu::wgpu_core::device::Device>: Send`
   = note: which requires `Vec<alloc::sync::Weak<wgpu::wgpu_core::device::Device>>: Send`
   = note: which requires `alloc::raw_vec::RawVec<alloc::sync::Weak<wgpu::wgpu_core::device::Device>>: Send`
   = note: which requires `PhantomData<alloc::sync::Weak<wgpu::wgpu_core::device::Device>>: Send`
   = note: which requires `alloc::sync::Weak<wgpu::wgpu_core::device::Device>: Send`
   = note: which requires `wgpu::wgpu_core::device::Device: Send`
   = note: and so on...

@nazar-pc

Copy link
Copy Markdown
Contributor Author

Should I rebase and re-target this on v30 branch or open a new PR?

For the new version, I'm not sure it is worth investing into fixing something that doesn't happen with the default limit, but I can look into that once v30 is fixed if you want. Should be fairly easy now that we know how to address it.

@kpreid

kpreid commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Should I rebase and re-target this on v30 branch or open a new PR?

I think re-targeting this PR makes sense.

For the new version, I'm not sure it is worth investing into fixing something that doesn't happen with the default limit,

Two considerations:

  1. It’s near the default limit, which means that applications which put wgpu types in their own nontrivial types are likely to hit the limit, and this really isn’t their fault.
  2. As you note in the PR description, it should help with compilation time (by moving the recursive Send/Sync checks from the dependents to wgpu-core itself). In graphics applications, iteration time is important, and so if we can do something reasonably-sized to help users’ code compile faster, we should.

I can look into that once v30 is fixed if you want.

I’d like to try doing it myself. I have an idea for how it should work: instead of trying to find the right place in the internals, how about we do it inside of wgpu/src/dispatch.rs, in the macro-generated dispatch enums? This nearly maximizes the benefit by doing it near the API surface, and only needs to be written once even as the API and implementation evolve.

@kpreid

kpreid commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

I’d like to try doing it myself. I have an idea for how it should work: instead of trying to find the right place in the internals, how about we do it inside of wgpu/src/dispatch.rs, in the macro-generated dispatch enums? This nearly maximizes the benefit by doing it near the API surface, and only needs to be written once even as the API and implementation evolve.

Posted #10177 — a draft PR, to see if CI immediately turns up any problems with this approach.

@nazar-pc
nazar-pc force-pushed the fix-recursion-limits-next-solver branch from 755831b to 17d1182 Compare August 26, 2026 19:13
@nazar-pc
nazar-pc changed the base branch from trunk to v30 August 26, 2026 19:13
@nazar-pc

Copy link
Copy Markdown
Contributor Author

Same 3 commits as before, rebased on v30 branch

@kpreid kpreid left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it were my project, I’d hit the merge (squash) button on this now, but I’ve contributed code to this PR, so I shouldn’t be the one to merge it.

@ErichDonGubler

ErichDonGubler commented Aug 27, 2026

Copy link
Copy Markdown
Member

From discussion in today’s meeting:

* This change in its current form should be applied to the v30 branch, for the benefit of people who are using wgpu v30.

* On trunk, `Global` is now part of `wgpu-core-remote` and is not used by `wgpu`. Therefore, the remaining question is: do we need to address any recursion limit issues in the _new_ architecture?
  I am testing with my application [`all-is-cubes`](https://github.com/kpreid/all-is-cubes/) and it seems that the answer is yes. For example, with a `recursion_limit` slightly reduced to 100 (to get a more useful report than one that shows only non-`wgpu` types in a different case):
warning: overflow evaluating the requirement `wgpu::Device: Sync`
  --> all-is-cubes-gpu/src/lib.rs:29:13
   |
29 | static FOO: wgpu::Device = todo!();
   |             ^^^^^^^^^^^^
   |
   = note: which requires `wgpu::dispatch::DispatchDevice: Sync`
   = note: which requires `Arc<wgpu::backend::wgpu_core::CoreDevice>: Sync`
   = note: which requires `wgpu::backend::wgpu_core::CoreDevice: Send`
   = note: which requires `wgpu::backend::wgpu_core::ContextWgpuCore: Send`
   = note: which requires `Arc<wgpu::wgpu_core::instance::Instance>: Send`
   = note: which requires `wgpu::wgpu_core::instance::Instance: Send`
   = note: which requires `wgpu::wgpu_core::instance::InstanceDevices: Send`
   = note: which requires `wgc::lock::vanilla::Mutex<wgc::weak_vec::WeakVec<wgpu::wgpu_core::device::Device>>: Send`
   = note: which requires `lock_api::mutex::Mutex<wgpu_sync::mutex::RawMutex, wgc::weak_vec::WeakVec<wgpu::wgpu_core::device::Device>>: Send`
   = note: which requires `wgc::weak_vec::WeakVec<wgpu::wgpu_core::device::Device>: Send`
   = note: which requires `Vec<alloc::sync::Weak<wgpu::wgpu_core::device::Device>>: Send`
   = note: which requires `alloc::raw_vec::RawVec<alloc::sync::Weak<wgpu::wgpu_core::device::Device>>: Send`
   = note: which requires `PhantomData<alloc::sync::Weak<wgpu::wgpu_core::device::Device>>: Send`
   = note: which requires `alloc::sync::Weak<wgpu::wgpu_core::device::Device>: Send`
   = note: which requires `wgpu::wgpu_core::device::Device: Send`
   = note: and so on...

This is missing the additional conclusion that I explicitly drove in the meeting that we were going to opt out of guaranteeing Send and Sync for Global, i.e., via a PhantomData<*const ()> member (though N.B. that it's no longer going to be used by wgpu or even wgpu-core directly). I'll raise this as a review issue in #10177.

EDIT: Raised: #10177 (review)

EDIT 2: Filed a PR for Global at #10180.

@ErichDonGubler
ErichDonGubler merged commit 73a7e97 into gfx-rs:v30 Aug 27, 2026
@github-project-automation github-project-automation Bot moved this from Small to Done in Triage Aug 27, 2026
@ErichDonGubler

Copy link
Copy Markdown
Member

CC @cwfitzgerald: ☝🏻 This is a backport now.

@nazar-pc
nazar-pc deleted the fix-recursion-limits-next-solver branch August 27, 2026 11:27
PizzaLvr49 pushed a commit to PizzaLvr49/bevy that referenced this pull request Aug 31, 2026
…ly (bevyengine#25512)

# Objective

- Improve compile times in `bevy_render`
- Help with bevyengine#25511

## Solution

While investigating a wgpu trait overflow issue with the new solver I
noticed that eagerly computing its `Send`/`Sync` reduces the compile
time of `bevy_render` by around 10 seconds (on my machine debug goes
from 20s to 9s and release from 26s to 15s).

I don't like too much having to expose all these types though, and we
might get the same perf benefits if
gfx-rs/wgpu#9953 is merged though (edit: I
tested with that PR changes and that alone reduces compile times by ~6
seconds, however when this PR is added it reduces another ~4 seconds).

I also ended up removing the `Arc`s used in some of the wgpu wrapper
types, as all wgpu types now use `Arc`s under the hood or equivalent.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
mirsella pushed a commit to mirsella/bevy that referenced this pull request Sep 3, 2026
…ly (bevyengine#25512)

- Improve compile times in `bevy_render`
- Help with bevyengine#25511

While investigating a wgpu trait overflow issue with the new solver I
noticed that eagerly computing its `Send`/`Sync` reduces the compile
time of `bevy_render` by around 10 seconds (on my machine debug goes
from 20s to 9s and release from 26s to 15s).

I don't like too much having to expose all these types though, and we
might get the same perf benefits if
gfx-rs/wgpu#9953 is merged though (edit: I
tested with that PR changes and that alone reduces compile times by ~6
seconds, however when this PR is added it reduces another ~4 seconds).

I also ended up removing the `Arc`s used in some of the wgpu wrapper
types, as all wgpu types now use `Arc`s under the hood or equivalent.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: core Issues related to wgpu-core changelog: released entry changed Allows the PR to modify released. This is uncommon.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

7 participants