Skip to content

Commit d0af0e3

Browse files
Add a bit more detail to multi-step recursive calls
1 parent 48730f9 commit d0af0e3

File tree

3 files changed

+36
-16
lines changed

3 files changed

+36
-16
lines changed

compiler/rustc_middle/src/values.rs

+22-10
Original file line numberDiff line numberDiff line change
@@ -161,21 +161,15 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>>
161161
tcx.def_kind_descr_article(def_kind, def_id.to_def_id()),
162162
tcx.def_kind_descr(def_kind, def_id.to_def_id()),
163163
);
164-
if matches!(coroutine_kind, hir::CoroutineKind::Async(_)) {
165-
diag.note("a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future");
166-
diag.note(
167-
"consider using the `async_recursion` crate: https://crates.io/crates/async_recursion",
168-
);
169-
}
170-
let mut called = false;
171164
for (i, frame) in cycle_error.cycle.iter().enumerate() {
172165
if frame.query.dep_kind != dep_kinds::layout_of {
173166
continue;
174167
}
175168
let Some(frame_def_id) = frame.query.ty_def_id else {
176169
continue;
177170
};
178-
if !matches!(tcx.def_kind(frame_def_id), DefKind::Coroutine) {
171+
let def_kind = tcx.def_kind(frame_def_id);
172+
if !matches!(def_kind, DefKind::Coroutine) {
179173
continue;
180174
}
181175
let frame_span = frame
@@ -184,8 +178,26 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>>
184178
if frame_span.is_dummy() {
185179
continue;
186180
}
187-
diag.span_label(frame_span, if called { "...which calls this" } else { "recursive call here" });
188-
called = true;
181+
if i == 0 {
182+
diag.span_label(frame_span, "recursive call here");
183+
} else {
184+
let coroutine_span: Span = if tcx
185+
.coroutine_kind(frame_def_id)
186+
.expect("expected coroutine to have a coroutine_kind").is_fn_like() {
187+
tcx.def_span(tcx.parent(frame_def_id))
188+
} else {
189+
tcx.def_span(frame_def_id)
190+
};
191+
let mut multispan = MultiSpan::from_span(coroutine_span);
192+
multispan.push_span_label(frame_span, "...leading to this recursive call");
193+
diag.span_note(multispan, format!("which leads to this {}", tcx.def_kind_descr(def_kind, frame_def_id)));
194+
}
195+
}
196+
if matches!(coroutine_kind, hir::CoroutineKind::Async(_)) {
197+
diag.note("a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future");
198+
diag.note(
199+
"consider using the `async_recursion` crate: https://crates.io/crates/async_recursion",
200+
);
189201
}
190202
diag.emit()
191203
} else {

tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr

+7-3
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ LL | async fn rec_1() {
55
| ^^^^^^^^^^^^^^^^
66
LL | rec_2().await;
77
| ------------- recursive call here
8-
...
9-
LL | rec_1().await;
10-
| ------------- ...which calls this
118
|
9+
note: which leads to this async fn
10+
--> $DIR/mutually-recursive-async-impl-trait-type.rs:9:1
11+
|
12+
LL | async fn rec_2() {
13+
| ^^^^^^^^^^^^^^^^
14+
LL | rec_1().await;
15+
| ------------- ...leading to this recursive call
1216
= note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
1317
= note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
1418

tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
error[E0733]: recursion in an async block requires boxing
22
--> $DIR/indirect-recursion-issue-112047.rs:21:9
33
|
4-
LL | t.recur().await;
5-
| --------------- ...which calls this
6-
...
74
LL | async move { recur(self).await; }
85
| ^^^^^^^^^^^^^-----------------^^^
96
| |
107
| recursive call here
118
|
9+
note: which leads to this async fn
10+
--> $DIR/indirect-recursion-issue-112047.rs:13:1
11+
|
12+
LL | async fn recur(t: impl Recur) {
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
LL | t.recur().await;
15+
| --------------- ...leading to this recursive call
1216
= note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
1317
= note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
1418

0 commit comments

Comments
 (0)