Skip to content

Commit

Permalink
Add a bit more detail to multi-step recursive calls
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Nov 8, 2023
1 parent 48730f9 commit d0af0e3
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 16 deletions.
32 changes: 22 additions & 10 deletions compiler/rustc_middle/src/values.rs
Expand Up @@ -161,21 +161,15 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>>
tcx.def_kind_descr_article(def_kind, def_id.to_def_id()),
tcx.def_kind_descr(def_kind, def_id.to_def_id()),
);
if matches!(coroutine_kind, hir::CoroutineKind::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",
);
}
let mut called = false;
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;
};
if !matches!(tcx.def_kind(frame_def_id), DefKind::Coroutine) {
let def_kind = tcx.def_kind(frame_def_id);
if !matches!(def_kind, DefKind::Coroutine) {
continue;
}
let frame_span = frame
Expand All @@ -184,8 +178,26 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>>
if frame_span.is_dummy() {
continue;
}
diag.span_label(frame_span, if called { "...which calls this" } else { "recursive call here" });
called = true;
if i == 0 {
diag.span_label(frame_span, "recursive call here");
} else {
let coroutine_span: Span = if tcx
.coroutine_kind(frame_def_id)
.expect("expected coroutine to have a 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_kind_descr(def_kind, frame_def_id)));
}
}
if matches!(coroutine_kind, hir::CoroutineKind::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 {
Expand Down
Expand Up @@ -5,10 +5,14 @@ LL | async fn rec_1() {
| ^^^^^^^^^^^^^^^^
LL | rec_2().await;
| ------------- recursive call here
...
LL | rec_1().await;
| ------------- ...which calls this
|
note: which leads to this async fn
--> $DIR/mutually-recursive-async-impl-trait-type.rs:9:1
|
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

Expand Down
@@ -1,14 +1,18 @@
error[E0733]: recursion in an async block requires boxing
--> $DIR/indirect-recursion-issue-112047.rs:21:9
|
LL | t.recur().await;
| --------------- ...which calls this
...
LL | async move { recur(self).await; }
| ^^^^^^^^^^^^^-----------------^^^
| |
| recursive call here
|
note: which leads to this async fn
--> $DIR/indirect-recursion-issue-112047.rs:13:1
|
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

Expand Down

0 comments on commit d0af0e3

Please sign in to comment.