Skip to content

Commit 9090987

Browse files
authored
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 rust-lang/trait-system-refactor-initiative#199. It is unfortunately still a regression. r? compiler-errors
2 parents 616650b + 667504b commit 9090987

File tree

3 files changed

+61
-7
lines changed

3 files changed

+61
-7
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -1754,17 +1754,19 @@ pub(super) fn check_coroutine_obligations(
17541754
debug!(?typeck_results.coroutine_stalled_predicates);
17551755

17561756
let mode = if tcx.next_trait_solver_globally() {
1757-
TypingMode::post_borrowck_analysis(tcx, def_id)
1757+
// This query is conceptually between HIR typeck and
1758+
// MIR borrowck. We use the opaque types defined by HIR
1759+
// and ignore region constraints.
1760+
TypingMode::borrowck(tcx, def_id)
17581761
} else {
17591762
TypingMode::analysis_in_body(tcx, def_id)
17601763
};
17611764

1762-
let infcx = tcx
1763-
.infer_ctxt()
1764-
// typeck writeback gives us predicates with their regions erased.
1765-
// As borrowck already has checked lifetimes, we do not need to do it again.
1766-
.ignoring_regions()
1767-
.build(mode);
1765+
// Typeck writeback gives us predicates with their regions erased.
1766+
// We only need to check the goals while ignoring lifetimes to give good
1767+
// error message and to avoid breaking the assumption of `mir_borrowck`
1768+
// that all obligations already hold modulo regions.
1769+
let infcx = tcx.infer_ctxt().ignoring_regions().build(mode);
17681770

17691771
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
17701772
for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
@@ -1785,6 +1787,10 @@ pub(super) fn check_coroutine_obligations(
17851787
let key = infcx.resolve_vars_if_possible(key);
17861788
sanity_check_found_hidden_type(tcx, key, hidden_type)?;
17871789
}
1790+
} else {
1791+
// We're not checking region constraints here, so we can simply drop the
1792+
// added opaque type uses in `TypingMode::Borrowck`.
1793+
let _ = infcx.take_opaque_types();
17881794
}
17891795

17901796
Ok(())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0275]: overflow evaluating the requirement `{async block@$DIR/delayed-obligations-emit.rs:17:11: 17:16}: Send`
2+
--> $DIR/delayed-obligations-emit.rs:17:5
3+
|
4+
LL | spawn(async { build_dependencies().await });
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: required by a bound in `spawn`
8+
--> $DIR/delayed-obligations-emit.rs:31:13
9+
|
10+
LL | fn spawn<F: Send>(_: F) {}
11+
| ^^^^ required by this bound in `spawn`
12+
13+
error: aborting due to 1 previous error
14+
15+
For more information about this error, try `rustc --explain E0275`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
//@ edition: 2024
5+
//@[current] check-pass
6+
7+
// This previously caused an ICE with the new solver.
8+
// The delayed coroutine obligations were checked with the
9+
// opaque types inferred by borrowck.
10+
//
11+
// One of these delayed obligations failed with overflow in
12+
// borrowck, causing us to taint `type_of` for the opaque. This
13+
// then caused us to also not emit an error when checking the
14+
// coroutine obligations.
15+
16+
fn build_multiple<'a>() -> impl Sized {
17+
spawn(async { build_dependencies().await });
18+
//[next]~^ ERROR overflow evaluating the requirement
19+
}
20+
21+
// Adding an explicit `Send` bound fixes it.
22+
// Proving `build_dependencies(): Send` in `build_multiple` adds
23+
// addiitional defining uses/placeholders.
24+
fn build_dependencies() -> impl Future<Output = ()> /* + Send */ {
25+
async {
26+
Box::pin(build_dependencies()).await;
27+
async { build_multiple() }.await;
28+
}
29+
}
30+
31+
fn spawn<F: Send>(_: F) {}
32+
33+
fn main() {}

0 commit comments

Comments
 (0)