about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-07-08 17:55:26 +0000
committerbors <bors@rust-lang.org>2022-07-08 17:55:26 +0000
commit052495d0017e2b18b781bcf0469a048e5051f5c0 (patch)
tree16023f6d02c5eea4ced47ce568101df49b193d42
parent45263fc66d253f762b3880764ae48611a25bf887 (diff)
parentd6b93eb79352149bae0fd1efc0bb181947a9e6f1 (diff)
Auto merge of #98614 - oli-obk:take_unsound_opaque_types, r=wesleywiser
don't succeed `evaluate_obligation` query if new opaque types were registered

fixes #98608
fixes #98604

The root cause of all this is that in type flag computation we entirely ignore nongeneric things like struct fields and the signature of function items. So if a flag had to be set for a struct if it is set for a field, that will only happen if the field is generic, as only the generic parameters are checked.

I now believe we cannot use type flags to handle opaque types. They seem like the wrong tool for this.

Instead, this PR replaces the previous logic by adding a new variant of `EvaluatedToOk`: `EvaluatedToOkModuloOpaqueTypes`, which says that there were some opaque types that got hidden types bound, but that binding may not have been legal (because we don't know if the opaque type was in its defining scope or not).
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs2
-rw-r--r--compiler/rustc_infer/src/infer/undo_log.rs4
-rw-r--r--compiler/rustc_infer/src/traits/project.rs2
-rw-r--r--compiler/rustc_middle/src/traits/select.rs18
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
-rw-r--r--compiler/rustc_type_ir/src/lib.rs8
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.rs1
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr112
-rw-r--r--src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs1
-rw-r--r--src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr27
-rw-r--r--src/test/ui/type-alias-impl-trait/inference-cycle.rs1
-rw-r--r--src/test/ui/type-alias-impl-trait/inference-cycle.stderr27
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-98604.rs13
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-98604.stderr18
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-98608.rs9
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-98608.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/reveal_local.rs1
-rw-r--r--src/test/ui/type-alias-impl-trait/reveal_local.stderr33
21 files changed, 116 insertions, 187 deletions
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 6e0f2d68743..28f037cc61a 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -888,6 +888,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             .region_constraints_added_in_snapshot(&snapshot.undo_snapshot)
     }
 
+    pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'a, 'tcx>) -> bool {
+        self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
+    }
+
     pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) {
         self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup);
     }
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 26d689f29ee..f11701bba6f 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -95,7 +95,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
         let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
         let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
