about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-11-24 15:05:11 +0000
committerMichael Goulet <michael@errs.io>2024-01-08 20:30:24 +0000
commit841184bcae3000335c26bfae24f8be44beb81759 (patch)
tree109f314cfe05bff6d219533dfd9cdc9b541bf364
parentfa2ff51ace4f1c415cbe24687828058bcf74d200 (diff)
downloadrust-841184bcae3000335c26bfae24f8be44beb81759.tar.gz
rust-841184bcae3000335c26bfae24f8be44beb81759.zip
Make cycle error more resilient to where it starts
Also don't recomment recursive_async crate anymore

Co-authored-by: lcnr <rust@lcnr.de>
-rw-r--r--compiler/rustc_middle/src/values.rs131
-rw-r--r--tests/ui/async-await/in-trait/async-recursive-generic.stderr1
-rw-r--r--tests/ui/async-await/in-trait/async-recursive.stderr1
-rw-r--r--tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs4
-rw-r--r--tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr15
-rw-r--r--tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr1
-rw-r--r--tests/ui/async-await/recursive-async-impl-trait-type.stderr1
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-boxed.rs (renamed from tests/ui/impl-trait/recursive-coroutine.rs)0
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr11
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr11
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.rs13
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs10
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr50
-rw-r--r--tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr1
14 files changed, 134 insertions, 116 deletions
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 3e3aa821b4e..77e4ed06eaa 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -11,6 +11,7 @@ use rustc_query_system::Value;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{ErrorGuaranteed, Span};
 
