Skip to content

Commit

Permalink
Auto merge of #49950 - Zoxc:default-span, r=estebank
Browse files Browse the repository at this point in the history
Improve query cycle error message

r? @michaelwoerister
  • Loading branch information
bors committed Apr 18, 2018
2 parents 9a59133 + 9cbe3b7 commit b91e6a2
Show file tree
Hide file tree
Showing 29 changed files with 138 additions and 171 deletions.
14 changes: 12 additions & 2 deletions src/librustc/ty/maps/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub(super) enum QueryResult<'tcx, T> {
/// A span and a query key
#[derive(Clone, Debug)]
pub struct QueryInfo<'tcx> {
/// The span for a reason this query was required
pub span: Span,
pub query: Query<'tcx>,
}
Expand Down Expand Up @@ -73,13 +74,22 @@ impl<'tcx> QueryJob<'tcx> {
cycle.insert(0, job.info.clone());

if &*job as *const _ == self as *const _ {
break;
// This is the end of the cycle
// The span entry we included was for the usage
// of the cycle itself, and not part of the cycle
// Replace it with the span which caused the cycle to form
cycle[0].span = span;
// Find out why the cycle itself was used
let usage = job.parent.as_ref().map(|parent| {
(job.info.span, parent.info.query.clone())
});
return Err(CycleError { usage, cycle });
}

current_job = job.parent.clone();
}

Err(CycleError { span, cycle })
panic!("did not find a cycle")
}

/// Signals to waiters that the query is complete.
Expand Down
79 changes: 43 additions & 36 deletions src/librustc/ty/maps/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use errors::DiagnosticBuilder;
use errors::Level;
use ty::tls;
use ty::{TyCtxt};
use ty::maps::Query;
use ty::maps::config::QueryDescription;
use ty::maps::job::{QueryResult, QueryInfo};
use ty::item_path;
Expand Down Expand Up @@ -63,7 +64,8 @@ pub(super) trait GetCacheInternal<'tcx>: QueryDescription<'tcx> + Sized {

#[derive(Clone)]
pub(super) struct CycleError<'tcx> {
pub(super) span: Span,
/// The query and related span which uses the cycle
pub(super) usage: Option<(Span, Query<'tcx>)>,
pub(super) cycle: Vec<QueryInfo<'tcx>>,
}

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

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub(super) fn report_cycle(self, CycleError { span, cycle: stack }: CycleError)
pub(super) fn report_cycle(self, CycleError { usage, cycle: stack }: CycleError<'gcx>)
-> DiagnosticBuilder<'a>
{
assert!(!stack.is_empty());

let fix_span = |span: Span, query: &Query<'gcx>| {
self.sess.codemap().def_span(query.default_span(self, span))
};

// Disable naming impls with types in this path, since that
// sometimes cycles itself, leading to extra cycle errors.
// (And cycle errors around impls tend to occur during the
// collect/coherence phases anyhow.)
item_path::with_forced_impl_filename_line(|| {
let span = self.sess.codemap().def_span(span);
let mut err =
struct_span_err!(self.sess, span, E0391,
"cyclic dependency detected");
err.span_label(span, "cyclic reference");

err.span_note(self.sess.codemap().def_span(stack[0].span),
&format!("the cycle begins when {}...", stack[0].query.describe(self)));

for &QueryInfo { span, ref query, .. } in &stack[1..] {
err.span_note(self.sess.codemap().def_span(span),
&format!("...which then requires {}...", query.describe(self)));
let span = fix_span(stack[1 % stack.len()].span, &stack[0].query);
let mut err = struct_span_err!(self.sess,
span,
E0391,
"cycle detected when {}",
stack[0].query.describe(self));

for i in 1..stack.len() {
let query = &stack[i].query;
let span = fix_span(stack[(i + 1) % stack.len()].span, query);
err.span_note(span, &format!("...which requires {}...", query.describe(self)));
}

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

if let Some((span, query)) = usage {
err.span_note(fix_span(span, &query),
&format!("cycle used when {}", query.describe(self)));
}

return err
})
}
Expand Down Expand Up @@ -266,6 +276,22 @@ macro_rules! define_maps {
r
}
}

// FIXME(eddyb) Get more valid Span's on queries.
pub fn default_span(&self, tcx: TyCtxt<'_, $tcx, '_>, span: Span) -> Span {
if span != DUMMY_SP {
return span;
}
// The def_span query is used to calculate default_span,
// so exit to avoid infinite recursion
match *self {
Query::def_span(..) => return span,
_ => ()
}
match *self {
$(Query::$name(key) => key.default_span(tcx),)*
}
}
}

