Skip to content

fix: Respect crate recursion limits when inferring deeply nested types - #23397

Closed
YinMo19 wants to merge 2 commits into
rust-lang:masterfrom
YinMo19:fix/trait-solver-recursion-limit
Closed

YinMo19 wants to merge 2 commits into
rust-lang:masterfrom
YinMo19:fix/trait-solver-recursion-limit

Conversation

@YinMo19

@YinMo19 YinMo19 commented Sep 19, 2026 •

Copy link
Copy Markdown

Problem

Fixes #23396.

The issue's diesel-async query compiles with rustc, but rust-analyzer reports E0282 on the query and E0308 (expected String, found str) at its return value. The trait solver's Interner::recursion_limit currently returns a fixed depth of 50, ignoring the crate's configured limit. A dependency-free regression with a finite, 64-layer trait obligation also fails to infer the expected u32 at that fixed depth.

Change

Use the active calling crate's existing DefMap recursion limit: 128 by default, or its explicit #![recursion_limit = "..."] value. This removes the hard-coded solver limit rather than special-casing Diesel or suppressing either diagnostic.

The numeric limit is exposed as a separately tracked field of DefMapPair, so consumers do not depend on unrelated changes to the full definition map. DbInterner reads it once during construction and stores a u32; solver calls then read the cached scalar. Contexts without a crate retain the default value.

The tests cover the default depth, an explicitly raised limit, calling-crate rather than dependency-crate selection, and low/high/low attribute edits in the same incremental database. Three existing crash-regression snapshots that pinned incidental recursive-reference expansion counts now assert inferred types instead. An obsolete query-log test referring to the removed trait_solve_shim query is replaced with the incremental inferred-type regression.

Corresponding rustc implementation

References are pinned to the revision in this checkout's rust-version:

This patch follows that crate-attribute/default policy through rust-analyzer's existing DefMap implementation. The limit belongs to the crate being analyzed, not the dependency defining a referenced trait. This change does not add support for rustc's unstable min_recursion_limit option.

Verification

The following results were obtained by the AI-assisted local workflow on macOS arm64 using nightly Rust 1.100.0:

  • The default-depth and explicit-depth regressions failed before the fix ({unknown} instead of u32) and pass with it.
  • The unchanged 22-line reproducer from False String/str mismatch in diesel-async query with four joins #23396 produces two native errors with the baseline analyzer and none with the patched analyzer.
  • hir-def, hir-ty, and ide-diagnostics: 2,279 tests passed, 5 ignored.
  • Release binary build and rustfmt check passed.
  • Clippy passed for the three affected crates with the CI-selected denied Clippy lints. Warnings remain in unchanged workspace manifests and hir-ty/src/lower.rs; this is not a warning-free/full-CI claim.

Commands:

cargo +nightly test --release --locked -p hir-def -p hir-ty -p ide-diagnostics --lib
cargo +nightly build --release --locked -p rust-analyzer
cargo +nightly fmt --all --check
cargo +nightly clippy --release --locked -p hir-def -p hir-ty -p ide-diagnostics --all-targets -- -D clippy::disallowed_macros -D clippy::dbg_macro -D clippy::todo -D clippy::print_stdout -D clippy::print_stderr

The full upstream cross-platform CI matrix has not been run locally.

Tradeoff

A higher default limit, or an explicitly high crate limit, can increase the work required for pathological recursive types. Three paired local CLI measurements on the issue reproducer had median elapsed times of 4.176 seconds before and 4.223 seconds after the change. This small sample is not a general guarantee about IDE responsiveness.

Declaration

The code changes were generated using OpenAI’s GPT-Astra. I reviewed the implementation and verified the fix.

Use the calling crate's configured recursion limit instead of the fixed depth of 50. Track the scalar separately and cache it in DbInterner to avoid broad incremental invalidation and repeated solver-loop queries.

Cover default and explicit limits, calling-crate selection, and incremental attribute edits. Replace depth-sensitive debug snapshots with type assertions.

Refs rust-lang#23396.

AI assistance was used for investigation, implementation, tests, and this commit message.
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 19, 2026
The CI debug test builds overflow libtest's default 2 MiB stack when exercising the crate recursion limit. Set the default RUST_MIN_STACK to 16 MiB, matching stdx::thread::DEFAULT_STACK_SIZE used by analyzer workers. Keep the deep inference fixtures and assertions unchanged.

Validated the full workspace with Rust 1.98.1, CI RUSTFLAGS, and nextest: 8188 passed, 10 skipped. AI assistance was used to investigate and prepare this change.
@ChayimFriedman2

Copy link
Copy Markdown
Contributor

First, @YUZHEthefool already claimed this in #23193, although perhaps you didn't know because you didn't see that issue.

Second, I've said multiple times that we cannot just change this and need to investigate the consequences. The change itself is trivial, that investigation is the real work.

Third and most severe of all, you didn't follow our AI policy. You said you've reviewed the implementation, but I doubt that and if even you did, you probably don't have the knowledge of the codebase to do that because the code quality is in no way good. Worse, your PR description is very likely AI-generated as well which is a clear violation of the policy.

I'm closing this now. If you'll repeat this behavior we'll reach to moderation.

@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 22, 2026
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.

False String/str mismatch in diesel-async query with four joins

3 participants