Skip to content

Commit 5841c68

Browse files
committed
Improve query cycle error message
1 parent 21f6e55 commit 5841c68

File tree

2 files changed

+32
-18
lines changed

2 files changed

+32
-18
lines changed

src/librustc/ty/maps/job.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub(super) enum QueryResult<'tcx, T> {
3131
/// A span and a query key
3232
#[derive(Clone, Debug)]
3333
pub struct QueryInfo<'tcx> {
34+
/// The span for a reason this query was required
3435
pub span: Span,
3536
pub query: Query<'tcx>,
3637
}
@@ -73,13 +74,22 @@ impl<'tcx> QueryJob<'tcx> {
7374
cycle.insert(0, job.info.clone());
7475

7576
if &*job as *const _ == self as *const _ {
76-
break;
77+
// This is the end of the cycle
78+
// The span entry we included was for the usage
79+
// of the cycle itself, and not part of the cycle
80+
// Replace it with the span which caused the cycle to form
81+
cycle[0].span = span;
82+
// Find out why the cycle itself was used
83+
let usage = job.parent.as_ref().map(|parent| {
84+
(job.info.span, parent.info.query.clone())
85+
});
86+
return Err(CycleError { usage, cycle });
7787
}
7888

7989
current_job = job.parent.clone();
8090
}
8191

82-
Err(CycleError { span, cycle })
92+
panic!("did not find a cycle")
8393
}
8494

8595
/// Signals to waiters that the query is complete.

src/librustc/ty/maps/plumbing.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ pub(super) trait GetCacheInternal<'tcx>: QueryDescription<'tcx> + Sized {
6464

6565
#[derive(Clone)]
6666
pub(super) struct CycleError<'tcx> {
67-
/// The span of the reason the first query in `cycle` ran the last query in `cycle`
68-
pub(super) span: Span,
67+
/// The query and related span which uses the cycle
68+
pub(super) usage: Option<(Span, Query<'tcx>)>,
6969
pub(super) cycle: Vec<QueryInfo<'tcx>>,
7070
}
7171

@@ -81,7 +81,7 @@ pub(super) enum TryGetLock<'a, 'tcx: 'a, T, D: QueryDescription<'tcx> + 'a> {
8181
}
8282

8383
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
84-
pub(super) fn report_cycle(self, CycleError { span, cycle: stack }: CycleError<'gcx>)
84+
pub(super) fn report_cycle(self, CycleError { usage, cycle: stack }: CycleError<'gcx>)
8585
-> DiagnosticBuilder<'a>
8686
{
8787
assert!(!stack.is_empty());
@@ -95,23 +95,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
9595
// (And cycle errors around impls tend to occur during the
9696
// collect/coherence phases anyhow.)
9797
item_path::with_forced_impl_filename_line(|| {
98-
let span = fix_span(span, &stack.first().unwrap().query);
99-
let mut err =
100-
struct_span_err!(self.sess, span, E0391,
101-
"cyclic dependency detected");
102-
err.span_label(span, "cyclic reference");
103-
104-
err.span_note(fix_span(stack[0].span, &stack[0].query),
105-
&format!("the cycle begins when {}...", stack[0].query.describe(self)));
106-
107-
for &QueryInfo { span, ref query, .. } in &stack[1..] {
108-
err.span_note(fix_span(span, query),
109-
&format!("...which then requires {}...", query.describe(self)));
98+
let span = fix_span(stack[1 % stack.len()].span, &stack[0].query);
99+
let mut err = struct_span_err!(self.sess,
100+
span,
101+
E0391,
102+
"cycle detected when {}",
103+
stack[0].query.describe(self));
104+
105+
for i in 1..stack.len() {
106+
let query = &stack[i].query;
107+
let span = fix_span(stack[(i + 1) % stack.len()].span, query);
108+
err.span_note(span, &format!("...which requires {}...", query.describe(self)));
110109
}
111110

112-
err.note(&format!("...which then again requires {}, completing the cycle.",
111+
err.note(&format!("...which again requires {}, completing the cycle",
113112
stack[0].query.describe(self)));
114113

114+
if let Some((span, query)) = usage {
115+
err.span_note(fix_span(span, &query),
116+
&format!("cycle used when {}", query.describe(self)));
117+
}
118+
115119
return err
116120
})
117121
}

0 commit comments

Comments
 (0)