Skip to content

Commit b91e6a2

Browse files
committed
Auto merge of #49950 - Zoxc:default-span, r=estebank
Improve query cycle error message r? @michaelwoerister
2 parents 9a59133 + 9cbe3b7 commit b91e6a2

29 files changed

+138
-171
lines changed

Diff for: src/librustc/ty/maps/job.rs

+12-2
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.

Diff for: src/librustc/ty/maps/plumbing.rs

+43-36
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use errors::DiagnosticBuilder;
1717
use errors::Level;
1818
use ty::tls;
1919
use ty::{TyCtxt};
20+
use ty::maps::Query;
2021
use ty::maps::config::QueryDescription;
2122
use ty::maps::job::{QueryResult, QueryInfo};
2223
use ty::item_path;
@@ -63,7 +64,8 @@ pub(super) trait GetCacheInternal<'tcx>: QueryDescription<'tcx> + Sized {
6364

6465
#[derive(Clone)]
6566
pub(super) struct CycleError<'tcx> {
66-
pub(super) span: Span,
67+
/// The query and related span which uses the cycle
68+
pub(super) usage: Option<(Span, Query<'tcx>)>,
6769
pub(super) cycle: Vec<QueryInfo<'tcx>>,
6870
}
6971

@@ -79,33 +81,41 @@ pub(super) enum TryGetLock<'a, 'tcx: 'a, T, D: QueryDescription<'tcx> + 'a> {
7981
}
8082

8183
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
82-
pub(super) fn report_cycle(self, CycleError { span, cycle: stack }: CycleError)
84+
pub(super) fn report_cycle(self, CycleError { usage, cycle: stack }: CycleError<'gcx>)
8385
-> DiagnosticBuilder<'a>
8486
{
8587
assert!(!stack.is_empty());
8688

89+
let fix_span = |span: Span, query: &Query<'gcx>| {
90+
self.sess.codemap().def_span(query.default_span(self, span))
91+
};
92+
8793
// Disable naming impls with types in this path, since that
8894
// sometimes cycles itself, leading to extra cycle errors.
8995
// (And cycle errors around impls tend to occur during the
9096
// collect/coherence phases anyhow.)
9197
item_path::with_forced_impl_filename_line(|| {
92-
let span = self.sess.codemap().def_span(span);
93-
let mut err =
94-
struct_span_err!(self.sess, span, E0391,
95-
"cyclic dependency detected");
96-
err.span_label(span, "cyclic reference");
97-
98-
err.span_note(self.sess.codemap().def_span(stack[0].span),
99-
&format!("the cycle begins when {}...", stack[0].query.describe(self)));
100-
101-
for &QueryInfo { span, ref query, .. } in &stack[1..] {
102-
err.span_note(self.sess.codemap().def_span(span),
103-
&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)));
104109
}
105110

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

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+
109119
return err
110120
})
111121
}
@@ -266,6 +276,22 @@ macro_rules! define_maps {
266276
r
267277
}
268278
}
279+
280+
// FIXME(eddyb) Get more valid Span's on queries.
281+
pub fn default_span(&self, tcx: TyCtxt<'_, $tcx, '_>, span: Span) -> Span {
282+
if span != DUMMY_SP {
283+
return span;
284+
}
285+
// The def_span query is used to calculate default_span,
286+
// so exit to avoid infinite recursion
287+
match *self {
288+
Query::def_span(..) => return span,
289+
_ => ()
290+
}
291+
match *self {
292+
$(Query::$name(key) => key.default_span(tcx),)*
293+
}
294+
}
269295
}
270296