-            ty::Opaque(def_id, substs) => {
+            ty::Opaque(def_id, substs) if def_id.is_local() => {
                 let origin = if self.defining_use_anchor.is_some() {
                     // Check that this is `impl Trait` type is
                     // declared by `parent_def_id` -- i.e., one whose
diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs
index 1b696f21cbc..74a26ebc39f 100644
--- a/compiler/rustc_infer/src/infer/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/undo_log.rs
@@ -185,6 +185,10 @@ impl<'tcx> InferCtxtUndoLogs<'tcx> {
         })
     }
 
+    pub(crate) fn opaque_types_in_snapshot(&self, s: &Snapshot<'tcx>) -> bool {
+        self.logs[s.undo_len..].iter().any(|log| matches!(log, UndoLog::OpaqueTypes(..)))
+    }
+
     pub(crate) fn region_constraints(
         &self,
     ) -> impl Iterator<Item = &'_ region_constraints::UndoLog<'tcx>> + Clone {
diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs
index 932e597509f..5d22f9f972e 100644
--- a/compiler/rustc_infer/src/traits/project.rs
+++ b/compiler/rustc_infer/src/traits/project.rs
@@ -203,7 +203,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
             Some(&ProjectionCacheEntry::NormalizedTy { ref ty, complete: _ }) => {
                 info!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty);
                 let mut ty = ty.clone();
-                if result == EvaluationResult::EvaluatedToOk {
+                if result.must_apply_considering_regions() {
                     ty.obligations = vec![];
                 }
                 map.insert(key, ProjectionCacheEntry::NormalizedTy { ty, complete: Some(result) });
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 34703b62820..0ca5a532b75 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -176,6 +176,10 @@ pub enum EvaluationResult {
     EvaluatedToOk,
     /// Evaluation successful, but there were unevaluated region obligations.
     EvaluatedToOkModuloRegions,
+    /// Evaluation successful, but need to rerun because opaque types got
+    /// hidden types assigned without it being known whether the opaque types
+    /// are within their defining scope
+    EvaluatedToOkModuloOpaqueTypes,
     /// Evaluation is known to be ambiguous -- it *might* hold for some
     /// assignment of inference variables, but it might not.
     ///
@@ -252,9 +256,11 @@ impl EvaluationResult {
 
     pub fn may_apply(self) -> bool {
         match self {
-            EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => {
-                true
-            }
+            EvaluatedToOkModuloOpaqueTypes
+            | EvaluatedToOk
+            | EvaluatedToOkModuloRegions
+            | EvaluatedToAmbig
+            | EvaluatedToUnknown => true,
 
             EvaluatedToErr | EvaluatedToRecur => false,
         }
@@ -264,7 +270,11 @@ impl EvaluationResult {
         match self {
             EvaluatedToUnknown | EvaluatedToRecur => true,
 
-            EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false,
+            EvaluatedToOkModuloOpaqueTypes
+            | EvaluatedToOk
+            | EvaluatedToOkModuloRegions
+            | EvaluatedToAmbig
+            | EvaluatedToErr => false,
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 3a795af2121..f15108fb750 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1089,6 +1089,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
 #[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, Lift)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct OpaqueTypeKey<'tcx> {
+    // FIXME(oli-obk): make this a LocalDefId
     pub def_id: DefId,
     pub substs: SubstsRef<'tcx>,
 }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 31d54b5b403..33585de6001 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -777,6 +777,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             Ok(
                 EvaluationResult::EvaluatedToOk
                 | EvaluationResult::EvaluatedToOkModuloRegions
+                | EvaluationResult::EvaluatedToOkModuloOpaqueTypes
                 | EvaluationResult::EvaluatedToAmbig,
             ) => {}
             _ => return false,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 596ee435622..b205ca8fa11 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -394,6 +394,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 Err(_) => return Ok(EvaluatedToErr),
             }
 
+            if self.infcx.opaque_types_added_in_snapshot(snapshot) {
+                return Ok(result.max(EvaluatedToOkModuloOpaqueTypes));
+            }
+
             match self.infcx.region_constraints_added_in_snapshot(snapshot) {
                 None => Ok(result),
                 Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)),
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 6744536338c..fd6376ef6ee 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -204,14 +204,6 @@ bitflags! {
                                           | TypeFlags::HAS_CT_INFER.bits
                                           | TypeFlags::HAS_TY_PLACEHOLDER.bits
                                           | TypeFlags::HAS_CT_PLACEHOLDER.bits
-                                          // The `evaluate_obligation` query does not return further
-                                          // obligations. If it evaluates an obligation with an opaque
-                                          // type, that opaque type may get compared to another type,
-                                          // constraining it. We would lose this information.
-                                          // FIXME: differentiate between crate-local opaque types
-                                          // and opaque types from other crates, as only opaque types
-                                          // from the local crate can possibly be a local name
-                                          | TypeFlags::HAS_TY_OPAQUE.bits
                                           // We consider 'freshened' types and constants
                                           // to depend on a particular fn.
                                           // The freshening process throws away information,
diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs
index d2452abab02..c2fbbf94fd6 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.rs
+++ b/src/test/ui/impl-trait/auto-trait-leak.rs
@@ -11,7 +11,6 @@ fn main() {
 // return type, which can't depend on the obligation.
 fn cycle1() -> impl Clone {
     //~^ ERROR cycle detected
-    //~| ERROR cycle detected
     send(cycle2().clone());
 
     Rc::new(Cell::new(5))
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index 14db864f1c2..634ff14869e 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -30,129 +30,47 @@ note: ...which requires building MIR for `cycle1`...
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires computing type of `cycle2::{opaque#0}`...
-  --> $DIR/auto-trait-leak.rs:20:16
-   |
-LL | fn cycle2() -> impl Clone {
-   |                ^^^^^^^^^^
-note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
-note: cycle used when checking item types in top-level module
-  --> $DIR/auto-trait-leak.rs:1:1
-   |
-LL | / use std::cell::Cell;
-LL | | use std::rc::Rc;
-LL | |
-LL | | fn send<T: Send>(_: T) {}
-...  |
-LL | |     Rc::new(String::from("foo"))
-LL | | }
-   | |_^
-
-error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
-  --> $DIR/auto-trait-leak.rs:12:16
+  --> $DIR/auto-trait-leak.rs:14:5
    |
-LL | fn cycle1() -> impl Clone {
-   |                ^^^^^^^^^^
-   |
-note: ...which requires borrow-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     send(cycle2().clone());
+   |     ^^^^
+   = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
 note: ...which requires computing type of `cycle2::{opaque#0}`...
-  --> $DIR/auto-trait-leak.rs:20:16
+  --> $DIR/auto-trait-leak.rs:19:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:19:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:1
+  --> $DIR/auto-trait-leak.rs:20:5
    |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     send(cycle1().clone());
+   |     ^^^^
+   = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
    = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/auto-trait-leak.rs:1:1
@@ -166,6 +84,6 @@ LL | |     Rc::new(String::from("foo"))
 LL | | }
    | |_^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs
index b456b1445e7..5fb7a9473d3 100644
--- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs
+++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs
@@ -6,7 +6,6 @@
 mod m {
     type Foo = impl std::fmt::Debug;
     //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
-    //~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
 
     pub fn foo() -> Foo {
         22_u32
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
index 4c44875b4a5..1e9a45aac79 100644
--- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
+++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
@@ -5,10 +5,11 @@ LL |     type Foo = impl std::fmt::Debug;
    |                ^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires type-checking `m::bar`...
-  --> $DIR/auto-trait-leakage3.rs:15:5
+  --> $DIR/auto-trait-leakage3.rs:15:9
    |
-LL |     pub fn bar() {
-   |     ^^^^^^^^^^^^
+LL |         is_send(foo());
+   |         ^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`...
    = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in module `m`
   --> $DIR/auto-trait-leakage3.rs:6:1
@@ -16,24 +17,6 @@ note: cycle used when checking item types in module `m`
 LL | mod m {
    | ^^^^^
 
-error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
-  --> $DIR/auto-trait-leakage3.rs:7:16
-   |
-LL |     type Foo = impl std::fmt::Debug;
-   |                ^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires type-checking `m::bar`...
-  --> $DIR/auto-trait-leakage3.rs:15:5
-   |
-LL |     pub fn bar() {
-   |     ^^^^^^^^^^^^
-   = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
-note: cycle used when checking item types in module `m`
-  --> $DIR/auto-trait-leakage3.rs:6:1
-   |
-LL | mod m {
-   | ^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.rs b/src/test/ui/type-alias-impl-trait/inference-cycle.rs
index 608572978a3..79caddf7913 100644
--- a/src/test/ui/type-alias-impl-trait/inference-cycle.rs
+++ b/src/test/ui/type-alias-impl-trait/inference-cycle.rs
@@ -4,7 +4,6 @@
 mod m {
     type Foo = impl std::fmt::Debug;
     //~^ ERROR cycle detected
-    //~| ERROR cycle detected
 
     // Cycle: error today, but it'd be nice if it eventually worked
 
diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
index 3ed86fae8a1..b9d646b927a 100644
--- a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
+++ b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
@@ -5,10 +5,11 @@ LL |     type Foo = impl std::fmt::Debug;
    |                ^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires type-checking `m::bar`...
-  --> $DIR/inference-cycle.rs:15:5
+  --> $DIR/inference-cycle.rs:15:9
    |
-LL |     pub fn bar() {
-   |     ^^^^^^^^^^^^
+LL |         is_send(foo()); // Today: error
+   |         ^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`...
    = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in module `m`
   --> $DIR/inference-cycle.rs:4:1
@@ -16,24 +17,6 @@ note: cycle used when checking item types in module `m`
 LL | mod m {
    | ^^^^^
 
-error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
-  --> $DIR/inference-cycle.rs:5:16
-   |
-LL |     type Foo = impl std::fmt::Debug;
-   |                ^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires type-checking `m::bar`...
-  --> $DIR/inference-cycle.rs:15:5
-   |
-LL |     pub fn bar() {
-   |     ^^^^^^^^^^^^
-   = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
-note: cycle used when checking item types in module `m`
-  --> $DIR/inference-cycle.rs:4:1
-   |
-LL | mod m {
-   | ^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-98604.rs b/src/test/ui/type-alias-impl-trait/issue-98604.rs
new file mode 100644
index 00000000000..a4fd8a82a04
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-98604.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+type AsyncFnPtr = Box<
+    dyn Fn() -> std::pin::Pin<Box<dyn std::future::Future<Output = ()>>>,
+>;
+
+async fn test() {}
+
+#[allow(unused_must_use)]
+fn main() {
+    Box::new(test) as AsyncFnPtr;
+    //~^ ERROR type mismatch
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-98604.stderr b/src/test/ui/type-alias-impl-trait/issue-98604.stderr
new file mode 100644
index 00000000000..f04d1b4d787
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-98604.stderr
@@ -0,0 +1,18 @@
+error[E0271]: type mismatch resolving `<fn() -> impl Future<Output = ()> {test} as FnOnce<()>>::Output == Pin<Box<(dyn Future<Output = ()> + 'static)>>`
+  --> $DIR/issue-98604.rs:11:5
+   |
+LL |     Box::new(test) as AsyncFnPtr;
+   |     ^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type
+   |
+note: while checking the return type of the `async fn`
+  --> $DIR/issue-98604.rs:7:17
+   |
+LL | async fn test() {}
+   |                 ^ checked the `Output` of this `async fn`, found opaque type
+   = note:   expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
+           found opaque type `impl Future<Output = ()>`
+   = note: required for the cast from `fn() -> impl Future<Output = ()> {test}` to the object type `dyn Fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-98608.rs b/src/test/ui/type-alias-impl-trait/issue-98608.rs
new file mode 100644
index 00000000000..d75762a8b62
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-98608.rs
@@ -0,0 +1,9 @@
+fn hi() -> impl Sized { std::ptr::null::<u8>() }
+
+fn main() {
+    let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
+    //~^ ERROR type mismatch resolving `<fn() -> impl Sized {hi} as FnOnce<()>>::Output == Box<u8>`
+    let boxed = b();
+    let null = *boxed;
+    println!("{null:?}");
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-98608.stderr b/src/test/ui/type-alias-impl-trait/issue-98608.stderr
new file mode 100644
index 00000000000..8f3ec7d9d16
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-98608.stderr
@@ -0,0 +1,16 @@
+error[E0271]: type mismatch resolving `<fn() -> impl Sized {hi} as FnOnce<()>>::Output == Box<u8>`
+  --> $DIR/issue-98608.rs:4:39
+   |
+LL | fn hi() -> impl Sized { std::ptr::null::<u8>() }
+   |            ---------- the found opaque type
+...
+LL |     let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
+   |                                       ^^^^^^^^^^^^ expected struct `Box`, found opaque type
+   |
+   = note:   expected struct `Box<u8>`
+           found opaque type `impl Sized`
+   = note: required for the cast from `fn() -> impl Sized {hi}` to the object type `dyn Fn() -> Box<u8>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/type-alias-impl-trait/reveal_local.rs b/src/test/ui/type-alias-impl-trait/reveal_local.rs
index 145186baa1f..7ecb5535301 100644
--- a/src/test/ui/type-alias-impl-trait/reveal_local.rs
+++ b/src/test/ui/type-alias-impl-trait/reveal_local.rs
@@ -4,7 +4,6 @@ use std::fmt::Debug;
 
 type Foo = impl Debug;
 //~^ ERROR cycle detected
-//~| ERROR cycle detected
 
 fn is_send<T: Send>() { }
 
diff --git a/src/test/ui/type-alias-impl-trait/reveal_local.stderr b/src/test/ui/type-alias-impl-trait/reveal_local.stderr
index 5d48dd5b2bf..27fded33329 100644
--- a/src/test/ui/type-alias-impl-trait/reveal_local.stderr
+++ b/src/test/ui/type-alias-impl-trait/reveal_local.stderr
@@ -5,10 +5,11 @@ LL | type Foo = impl Debug;
    |            ^^^^^^^^^^
    |
 note: ...which requires type-checking `not_good`...
-  --> $DIR/reveal_local.rs:11:1
+  --> $DIR/reveal_local.rs:13:5
    |
-LL | fn not_good() {
-   | ^^^^^^^^^^^^^
+LL |     is_send::<Foo>();
+   |     ^^^^^^^^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `Foo: core::marker::Send`...
    = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/reveal_local.rs:1:1
@@ -22,30 +23,6 @@ LL | |
 LL | | fn main() {}
    | |____________^
 
-error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
-  --> $DIR/reveal_local.rs:5:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-   |
-note: ...which requires type-checking `not_gooder`...
-  --> $DIR/reveal_local.rs:17:1
-   |
-LL | fn not_gooder() {
-   | ^^^^^^^^^^^^^^^
-   = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
-note: cycle used when checking item types in top-level module
-  --> $DIR/reveal_local.rs:1:1
-   |
-LL | / #![feature(type_alias_impl_trait)]
-LL | |
-LL | | use std::fmt::Debug;
-LL | |
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0391`.