+use std::collections::VecDeque;
 use std::fmt::Write;
 
 impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> {
@@ -135,73 +136,79 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>>
         cycle_error: &CycleError,
         _guar: ErrorGuaranteed,
     ) -> Self {
-        let guar = if cycle_error.cycle[0].query.dep_kind == dep_kinds::layout_of
-            && let Some(def_id) = cycle_error.cycle[0].query.ty_def_id
-            && let Some(def_id) = def_id.as_local()
-            && let def_kind = tcx.def_kind(def_id)
-            && matches!(def_kind, DefKind::Closure)
-            && let Some(coroutine_kind) = tcx.coroutine_kind(def_id)
-        {
-            // FIXME: `def_span` for an fn-like coroutine will point to the fn's body
-            // due to interactions between the desugaring into a closure expr and the
-            // def_span code. I'm not motivated to fix it, because I tried and it was
-            // not working, so just hack around it by grabbing the parent fn's span.
-            let span = if coroutine_kind.is_fn_like() {
-                tcx.def_span(tcx.local_parent(def_id))
-            } else {
-                tcx.def_span(def_id)
-            };
-            let mut diag = struct_span_err!(
-                tcx.sess.dcx(),
-                span,
-                E0733,
-                "recursion in {} {} requires boxing",
-                tcx.def_kind_descr_article(def_kind, def_id.to_def_id()),
-                tcx.def_kind_descr(def_kind, def_id.to_def_id()),
-            );
-            for (i, frame) in cycle_error.cycle.iter().enumerate() {
-                if frame.query.dep_kind != dep_kinds::layout_of {
-                    continue;
-                }
-                let Some(frame_def_id) = frame.query.ty_def_id else {
-                    continue;
-                };
-                let Some(frame_coroutine_kind) = tcx.coroutine_kind(frame_def_id) else {
-                    continue;
-                };
-                let frame_span = frame
-                    .query
-                    .default_span(cycle_error.cycle[(i + 1) % cycle_error.cycle.len()].span);
-                if frame_span.is_dummy() {
-                    continue;
-                }
-                if i == 0 {
-                    diag.span_label(frame_span, "recursive call here");
-                } else {
-                    let coroutine_span = if frame_coroutine_kind.is_fn_like() {
-                        tcx.def_span(tcx.parent(frame_def_id))
+        let mut cycle: VecDeque<_> = cycle_error.cycle.iter().collect();
+
+        let guar = 'search: {
+            for _ in 0..cycle.len() {
+                if cycle[0].query.dep_kind == dep_kinds::layout_of
+                    && let Some(def_id) = cycle[0].query.ty_def_id
+                    && let Some(def_id) = def_id.as_local()
+                    && let def_kind = tcx.def_kind(def_id)
+                    && matches!(def_kind, DefKind::Closure)
+                    && let Some(coroutine_kind) = tcx.coroutine_kind(def_id)
+                {
+                    // FIXME: `def_span` for an fn-like coroutine will point to the fn's body
+                    // due to interactions between the desugaring into a closure expr and the
+                    // def_span code. I'm not motivated to fix it, because I tried and it was
+                    // not working, so just hack around it by grabbing the parent fn's span.
+                    let span = if coroutine_kind.is_fn_like() {
+                        tcx.def_span(tcx.local_parent(def_id))
                     } else {
-                        tcx.def_span(frame_def_id)
+                        tcx.def_span(def_id)
                     };
-                    let mut multispan = MultiSpan::from_span(coroutine_span);
-                    multispan.push_span_label(frame_span, "...leading to this recursive call");
-                    diag.span_note(
-                        multispan,
-                        format!("which leads to this {}", tcx.def_descr(frame_def_id)),
+                    let mut diag = struct_span_err!(
+                        tcx.sess.dcx(),
+                        span,
+                        E0733,
+                        "recursion in {} {} requires boxing",
+                        tcx.def_kind_descr_article(def_kind, def_id.to_def_id()),
+                        tcx.def_kind_descr(def_kind, def_id.to_def_id()),
                     );
+                    for (i, frame) in cycle.iter().enumerate() {
+                        if frame.query.dep_kind != dep_kinds::layout_of {
+                            continue;
+                        }
+                        let Some(frame_def_id) = frame.query.ty_def_id else {
+                            continue;
+                        };
+                        let Some(frame_coroutine_kind) = tcx.coroutine_kind(frame_def_id) else {
+                            continue;
+                        };
+                        let frame_span =
+                            frame.query.default_span(cycle[(i + 1) % cycle.len()].span);
+                        if frame_span.is_dummy() {
+                            continue;
+                        }
+                        if i == 0 {
+                            diag.span_label(frame_span, "recursive call here");
+                        } else {
+                            let coroutine_span: Span = if frame_coroutine_kind.is_fn_like() {
+                                tcx.def_span(tcx.parent(frame_def_id))
+                            } else {
+                                tcx.def_span(frame_def_id)
+                            };
+                            let mut multispan = MultiSpan::from_span(coroutine_span);
+                            multispan
+                                .push_span_label(frame_span, "...leading to this recursive call");
+                            diag.span_note(
+                                multispan,
+                                format!("which leads to this {}", tcx.def_descr(frame_def_id)),
+                            );
+                        }
+                    }
+                    // FIXME: We could report a structured suggestion if we had
+                    // enough info here... Maybe we can use a hacky HIR walker.
+                    if matches!(
+                        coroutine_kind,
+                        hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
+                    ) {
+                        diag.note("a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future");
+                    }
+                    break 'search diag.emit();
+                } else {
+                    cycle.rotate_left(1);
                 }
             }
-            if matches!(
-                coroutine_kind,
-                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
-            ) {
-                diag.note("a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future");
-                diag.note(
-                    "consider using the `async_recursion` crate: https://crates.io/crates/async_recursion",
-                );
-            }
-            diag.emit()
-        } else {
             report_cycle(tcx.sess, cycle_error).emit()
         };
 
diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.stderr b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
index 37de274565d..d085747bc4b 100644
--- a/tests/ui/async-await/in-trait/async-recursive-generic.stderr
+++ b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
@@ -8,7 +8,6 @@ LL |             self.foo_recursive(n - 1).await
    |             ------------------------------- recursive call here
    |
    = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
-   = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/in-trait/async-recursive.stderr b/tests/ui/async-await/in-trait/async-recursive.stderr
index 6b99c516c3b..25ebc6e77c4 100644
--- a/tests/ui/async-await/in-trait/async-recursive.stderr
+++ b/tests/ui/async-await/in-trait/async-recursive.stderr
@@ -8,7 +8,6 @@ LL |             self.foo_recursive(n - 1).await
    |             ------------------------------- recursive call here
    |
    = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
-   = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs
index 8443cbcf4ac..4b615343a05 100644
--- a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs
+++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs
@@ -1,6 +1,7 @@
 // edition: 2021
+
+// Test doesn't fail until monomorphization time, unfortunately.
 // build-fail
-//~^^ ERROR cycle detected when computing layout of
 
 fn main() {
     let _ = async {
@@ -31,6 +32,7 @@ where
     C: First,
 {
     async fn second(self) {
+        //~^ ERROR recursion in an async fn requires boxing
         self.first().await.second().await;
     }
 }
diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr
index 8e573b512ad..8126c6e1394 100644
--- a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr
+++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr
@@ -1,12 +1,11 @@
-error[E0391]: cycle detected when computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}>`
+error[E0733]: recursion in an async fn requires boxing
+  --> $DIR/indirect-recursion-issue-112047.rs:34:5
    |
-   = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}>`...
-   = note: ...which requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}`...
-   = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<<<A as First>::Second as Second>::{opaque#0}>`...
-   = note: ...which again requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}>`, completing the cycle
-   = note: cycle used when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:6:13: 8:6}`
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+LL |     async fn second(self) {
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0391`.
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
index 3f2ee4150da..52fb41be1fb 100644
--- a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
+++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
@@ -14,7 +14,6 @@ LL | async fn rec_2() {
 LL |     rec_1().await;
    |     ------------- ...leading to this recursive call
    = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
-   = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.stderr
index cec92c54f01..5475469335f 100644
--- a/tests/ui/async-await/recursive-async-impl-trait-type.stderr
+++ b/tests/ui/async-await/recursive-async-impl-trait-type.stderr
@@ -8,7 +8,6 @@ LL |     recursive_async_function().await;
    |     -------------------------------- recursive call here
    |
    = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
-   = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/recursive-coroutine.rs b/tests/ui/impl-trait/recursive-coroutine-boxed.rs
index b9291f07e21..b9291f07e21 100644
--- a/tests/ui/impl-trait/recursive-coroutine.rs
+++ b/tests/ui/impl-trait/recursive-coroutine-boxed.rs
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
new file mode 100644
index 00000000000..11b3c4ef007
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
@@ -0,0 +1,11 @@
+error[E0733]: recursion in a coroutine requires boxing
+  --> $DIR/recursive-coroutine-indirect.rs:6:5
+   |
+LL |     move || {
+   |     ^^^^^^^
+LL |         let x = coroutine_hold();
+   |             - recursive call here
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
new file mode 100644
index 00000000000..11b3c4ef007
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
@@ -0,0 +1,11 @@
+error[E0733]: recursion in a coroutine requires boxing
+  --> $DIR/recursive-coroutine-indirect.rs:6:5
+   |
+LL |     move || {
+   |     ^^^^^^^
+LL |         let x = coroutine_hold();
+   |             - recursive call here
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.rs b/tests/ui/impl-trait/recursive-coroutine-indirect.rs
new file mode 100644
index 00000000000..4f8d4d33050
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.rs
@@ -0,0 +1,13 @@
+// revisions: current next
+//[next] compile-flags: -Znext-solver
+#![feature(coroutines)]
+#![allow(unconditional_recursion)]
+fn coroutine_hold() -> impl Sized {
+    move || { //~ ERROR recursion in a coroutine requires boxing
+        let x = coroutine_hold();
+        yield;
+        x;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
index a6bca107b1e..432f80a1763 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
@@ -1,6 +1,5 @@
 // Test that impl trait does not allow creating recursive types that are
 // otherwise forbidden.
-
 #![feature(coroutines)]
 #![allow(unconditional_recursion)]
 
@@ -69,15 +68,6 @@ fn substs_change<T: 'static>() -> impl Sized {
     (substs_change::<&T>(),)
 }
 
-fn coroutine_hold() -> impl Sized {
-    move || {
-    //~^ ERROR
-        let x = coroutine_hold();
-        yield;
-        x;
-    }
-}
-
 fn use_fn_ptr() -> impl Sized {
     // OK, error already reported
     fn_ptr()
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
index 16a9012958e..d5b8c531fd6 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -1,5 +1,5 @@
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:7:22
+  --> $DIR/recursive-impl-trait-type-indirect.rs:6:22
    |
 LL | fn option(i: i32) -> impl Sized {
    |                      ^^^^^^^^^^ recursive opaque type
@@ -10,7 +10,7 @@ LL |     if i < 0 { None } else { Some((option(i - 1), i)) }
    |                returning here with type `Option<(impl Sized, i32)>`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:12:15
+  --> $DIR/recursive-impl-trait-type-indirect.rs:11:15
    |
 LL | fn tuple() -> impl Sized {
    |               ^^^^^^^^^^ recursive opaque type
@@ -19,7 +19,7 @@ LL |     (tuple(),)
    |     ---------- returning here with type `(impl Sized,)`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:17:15
+  --> $DIR/recursive-impl-trait-type-indirect.rs:16:15
    |
 LL | fn array() -> impl Sized {
    |               ^^^^^^^^^^ recursive opaque type
@@ -28,7 +28,7 @@ LL |     [array()]
    |     --------- returning here with type `[impl Sized; 1]`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:22:13
+  --> $DIR/recursive-impl-trait-type-indirect.rs:21:13
    |
 LL | fn ptr() -> impl Sized {
    |             ^^^^^^^^^^ recursive opaque type
@@ -37,7 +37,7 @@ LL |     &ptr() as *const _
    |     ------------------ returning here with type `*const impl Sized`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:27:16
+  --> $DIR/recursive-impl-trait-type-indirect.rs:26:16
    |
 LL | fn fn_ptr() -> impl Sized {
    |                ^^^^^^^^^^ recursive opaque type
@@ -46,7 +46,7 @@ LL |     fn_ptr as fn() -> _
    |     ------------------- returning here with type `fn() -> impl Sized`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:32:25
+  --> $DIR/recursive-impl-trait-type-indirect.rs:31:25
    |
 LL |   fn closure_capture() -> impl Sized {
    |                           ^^^^^^^^^^ recursive opaque type
@@ -55,10 +55,10 @@ LL | /     move || {
 LL | |         x;
    | |         - closure captures itself here
 LL | |     }
-   | |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 35:12}`
+   | |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:34:5: 34:12}`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:40:29
+  --> $DIR/recursive-impl-trait-type-indirect.rs:39:29
    |
 LL |   fn closure_ref_capture() -> impl Sized {
    |                               ^^^^^^^^^^ recursive opaque type
@@ -67,28 +67,28 @@ LL | /     move || {
 LL | |         &x;
    | |          - closure captures itself here
 LL | |     }
-   | |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 43:12}`
+   | |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:42:5: 42:12}`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:48:21
+  --> $DIR/recursive-impl-trait-type-indirect.rs:47:21
    |
 LL | fn closure_sig() -> impl Sized {
    |                     ^^^^^^^^^^ recursive opaque type
 LL |
 LL |     || closure_sig()
-   |     ---------------- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:7}`
+   |     ---------------- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:49:5: 49:7}`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:53:23
+  --> $DIR/recursive-impl-trait-type-indirect.rs:52:23
    |
 LL | fn coroutine_sig() -> impl Sized {
    |                       ^^^^^^^^^^ recursive opaque type
 LL |
 LL |     || coroutine_sig()
-   |     ------------------ returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:7}`
+   |     ------------------ returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7}`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:58:27
+  --> $DIR/recursive-impl-trait-type-indirect.rs:57:27
    |
 LL |   fn coroutine_capture() -> impl Sized {
    |                             ^^^^^^^^^^ recursive opaque type
@@ -98,10 +98,10 @@ LL | |         yield;
 LL | |         x;
    | |         - coroutine captures itself here
 LL | |     }
-   | |_____- returning here with type `{coroutine@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 61:12}`
+   | |_____- returning here with type `{coroutine@$DIR/recursive-impl-trait-type-indirect.rs:60:5: 60:12}`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:67:35
+  --> $DIR/recursive-impl-trait-type-indirect.rs:66:35
    |
 LL | fn substs_change<T: 'static>() -> impl Sized {
    |                                   ^^^^^^^^^^ recursive opaque type
@@ -109,17 +109,8 @@ LL |
 LL |     (substs_change::<&T>(),)
    |     ------------------------ returning here with type `(impl Sized,)`
 
-error[E0733]: recursion in a coroutine requires boxing
-  --> $DIR/recursive-impl-trait-type-indirect.rs:73:5
-   |
-LL |     move || {
-   |     ^^^^^^^
-LL |
-LL |         let x = coroutine_hold();
-   |             - recursive call here
-
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:86:26
+  --> $DIR/recursive-impl-trait-type-indirect.rs:76:26
    |
 LL | fn mutual_recursion() -> impl Sync {
    |                          ^^^^^^^^^ recursive opaque type
@@ -131,7 +122,7 @@ LL | fn mutual_recursion_b() -> impl Sized {
    |                            ---------- returning this opaque type `impl Sized`
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-indirect.rs:91:28
+  --> $DIR/recursive-impl-trait-type-indirect.rs:81:28
    |
 LL | fn mutual_recursion() -> impl Sync {
    |                          --------- returning this opaque type `impl Sync`
@@ -142,7 +133,6 @@ LL |
 LL |     mutual_recursion()
    |     ------------------ returning here with type `impl Sync`
 
-error: aborting due to 14 previous errors
+error: aborting due to 13 previous errors
 
-Some errors have detailed explanations: E0720, E0733.
-For more information about an error, try `rustc --explain E0720`.
+For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr
index 2e75f676971..b62186103c7 100644
--- a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr
+++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr
@@ -14,7 +14,6 @@ LL | async fn recur(t: impl Recur) {
 LL |     t.recur().await;
    |     --------------- ...leading to this recursive call
    = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
-   = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
 
 error: aborting due to 1 previous error