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
This commit is contained in:
commit
909098728c
3 changed files with 61 additions and 7 deletions
|
|
@ -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(())
|
||||
|
|
|
|||
15
tests/ui/coroutine/delayed-obligations-emit.next.stderr
Normal file
15
tests/ui/coroutine/delayed-obligations-emit.next.stderr
Normal file
|
|
@ -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`.
|
||||
33
tests/ui/coroutine/delayed-obligations-emit.rs
Normal file
33
tests/ui/coroutine/delayed-obligations-emit.rs
Normal file
|
|
@ -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() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue