about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-11-22 09:28:52 -0800
committerGitHub <noreply@github.com>2023-11-22 09:28:52 -0800
commit4ec548afbe27589f6542f11c81b93f2931d1c811 (patch)
tree509623e62b89d684a363ad19391d6ae5c8962138 /compiler
parent040151a4be145871ef15e333d94f84d9039a5e0c (diff)
parent4f958a4802c1c29b804db34d53297504da555d02 (diff)
Rollup merge of #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`
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs22
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
2 files changed, 19 insertions, 5 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index e301f0b22ef..00f636862be 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1468,7 +1468,10 @@ fn opaque_type_cycle_error(
     err.emit()
 }
 
-pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+pub(super) fn check_coroutine_obligations(
+    tcx: TyCtxt<'_>,
+    def_id: LocalDefId,
+) -> Result<(), ErrorGuaranteed> {
     debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Coroutine));
 
     let typeck = tcx.typeck(def_id);
@@ -1482,8 +1485,9 @@ pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         // 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()
-        // Bind opaque types to `def_id` as they should have been checked by borrowck.
-        .with_opaque_type_inference(DefiningAnchor::Bind(def_id))
+        // Bind opaque types to type checking root, as they should have been checked by borrowck,
+        // but may show up in some cases, like when (root) obligations are stalled in the new solver.
+        .with_opaque_type_inference(DefiningAnchor::Bind(typeck.hir_owner.def_id))
         .build();
 
     let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);
@@ -1513,6 +1517,16 @@ pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let errors = fulfillment_cx.select_all_or_error(&infcx);
     debug!(?errors);
     if !errors.is_empty() {
-        infcx.err_ctxt().report_fulfillment_errors(errors);
+        return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
     }
+
+    // Check that any hidden types found when checking these stalled coroutine obligations
+    // are valid.
+    for (key, ty) in infcx.take_opaque_types() {
+        let hidden_type = infcx.resolve_vars_if_possible(ty.hidden_type);
+        let key = infcx.resolve_vars_if_possible(key);
+        sanity_check_found_hidden_type(tcx, key, hidden_type)?;
+    }
+
+    Ok(())
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index cbba990867e..c982e2a9325 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -567,7 +567,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query check_coroutine_obligations(key: LocalDefId) {
+    query check_coroutine_obligations(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
         desc { |tcx| "verify auto trait bounds for coroutine interior type `{}`", tcx.def_path_str(key) }
     }