271297
pub mod queries {
@@ -303,7 +329,7 @@ macro_rules! define_maps {
303329
/// If the query already executed and panicked, this will fatal error / silently panic
304330
fn try_get_lock(
305331
tcx: TyCtxt<'a, $tcx, 'lcx>,
306-
mut span: Span,
332+
span: Span,
307333
key: &$K
308334
) -> TryGetLock<'a, $tcx, $V, Self>
309335
{
@@ -329,21 +355,14 @@ macro_rules! define_maps {
329355
};
330356
mem::drop(lock);
331357

332-
// This just matches the behavior of `try_get_with` so the span when
333-
// we await matches the span we would use when executing.
334-
// See the FIXME there.
335-
if span == DUMMY_SP && stringify!($name) != "def_span" {
336-
span = key.default_span(tcx);
337-
}
338-
339358
if let Err(cycle) = job.await(tcx, span) {
340359
return TryGetLock::JobCompleted(Err(cycle));
341360
}
342361
}
343362
}
344363

345364
fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
346-
mut span: Span,
365+
span: Span,
347366
key: $K)
348367
-> Result<$V, CycleError<$tcx>>
349368
{
@@ -377,18 +396,6 @@ macro_rules! define_maps {
377396

378397
let mut lock = get_lock_or_return!();
379398

380-
// FIXME(eddyb) Get more valid Span's on queries.
381-
// def_span guard is necessary to prevent a recursive loop,
382-
// default_span calls def_span query internally.
383-
if span == DUMMY_SP && stringify!($name) != "def_span" {
384-
// This might deadlock if we hold the map lock since we might be
385-
// waiting for the def_span query and switch to some other fiber
386-
// So we drop the lock here and reacquire it
387-
mem::drop(lock);
388-
span = key.default_span(tcx);
389-
lock = get_lock_or_return!();
390-
}
391-
392399
// Fast path for when incr. comp. is off. `to_dep_node` is
393400
// expensive for some DepKinds.
394401
if !tcx.dep_graph.is_fully_enabled() {

Diff for: src/test/compile-fail/coherence-inherited-assoc-ty-cycle-err.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#![feature(specialization)]
1818

1919
trait Trait<T> { type Assoc; }
20-
//~^ cyclic dependency detected [E0391]
20+
//~^ cycle detected
2121

2222
impl<T> Trait<T> for Vec<T> {
2323
type Assoc = ();

Diff for: src/test/compile-fail/const-size_of-cycle.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// error-pattern: cyclic dependency detected
11+
// error-pattern: cycle detected
1212

1313
#![feature(const_fn)]
1414

Diff for: src/test/compile-fail/cycle-projection-based-on-where-clause.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ trait Trait { type Item; }
2525
struct A<T>
2626
where T : Trait,
2727
T : Add<T::Item>
28-
//~^ ERROR cyclic dependency detected
28+
//~^ ERROR cycle detected
2929
//~| ERROR associated type `Item` not found for `T`
3030
{
3131
data: T

Diff for: src/test/compile-fail/cycle-trait-default-type-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// again references the trait.
1313

1414
trait Foo<X = Box<Foo>> {
15-
//~^ ERROR cyclic dependency detected
15+
//~^ ERROR cycle detected
1616
}
1717

1818
fn main() { }

Diff for: src/test/compile-fail/cycle-trait-supertrait-direct.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// Test a supertrait cycle where a trait extends itself.
1212

1313
trait Chromosome: Chromosome {
14-
//~^ ERROR cyclic dependency detected
14+
//~^ ERROR cycle detected
1515
}
1616

1717
fn main() { }

Diff for: src/test/compile-fail/infinite-vec-type-recursion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99
// except according to those terms.
1010

1111
type x = Vec<x>;
12-
//~^ ERROR cyclic dependency detected
12+
//~^ ERROR cycle detected
1313

1414
fn main() { let b: x = Vec::new(); }

Diff for: src/test/compile-fail/issue-20772.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
trait T : Iterator<Item=Self::Item>
12-
//~^ ERROR cyclic dependency detected
12+
//~^ ERROR cycle detected
1313
//~| ERROR associated type `Item` not found for `Self`
1414
{}
1515

Diff for: src/test/compile-fail/issue-20825.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub trait Subscriber {
1313
}
1414

1515
pub trait Processor: Subscriber<Input = Self::Input> {
16-
//~^ ERROR cyclic dependency detected [E0391]
16+
//~^ ERROR cycle detected
1717
type Input;
1818
}
1919

Diff for: src/test/compile-fail/issue-21177.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ trait Trait {
1414
}
1515

1616
fn foo<T: Trait<A = T::B>>() { }
17-
//~^ ERROR cyclic dependency detected
17+
//~^ ERROR cycle detected
1818
//~| ERROR associated type `B` not found for `T`
1919

2020
fn main() { }

Diff for: src/test/compile-fail/issue-22673.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
trait Expr : PartialEq<Self::Item> {
12-
//~^ ERROR: cyclic dependency detected
12+
//~^ ERROR: cycle detected
1313
type Item;
1414
}
1515

Diff for: src/test/compile-fail/issue-26548.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// error-pattern: cyclic dependency detected
12-
// note-pattern: the cycle begins when computing layout of
13-
// note-pattern: ...which then requires computing layout of
14-
// note-pattern: ...which then again requires computing layout of
15-
11+
// error-pattern: cycle detected when computing layout of
12+
// note-pattern: ...which requires computing layout of
13+
// note-pattern: ...which again requires computing layout of
1614

1715
trait Mirror { type It: ?Sized; }
1816
impl<T: ?Sized> Mirror for T { type It = Self; }

Diff for: src/test/compile-fail/issue-34373.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ trait Trait<T> {
1414
fn foo(_: T) {}
1515
}
1616

17-
pub struct Foo<T = Box<Trait<DefaultFoo>>>;
18-
type DefaultFoo = Foo; //~ ERROR cyclic dependency detected
17+
pub struct Foo<T = Box<Trait<DefaultFoo>>>; //~ ERROR cycle detected
18+
type DefaultFoo = Foo;
1919

2020
fn main() {
2121
}

Diff for: src/test/compile-fail/issue-44415.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// error-pattern: cycle detected when computing layout of
12+
1113
#![feature(const_fn)]
1214
#![feature(core_intrinsics)]
1315

1416
use std::intrinsics;
1517

1618
struct Foo {
1719
bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
18-
//~^ ERROR cyclic dependency detected
1920
x: usize,
2021
}
2122

Diff for: src/test/compile-fail/resolve-self-in-impl.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ impl Tr for S where Self: Copy {} // OK
2121
impl Tr for S where S<Self>: Copy {} // OK
2222
impl Tr for S where Self::A: Copy {} // OK
2323

24-
impl Tr for Self {} //~ ERROR cyclic dependency detected
25-
impl Tr for S<Self> {} //~ ERROR cyclic dependency detected
26-
impl Self {} //~ ERROR cyclic dependency detected
27-
impl S<Self> {} //~ ERROR cyclic dependency detected
28-
impl Tr<Self::A> for S {} //~ ERROR cyclic dependency detected
24+
impl Tr for Self {} //~ ERROR cycle detected
25+
impl Tr for S<Self> {} //~ ERROR cycle detected
26+
impl Self {} //~ ERROR cycle detected
27+
impl S<Self> {} //~ ERROR cycle detected
28+
impl Tr<Self::A> for S {} //~ ERROR cycle detected
2929

3030
fn main() {}

Diff for: src/test/ui/cycle-trait-supertrait-indirect.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@ trait A: B {
1515
}
1616

1717
trait B: C {
18+
//~^ ERROR cycle detected
1819
}
1920

2021
trait C: B { }
21-
//~^ ERROR cyclic dependency detected
22-
//~| cyclic reference
2322

2423
fn main() { }

Diff for: src/test/ui/cycle-trait-supertrait-indirect.stderr

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
error[E0391]: cyclic dependency detected
2-
--> $DIR/cycle-trait-supertrait-indirect.rs:20:1
1+
error[E0391]: cycle detected when computing the supertraits of `B`
2+
--> $DIR/cycle-trait-supertrait-indirect.rs:17:1
33
|
4-
LL | trait C: B { }
5-
| ^^^^^^^^^^ cyclic reference
4+
LL | trait B: C {
5+
| ^^^^^^^^^^
66
|
7-
note: the cycle begins when computing the supertraits of `B`...
8-
--> $DIR/cycle-trait-supertrait-indirect.rs:14:1
7+
note: ...which requires computing the supertraits of `C`...
8+
--> $DIR/cycle-trait-supertrait-indirect.rs:21:1
99
|
10-
LL | trait A: B {
10+
LL | trait C: B { }
1111
| ^^^^^^^^^^
12-
note: ...which then requires computing the supertraits of `C`...
13-
--> $DIR/cycle-trait-supertrait-indirect.rs:17:1
12+
= note: ...which again requires computing the supertraits of `B`, completing the cycle
13+
note: cycle used when computing the supertraits of `A`
14+
--> $DIR/cycle-trait-supertrait-indirect.rs:14:1
1415
|
15-
LL | trait B: C {
16+
LL | trait A: B {
1617
| ^^^^^^^^^^
17-
= note: ...which then again requires computing the supertraits of `B`, completing the cycle.
1818

1919
error: aborting due to previous error
2020

Diff for: src/test/ui/impl-trait/auto-trait-leak.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ fn after() -> impl Fn(i32) {
4040
// independently resolved and only require the concrete
4141
// return type, which can't depend on the obligation.
4242
fn cycle1() -> impl Clone {
43-
//~^ ERROR cyclic dependency detected
44-
//~| cyclic reference
43+
//~^ ERROR cycle detected
4544
send(cycle2().clone());
4645

4746
Rc::new(Cell::new(5))

0 commit comments

Comments
 (0)