Skip to content

Fix coroutine witness trait solving with NLL-derived facts - #160940

Draft
dingxiangfei2009 wants to merge 1 commit into
rust-lang:mainfrom
dingxiangfei2009:corowit-ground-truth
Draft

Fix coroutine witness trait solving with NLL-derived facts#160940
dingxiangfei2009 wants to merge 1 commit into
rust-lang:mainfrom
dingxiangfei2009:corowit-ground-truth

Conversation

@dingxiangfei2009

@dingxiangfei2009 dingxiangfei2009 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

When checking auto-trait bounds like Send on coroutine witness types, the solver creates independent placeholder regions for each bound variable in the witness binder. Even when NLL proves these regions are equal or have outlives relationships, the solver cannot use this information, causing Send/Sync bound checks to fail. But we can do better.

This commit adds a mechanism to propagate NLL region constraints into the trait solver via an enriched ParamEnv. The rough idea is as follows.

  1. Extract SCC data from NLL during mir_borrowck, maximise the outlive relations in SCC and compute the quotient by relating lifetimes in the saved locals. This becomes the NLL facts that can "hydrate" the ParamEnv per coroutine in the re-evaluation step.
  2. Stall coroutine auto-trait goals using BorrowckPendingScc typing mode
  3. Re-evaluate stalled goals inside mir_borrowck with an enriched ParamEnv containing CoroutineWitnessRegionConstraints, the NLL facts that we mentioned.
  4. The solver merges these constraints into forall placeholder assumptions, enabling proof of region obligations

Gated behind -Zdxf flag, which is totally not serious and mostly requires -Znext-solver.

Fixes #87425, #126551, #71723, #126550, #149235.
Partially addresses #79648, #110338.

This is a throw-away patch, it exists only for discussion. Do not expect timely updates to keep it working or mergeable. Sorry!

  • I did not use an LLM to create a change in this PR.
  • I used an LLM to create a change in this PR, and I have explained below how it was used.

I used LLMs to

  • parse RUSTC_LOGs to reconstruct proof trees
  • minimize a few complicated repros that we can effectively check our work against

@rustbot rustbot added A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Aug 11, 2026
When checking auto-trait bounds like Send on coroutine witness types,
the solver creates independent placeholder regions for each bound variable
in the witness binder. Even when NLL proves these regions are equal or
have outlives relationships, the solver cannot use this information,
causing false Send/Sync failures.

This commit adds a mechanism to propagate NLL region constraints into
the trait solver via an enriched ParamEnv:

1. Extract SCC data from NLL during mir_borrowck
2. Stall coroutine auto-trait goals using BorrowckPendingScc typing mode
3. Re-evaluate stalled goals inside mir_borrowck with an enriched
   ParamEnv containing CoroutineWitnessRegionConstraints
4. The solver merges these constraints into forall placeholder
   assumptions, enabling proof of region obligations

Gated behind -Zdxf flag (requires -Znext-solver).

Fixes rust-lang#87425, rust-lang#126551, rust-lang#71723, rust-lang#126550, rust-lang#149235.
Partially addresses rust-lang#79648, rust-lang#110338.
@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job aarch64-gnu-llvm-21-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
[RUSTC-TIMING] shlex test:false 0.262
   Compiling rustc-main v0.0.0 (/checkout/compiler/rustc)
[RUSTC-TIMING] build_script_build test:false 0.128
[RUSTC-TIMING] jiff test:false 7.416
error[E0080]: evaluation panicked: the query `type_op_ascribe_user_type` has a key type `CanonicalTypeOpAscribeUserTypeGoal < 'tcx >` that is too large
    --> /rustc/08d5b675a9b2abdca5e2fe4eabe0e07bbda15d49/library/core/src/panic.rs:51:0
     |
     = note: in this expansion of `$crate::panic::panic_2021!` (#4)
    ::: /rustc/08d5b675a9b2abdca5e2fe4eabe0e07bbda15d49/library/core/src/panic.rs:57:8
     |
     = note: evaluation of `queries::type_op_ascribe_user_type::_` failed here
     |
    ::: compiler/rustc_middle/src/queries.rs:134:1
     |
 134 | /   rustc_queries! {
 135 | |       /// Caches the expansion of a derive proc macro, e.g. `#[derive(Serialize)]`.
---
    ::: compiler/rustc_middle/src/query/plumbing.rs:282:1
     |
 282 | /   macro_rules! define_callbacks {
...    |
 373 | | /                         panic!("{}", concat!(
 374 | | |                             "the query `",
 375 | | |                             stringify!($name),
 376 | | |                             "` has a key type `",
 377 | | |                             stringify!($($K)*),
 378 | | |                             "` that is too large"
 379 | | |                         ));
     | | |                          -
     | | |                          |
     | | |__________________________in this macro invocation (#3)
     | |                            in this macro invocation (#4)

@rust-bors

rust-bors Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

☔ The latest upstream changes (presumably #158436) made this pull request unmergeable. Please resolve the merge conflicts by rebasing.

@adwinwhite

Copy link
Copy Markdown
Contributor

It seems that you're trying to solve the same problem as assumptions on binders addresses?

@dingxiangfei2009

dingxiangfei2009 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

@adwinwhite Hmm problems in the same category yeah, but I found that there are tests in the patch that shows AoB cannot prove certain auto trait bounds, see tests/ui/async-await/dxf-coroutine-send-outlives.rs.

AoB also has a small unsoundness issue which incorrectly dismissed outstanding higher ranked outlive constraints, see tests/ui/async-await/dxf-coroutine-send-nested.rs.

I mostly would see this as addition to AoB. There are bounds that AoB cannot prove alone and there are bounds which NLL data must work with AoB together to prove because WF facts are essential.

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

Labels

A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

implementation of Debug is not general enough when making async block into &dyn Future + Send

4 participants