pub mod queries {
Expand Down Expand Up @@ -303,7 +329,7 @@ macro_rules! define_maps {
/// If the query already executed and panicked, this will fatal error / silently panic
fn try_get_lock(
tcx: TyCtxt<'a, $tcx, 'lcx>,
mut span: Span,
span: Span,
key: &$K
) -> TryGetLock<'a, $tcx, $V, Self>
{
Expand All @@ -329,21 +355,14 @@ macro_rules! define_maps {
};
mem::drop(lock);

// This just matches the behavior of `try_get_with` so the span when
// we await matches the span we would use when executing.
// See the FIXME there.
if span == DUMMY_SP && stringify!($name) != "def_span" {
span = key.default_span(tcx);
}

if let Err(cycle) = job.await(tcx, span) {
return TryGetLock::JobCompleted(Err(cycle));
}
}
}

fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
mut span: Span,
span: Span,
key: $K)
-> Result<$V, CycleError<$tcx>>
{
Expand Down Expand Up @@ -377,18 +396,6 @@ macro_rules! define_maps {

let mut lock = get_lock_or_return!();

// FIXME(eddyb) Get more valid Span's on queries.
// def_span guard is necessary to prevent a recursive loop,
// default_span calls def_span query internally.
if span == DUMMY_SP && stringify!($name) != "def_span" {
// This might deadlock if we hold the map lock since we might be
// waiting for the def_span query and switch to some other fiber
// So we drop the lock here and reacquire it
mem::drop(lock);
span = key.default_span(tcx);
lock = get_lock_or_return!();
}

// Fast path for when incr. comp. is off. `to_dep_node` is
// expensive for some DepKinds.
if !tcx.dep_graph.is_fully_enabled() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#![feature(specialization)]

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

impl<T> Trait<T> for Vec<T> {
type Assoc = ();
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/const-size_of-cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern: cyclic dependency detected
// error-pattern: cycle detected

#![feature(const_fn)]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ trait Trait { type Item; }
struct A<T>
where T : Trait,
T : Add<T::Item>
//~^ ERROR cyclic dependency detected
//~^ ERROR cycle detected
//~| ERROR associated type `Item` not found for `T`
{
data: T
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/cycle-trait-default-type-trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// again references the trait.

trait Foo<X = Box<Foo>> {
//~^ ERROR cyclic dependency detected
//~^ ERROR cycle detected
}

fn main() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/cycle-trait-supertrait-direct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// Test a supertrait cycle where a trait extends itself.

trait Chromosome: Chromosome {
//~^ ERROR cyclic dependency detected
//~^ ERROR cycle detected
}

fn main() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/infinite-vec-type-recursion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
// except according to those terms.

type x = Vec<x>;
//~^ ERROR cyclic dependency detected
//~^ ERROR cycle detected

fn main() { let b: x = Vec::new(); }
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-20772.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.

trait T : Iterator<Item=Self::Item>
//~^ ERROR cyclic dependency detected
//~^ ERROR cycle detected
//~| ERROR associated type `Item` not found for `Self`
{}

Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-20825.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub trait Subscriber {
}

pub trait Processor: Subscriber<Input = Self::Input> {
//~^ ERROR cyclic dependency detected [E0391]
//~^ ERROR cycle detected
type Input;
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-21177.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ trait Trait {
}

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

fn main() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-22673.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.

trait Expr : PartialEq<Self::Item> {
//~^ ERROR: cyclic dependency detected
//~^ ERROR: cycle detected
type Item;
}

Expand Down
8 changes: 3 additions & 5 deletions src/test/compile-fail/issue-26548.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern: cyclic dependency detected
// note-pattern: the cycle begins when computing layout of
// note-pattern: ...which then requires computing layout of
// note-pattern: ...which then again requires computing layout of

// error-pattern: cycle detected when computing layout of
// note-pattern: ...which requires computing layout of
// note-pattern: ...which again requires computing layout of

trait Mirror { type It: ?Sized; }
impl<T: ?Sized> Mirror for T { type It = Self; }
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-34373.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ trait Trait<T> {
fn foo(_: T) {}
}

pub struct Foo<T = Box<Trait<DefaultFoo>>>;
type DefaultFoo = Foo; //~ ERROR cyclic dependency detected
pub struct Foo<T = Box<Trait<DefaultFoo>>>; //~ ERROR cycle detected
type DefaultFoo = Foo;

fn main() {
}
3 changes: 2 additions & 1 deletion src/test/compile-fail/issue-44415.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern: cycle detected when computing layout of

#![feature(const_fn)]
#![feature(core_intrinsics)]

use std::intrinsics;

struct Foo {
bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
//~^ ERROR cyclic dependency detected
x: usize,
}

Expand Down
10 changes: 5 additions & 5 deletions src/test/compile-fail/resolve-self-in-impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ impl Tr for S where Self: Copy {} // OK
impl Tr for S where S<Self>: Copy {} // OK
impl Tr for S where Self::A: Copy {} // OK

impl Tr for Self {} //~ ERROR cyclic dependency detected
impl Tr for S<Self> {} //~ ERROR cyclic dependency detected
impl Self {} //~ ERROR cyclic dependency detected
impl S<Self> {} //~ ERROR cyclic dependency detected
impl Tr<Self::A> for S {} //~ ERROR cyclic dependency detected
impl Tr for Self {} //~ ERROR cycle detected
impl Tr for S<Self> {} //~ ERROR cycle detected
impl Self {} //~ ERROR cycle detected
impl S<Self> {} //~ ERROR cycle detected
impl Tr<Self::A> for S {} //~ ERROR cycle detected

fn main() {}
3 changes: 1 addition & 2 deletions src/test/ui/cycle-trait-supertrait-indirect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ trait A: B {
}

trait B: C {
//~^ ERROR cycle detected
}

trait C: B { }
//~^ ERROR cyclic dependency detected
//~| cyclic reference

fn main() { }
22 changes: 11 additions & 11 deletions src/test/ui/cycle-trait-supertrait-indirect.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
error[E0391]: cyclic dependency detected
--> $DIR/cycle-trait-supertrait-indirect.rs:20:1
error[E0391]: cycle detected when computing the supertraits of `B`
--> $DIR/cycle-trait-supertrait-indirect.rs:17:1
|
LL | trait C: B { }
| ^^^^^^^^^^ cyclic reference
LL | trait B: C {
| ^^^^^^^^^^
|
note: the cycle begins when computing the supertraits of `B`...
--> $DIR/cycle-trait-supertrait-indirect.rs:14:1
note: ...which requires computing the supertraits of `C`...
--> $DIR/cycle-trait-supertrait-indirect.rs:21:1
|
LL | trait A: B {
LL | trait C: B { }
| ^^^^^^^^^^
note: ...which then requires computing the supertraits of `C`...
--> $DIR/cycle-trait-supertrait-indirect.rs:17:1
= note: ...which again requires computing the supertraits of `B`, completing the cycle
note: cycle used when computing the supertraits of `A`
--> $DIR/cycle-trait-supertrait-indirect.rs:14:1
|
LL | trait B: C {
LL | trait A: B {
| ^^^^^^^^^^
= note: ...which then again requires computing the supertraits of `B`, completing the cycle.

error: aborting due to previous error

Expand Down
3 changes: 1 addition & 2 deletions src/test/ui/impl-trait/auto-trait-leak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ fn after() -> impl Fn(i32) {
// independently resolved and only require the concrete
// return type, which can't depend on the obligation.
fn cycle1() -> impl Clone {
//~^ ERROR cyclic dependency detected
//~| cyclic reference
//~^ ERROR cycle detected
send(cycle2().clone());

Rc::new(Cell::new(5))
Expand Down
Loading

0 comments on commit b91e6a2

Please sign in to comment.