diff options
| author | Matthias Krüger <476013+matthiaskrgr@users.noreply.github.com> | 2025-05-17 15:45:22 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-17 15:45:22 +0200 |
| commit | 909098728c37729a166a3d38d90532d655cfd511 (patch) | |
| tree | f2355de8e4b8977cbc67663f860bfbdbe1c1364c | |
| parent | 616650b6ca98e82fd2e8c32a6f2330dcef118421 (diff) | |
| parent | 667504b176c9e1ab380cef6eb9eaeba4813337c3 (diff) | |
| download | rust-909098728c37729a166a3d38d90532d655cfd511.tar.gz rust-909098728c37729a166a3d38d90532d655cfd511.zip | |
Rollup merge of #141125 - lcnr:coroutine_obligations_use_borrowck, r=compiler-errors
check coroutines with `TypingMode::Borrowck` to avoid cyclic reasoning MIR borrowck taints its output if an obligation fails. This could then cause `check_coroutine_obligations` to silence its error, causing us to not emit and actual error and ICE. Fixes the ICE in https://github.com/rust-lang/trait-system-refactor-initiative/issues/199. It is unfortunately still a regression. r? compiler-errors
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/check.rs | 20 | ||||
| -rw-r--r-- | tests/ui/coroutine/delayed-obligations-emit.next.stderr | 15 | ||||
| -rw-r--r-- | tests/ui/coroutine/delayed-obligations-emit.rs | 33 |
3 files changed, 61 insertions, 7 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index f92b2aea160..da94331aa26 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1754,17 +1754,19 @@ pub(super) fn check_coroutine_obligations( debug!(?typeck_results.coroutine_stalled_predicates); let mode = if tcx.next_trait_solver_globally() { - TypingMode::post_borrowck_analysis(tcx, def_id) + // This query is conceptually between HIR typeck and + // MIR borrowck. We use the opaque types defined by HIR + // and ignore region constraints. + TypingMode::borrowck(tcx, def_id) } else { TypingMode::analysis_in_body(tcx, def_id) }; - let infcx = tcx - .infer_ctxt() - // typeck writeback gives us predicates with their regions erased. - // As borrowck already has checked lifetimes, we do not need to do it again. - .ignoring_regions() - .build(mode); + // Typeck writeback gives us predicates with their regions erased. + // We only need to check the goals while ignoring lifetimes to give good + // error message and to avoid breaking the assumption of `mir_borrowck` + // that all obligations already hold modulo regions. + let infcx = tcx.infer_ctxt().ignoring_regions().build(mode); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); for (predicate, cause) in &typeck_results.coroutine_stalled_predicates { @@ -1785,6 +1787,10 @@ pub(super) fn check_coroutine_obligations( let key = infcx.resolve_vars_if_possible(key); sanity_check_found_hidden_type(tcx, key, hidden_type)?; } + } else { + // We're not checking region constraints here, so we can simply drop the + // added opaque type uses in `TypingMode::Borrowck`. + let _ = infcx.take_opaque_types(); } Ok(()) diff --git a/tests/ui/coroutine/delayed-obligations-emit.next.stderr b/tests/ui/coroutine/delayed-obligations-emit.next.stderr new file mode 100644 index 00000000000..3a3663398c9 --- /dev/null +++ b/tests/ui/coroutine/delayed-obligations-emit.next.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `{async block@$DIR/delayed-obligations-emit.rs:17:11: 17:16}: Send` + --> $DIR/delayed-obligations-emit.rs:17:5 + | +LL | spawn(async { build_dependencies().await }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `spawn` + --> $DIR/delayed-obligations-emit.rs:31:13 + | +LL | fn spawn<F: Send>(_: F) {} + | ^^^^ required by this bound in `spawn` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/coroutine/delayed-obligations-emit.rs b/tests/ui/coroutine/delayed-obligations-emit.rs new file mode 100644 index 00000000000..6334f29fcb2 --- /dev/null +++ b/tests/ui/coroutine/delayed-obligations-emit.rs @@ -0,0 +1,33 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ edition: 2024 +//@[current] check-pass + +// This previously caused an ICE with the new solver. +// The delayed coroutine obligations were checked with the +// opaque types inferred by borrowck. +// +// One of these delayed obligations failed with overflow in +// borrowck, causing us to taint `type_of` for the opaque. This +// then caused us to also not emit an error when checking the +// coroutine obligations. + +fn build_multiple<'a>() -> impl Sized { + spawn(async { build_dependencies().await }); + //[next]~^ ERROR overflow evaluating the requirement +} + +// Adding an explicit `Send` bound fixes it. +// Proving `build_dependencies(): Send` in `build_multiple` adds +// addiitional defining uses/placeholders. +fn build_dependencies() -> impl Future<Output = ()> /* + Send */ { + async { + Box::pin(build_dependencies()).await; + async { build_multiple() }.await; + } +} + +fn spawn<F: Send>(_: F) {} + +fn main() {} |
