rust-lang / rust-lang/rust

Next solver: recursion limit triggered on downstream packages

Open
#160,036 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

T-compiler T-types WG-trait-system-refactor
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

wgpu is a well known crate that currently requires increasing recursion limit with -Znext-solver=globally, in fact the latest release of it already intentionally includes #![recursion_limit = "256"].

However, turns out wgpu is infectious and causes any crate that directly or indirectly uses its Device type to trigger the same recursion limit warning (or error in older nightly).

I have reduced one of the crates in my workspace that uses wgpu here: https://github.com/nazar-pc/abundance/tree/reduced-wgpu-recursive-solver-recursion-limits

crates/farmer/ab-proof-of-space-gpu is a somewhat reduced library that uses wgpu:

use ab_core_primitives::pieces::Record;
use ab_core_primitives::sectors::SectorId;
use ab_farmer_components::plotting::RecordsEncoder;
use ab_farmer_components::sector::SectorContentsMap;
use rayon::{ThreadPool, ThreadPoolBuilder};
use std::sync::atomic::AtomicBool;

#[derive(Clone, Debug)]
pub struct Device;

impl Device {
    pub fn instantiate(&self) -> GpuRecordsEncoder {
        let thread_pool = ThreadPoolBuilder::new().build().unwrap();

        GpuRecordsEncoder {
            instances: Vec::new(),
            thread_pool,
        }
    }
}

#[derive(Debug)]
pub struct GpuRecordsEncoder {
    instances: Vec<GpuRecordsEncoderInstance>,
    thread_pool: ThreadPool,
}

impl RecordsEncoder for GpuRecordsEncoder {
    fn encode_records(
        &mut self,
        _sector_id: &SectorId,
        _records: &mut [Record],
        _abort_early: &AtomicBool,
    ) -> anyhow::Result<SectorContentsMap> {
        self.thread_pool.install(|| {
            let _ = &self.instances[0];
        });

        Ok(SectorContentsMap::new(0))
    }
}

#[derive(Debug)]
struct GpuRecordsEncoderInstance {
    _device: wgpu::Device,
}

Within this crate recursion is triggered here:

warning: overflow evaluating the requirement `{closure@crates/farmer/ab-proof-of-space-gpu/src/lib.rs:39:34: 39:36}: std::marker::Send`
  --> crates/farmer/ab-proof-of-space-gpu/src/lib.rs:39:26
   |
39 |         self.thread_pool.install(|| {
   |                          ^^^^^^^
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`ab_proof_of_space_gpu`)
   = help: or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved
   = note: this lint is attached to the whole crate and can't be disabled on a per-function basis
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>
   = note: `#[warn(recursion_depth_exceeding_limit)]` (part of `#[warn(future_incompatible)]`) on by default

warning: overflow evaluating the requirement `{closure@crates/farmer/ab-proof-of-space-gpu/src/lib.rs:39:34: 39:36}: std::marker::Send`
  --> crates/farmer/ab-proof-of-space-gpu/src/lib.rs:39:9
   |
39 | /         self.thread_pool.install(|| {
40 | |             let _ = &self.instances[0];
41 | |         });
   | |__________^
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`ab_proof_of_space_gpu`)
   = help: or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved
   = note: this lint is attached to the whole crate and can't be disabled on a per-function basis
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>

However, since wgpu::Device is a field of GpuRecordsEncoderInstance, which is stored inside public GpuRecordsEncoder, simply using GpuRecordsEncoder is enough to trigger recursion limits in further downstream crates, in this case crates/farmer/ab-farmer (both library and binary, triggered in both):

warning: overflow evaluating the requirement `tracing::instrument::Instrumented<{async block@crates/farmer/ab-farmer/src/plotter/gpu.rs:257:13: 257:23}>: std::marker::Send`
   --> crates/farmer/ab-farmer/src/plotter/gpu.rs:425:34
    |
425 |             AsyncJoinOnDrop::new(tokio::spawn(plotting_fut.in_current_span()), true);
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`ab_farmer`)
    = help: or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved
    = note: this lint is attached to the whole crate and can't be disabled on a per-function basis
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>
    = note: `#[warn(recursion_depth_exceeding_limit)]` (part of `#[warn(future_incompatible)]`) on by default

warning: overflow evaluating the requirement `std::pin::Pin<std::boxed::Box<{async block@crates/farmer/ab-farmer/src/plotter/gpu.rs:84:5: 84:10}>>: std::ops::CoerceUnsized<std::pin::Pin<std::boxed::Box<dyn futures::Future<Output = std::result::Result<bool, String>> + std::marker::Send>>>`
  --> crates/farmer/ab-farmer/src/plotter/gpu.rs:84:5
   |
84 |     async fn has_free_capacity(&self) -> Result<bool, String> {
   |     ^^^^^
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`ab_farmer`)
   = help: or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved
   = note: this lint is attached to the whole crate and can't be disabled on a per-function basis
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>

warning: overflow evaluating the requirement `std::pin::Pin<std::boxed::Box<{async block@crates/farmer/ab-farmer/src/plotter/gpu.rs:88:5: 88:10}>>: std::ops::CoerceUnsized<std::pin::Pin<std::boxed::Box<dyn futures::Future<Output = ()> + std::marker::Send>>>`
  --> crates/farmer/ab-farmer/src/plotter/gpu.rs:88:5
   |
88 |     async fn plot_sector(
   |     ^^^^^
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`ab_farmer`)
   = help: or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved
   = note: this lint is attached to the whole crate and can't be disabled on a per-function basis
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>

warning: overflow evaluating the requirement `std::pin::Pin<std::boxed::Box<{async block@crates/farmer/ab-farmer/src/plotter/gpu.rs:117:5: 117:10}>>: std::ops::CoerceUnsized<std::pin::Pin<std::boxed::Box<dyn futures::Future<Output = bool> + std::marker::Send>>>`
   --> crates/farmer/ab-farmer/src/plotter/gpu.rs:117:5
    |
117 |     async fn try_plot_sector(
    |     ^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`ab_farmer`)
    = help: or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved
    = note: this lint is attached to the whole crate and can't be disabled on a per-function basis
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>

warning: overflow evaluating the requirement `(parking_lot::lock_api::Mutex<parking_lot::RawMutex, std::vec::Vec<ab_proof_of_space_gpu::GpuRecordsEncoder>>, event_listener::Event): std::marker::Send`
  |
  = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`ab_farmer`)
  = help: or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved
  = note: this lint is attached to the whole crate and can't be disabled on a per-function basis
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>

warning: overflow evaluating the requirement `(parking_lot::lock_api::Mutex<parking_lot::RawMutex, std::vec::Vec<ab_proof_of_space_gpu::GpuRecordsEncoder>>, event_listener::Event): std::marker::Sync`
  |
  = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`ab_farmer`)
  = help: or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved
  = note: this lint is attached to the whole crate and can't be disabled on a per-function basis
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>

It is quite unexpected that downstream crates need to recursively also raise recursion limits in addition to the upstream dependency itself.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the reduced workspace linked in the issue, especially crates/farmer/ab-proof-of-space-gpu and crates/farmer/ab-farmer, and reproduce the recursion-limit diagnostics on nightly. Read issue #159228 and trace the reported Send and Sync requirement evaluation. Done means the downstream crates no longer need independently increased recursion limits, with a regression test covering the dependency shape.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.