Skip to content

Commit e277077

Browse files
authored
Unrolled build for rust-lang#118161
Rollup merge of rust-lang#118161 - compiler-errors:coroutine-obligation-opaques, r=lcnr Allow defining opaques in `check_coroutine_obligations` In the new trait solver, when an obligation stalls on an unresolved coroutine witness, we will stash away the *root* obligation, even if the stalled obligation is only a distant descendent of the root obligation, since the new solver is purely recursive. This means that we may need to reprocess alias-relate obligations (and others) which may define opaque types in the new solver. Currently, we use the coroutine's def id as the defining anchor in `check_coroutine_obligations`, which will allow defining no opaque types, resulting in errors like: ``` error[E0271]: type mismatch resolving `{coroutine@<source>:6:5: 6:17} <: impl Clone` --> <source>:6:5 | 6 | / move |_: ()| { 7 | | let () = yield (); 8 | | } | |_____^ types differ ``` So this PR fixes the defining anchor and does the same trick as `check_opaque_well_formed`, where we manually compare opaques that were defined against their hidden types to make sure they weren't defined differently when processing these stalled coroutine obligations. r? `@lcnr` cc `@cjgillot`
2 parents 6d2b84b + 4f958a4 commit e277077

File tree

3 files changed

+36
-5
lines changed

3 files changed

+36
-5
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -1468,7 +1468,10 @@ fn opaque_type_cycle_error(
14681468
err.emit()
14691469
}
14701470

1471-
pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
1471+
pub(super) fn check_coroutine_obligations(
1472+
tcx: TyCtxt<'_>,
1473+
def_id: LocalDefId,
1474+
) -> Result<(), ErrorGuaranteed> {
14721475
debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Coroutine));
14731476

14741477
let typeck = tcx.typeck(def_id);
@@ -1482,8 +1485,9 @@ pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
14821485
// typeck writeback gives us predicates with their regions erased.
14831486
// As borrowck already has checked lifetimes, we do not need to do it again.
14841487
.ignoring_regions()
1485-
// Bind opaque types to `def_id` as they should have been checked by borrowck.
1486-
.with_opaque_type_inference(DefiningAnchor::Bind(def_id))
1488+
// Bind opaque types to type checking root, as they should have been checked by borrowck,
1489+
// but may show up in some cases, like when (root) obligations are stalled in the new solver.
1490+
.with_opaque_type_inference(DefiningAnchor::Bind(typeck.hir_owner.def_id))
14871491
.build();
14881492

14891493
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);
@@ -1513,6 +1517,16 @@ pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
15131517
let errors = fulfillment_cx.select_all_or_error(&infcx);
15141518
debug!(?errors);
15151519
if !errors.is_empty() {
1516-
infcx.err_ctxt().report_fulfillment_errors(errors);
1520+
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
15171521
}
1522+
1523+
// Check that any hidden types found when checking these stalled coroutine obligations
1524+
// are valid.
1525+
for (key, ty) in infcx.take_opaque_types() {
1526+
let hidden_type = infcx.resolve_vars_if_possible(ty.hidden_type);
1527+
let key = infcx.resolve_vars_if_possible(key);
1528+
sanity_check_found_hidden_type(tcx, key, hidden_type)?;
1529+
}
1530+
1531+
Ok(())
15181532
}

compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ rustc_queries! {
567567
separate_provide_extern
568568
}
569569

570-
query check_coroutine_obligations(key: LocalDefId) {
570+
query check_coroutine_obligations(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
571571
desc { |tcx| "verify auto trait bounds for coroutine interior type `{}`", tcx.def_path_str(key) }
572572
}
573573

tests/ui/coroutine/clone-rpit.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// revisions: current next
2+
//[next] compile-flags: -Ztrait-solver=next
3+
// check-pass
4+
5+
#![feature(coroutines, coroutine_trait, coroutine_clone)]
6+
7+
// This stalls the goal `{coroutine} <: impl Clone`, since that has a nested goal
8+
// of `{coroutine}: Clone`. That is only known if we can compute the generator
9+
// witness types, which we don't know until after borrowck. When we later check
10+
// the goal for correctness, we want to be able to bind the `impl Clone` opaque.
11+
pub fn foo<'a, 'b>() -> impl Clone {
12+
move |_: ()| {
13+
let () = yield ();
14+
}
15+
}
16+
17+
fn main() {}

0 commit comments

Comments
 (0)