Move report_cycle to rustc_query_system.

The call to `ty::print::with_forced_impl_filename_line`
is done when constructing the description,
at the construction of the QueryStackFrame.
This commit is contained in:
Camille GILLOT 2020-11-29 00:21:56 +01:00
parent 3897395787
commit c26d965714
5 changed files with 54 additions and 64 deletions

View File

@ -18,7 +18,7 @@ extern crate tracing;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::{Diagnostic, Handler, Level};
use rustc_errors::{Diagnostic, DiagnosticBuilder, Handler, Level};
use rustc_hir::def_id::CrateNum;
use rustc_index::vec::IndexVec;
use rustc_middle::dep_graph;

View File

@ -8,15 +8,13 @@ use rustc_middle::ty::query::on_disk_cache;
use rustc_middle::ty::tls::{self, ImplicitCtxt};
use rustc_middle::ty::{self, TyCtxt};
use rustc_query_system::dep_graph::HasDepContext;
use rustc_query_system::query::{CycleError, QueryJobId};
use rustc_query_system::query::{QueryContext, QueryDescription, QueryMap, QueryStackFrame};
use rustc_query_system::query::{QueryContext, QueryDescription, QueryJobId, QueryMap};
use rustc_data_structures::sync::Lock;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder};
use rustc_errors::Diagnostic;
use rustc_serialize::opaque;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::Span;
#[derive(Copy, Clone)]
pub struct QueryCtxt<'tcx> {
@ -175,54 +173,6 @@ impl QueryContext for QueryCtxt<'tcx> {
}
impl<'tcx> QueryCtxt<'tcx> {
#[inline(never)]
#[cold]
pub(super) fn report_cycle(
self,
CycleError { usage, cycle: stack }: CycleError,
) -> DiagnosticBuilder<'tcx> {
assert!(!stack.is_empty());
let fix_span = |span: Span, query: &QueryStackFrame| {
self.sess.source_map().guess_head_span(query.default_span(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.)
ty::print::with_forced_impl_filename_line(|| {
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.description
);
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.description));
}
err.note(&format!(
"...which again requires {}, completing the cycle",
stack[0].query.description
));
if let Some((span, query)) = usage {
err.span_note(
fix_span(span, &query),
&format!("cycle used when {}", query.description),
);
}
err
})
}
pub(super) fn encode_query_results(
self,
encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>,
@ -302,16 +252,16 @@ pub struct QueryStruct {
macro_rules! handle_cycle_error {
([][$tcx: expr, $error:expr]) => {{
$tcx.report_cycle($error).emit();
$error.emit();
Value::from_cycle_error($tcx)
}};
([fatal_cycle $($rest:tt)*][$tcx:expr, $error:expr]) => {{
$tcx.report_cycle($error).emit();
$error.emit();
$tcx.sess.abort_if_errors();
unreachable!()
}};
([cycle_delay_bug $($rest:tt)*][$tcx:expr, $error:expr]) => {{
$tcx.report_cycle($error).delay_as_bug();
$error.delay_as_bug();
Value::from_cycle_error($tcx)
}};
([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => {
@ -459,7 +409,7 @@ macro_rules! define_queries {
fn handle_cycle_error(
tcx: QueryCtxt<'tcx>,
error: CycleError,
mut error: DiagnosticBuilder<'_>,
) -> Self::Value {
handle_cycle_error!([$($modifiers)*][tcx, error])
}

View File

@ -3,10 +3,10 @@
use crate::dep_graph::DepNode;
use crate::dep_graph::SerializedDepNodeIndex;
use crate::query::caches::QueryCache;
use crate::query::plumbing::CycleError;
use crate::query::{QueryCacheStore, QueryContext, QueryState};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_errors::DiagnosticBuilder;
use std::fmt::Debug;
use std::hash::Hash;
@ -27,7 +27,7 @@ pub(crate) struct QueryVtable<CTX: QueryContext, K, V> {
pub compute: fn(CTX, K) -> V,
pub hash_result: fn(&mut CTX::StableHashingContext, &V) -> Option<Fingerprint>,
pub handle_cycle_error: fn(CTX, CycleError) -> V,
pub handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V,
pub cache_on_disk: fn(CTX, &K, Option<&V>) -> bool,
pub try_load_from_disk: fn(CTX, SerializedDepNodeIndex) -> Option<V>,
}
@ -52,8 +52,8 @@ impl<CTX: QueryContext, K, V> QueryVtable<CTX, K, V> {
(self.hash_result)(hcx, value)
}
pub(crate) fn handle_cycle_error(&self, tcx: CTX, error: CycleError) -> V {
(self.handle_cycle_error)(tcx, error)
pub(crate) fn handle_cycle_error(&self, tcx: CTX, diag: DiagnosticBuilder<'_>) -> V {
(self.handle_cycle_error)(tcx, diag)
}
pub(crate) fn cache_on_disk(&self, tcx: CTX, key: &K, value: Option<&V>) -> bool {
@ -90,7 +90,7 @@ pub trait QueryAccessors<CTX: QueryContext>: QueryConfig {
result: &Self::Value,
) -> Option<Fingerprint>;
fn handle_cycle_error(tcx: CTX, error: CycleError) -> Self::Value;
fn handle_cycle_error(tcx: CTX, diag: DiagnosticBuilder<'_>) -> Self::Value;
}
pub trait QueryDescription<CTX: QueryContext>: QueryAccessors<CTX> {

View File

@ -2,6 +2,8 @@ use crate::query::plumbing::CycleError;
use crate::query::QueryStackFrame;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{struct_span_err, DiagnosticBuilder};
use rustc_session::Session;
use rustc_span::Span;
use std::convert::TryFrom;
@ -590,3 +592,37 @@ pub fn deadlock<CTX: QueryContext>(tcx: CTX, registry: &rayon_core::Registry) {
on_panic.disable();
}
#[inline(never)]
#[cold]
pub(crate) fn report_cycle<'a>(
sess: &'a Session,
CycleError { usage, cycle: stack }: CycleError,
) -> DiagnosticBuilder<'a> {
assert!(!stack.is_empty());
let fix_span = |span: Span, query: &QueryStackFrame| {
sess.source_map().guess_head_span(query.default_span(span))
};
let span = fix_span(stack[1 % stack.len()].span, &stack[0].query);
let mut err =
struct_span_err!(sess, span, E0391, "cycle detected when {}", stack[0].query.description);
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.description));
}
err.note(&format!(
"...which again requires {}, completing the cycle",
stack[0].query.description
));
if let Some((span, query)) = usage {
err.span_note(fix_span(span, &query), &format!("cycle used when {}", query.description));
}
err
}

View File

@ -6,7 +6,9 @@ use crate::dep_graph::{DepContext, DepKind, DepNode};
use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
use crate::query::caches::QueryCache;
use crate::query::config::{QueryDescription, QueryVtable, QueryVtableExt};
use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryShardJobId};
use crate::query::job::{
report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryShardJobId,
};
use crate::query::{QueryContext, QueryMap, QueryStackFrame};
#[cfg(not(parallel_compiler))]
@ -245,6 +247,7 @@ where
&tcx.current_query_job(),
span,
);
let error = report_cycle(tcx.dep_context().sess(), error);
let value = query.handle_cycle_error(tcx, error);
cache.cache.store_nocache(value)
}));
@ -256,6 +259,7 @@ where
let result = latch.wait_on(tcx.current_query_job(), span);
if let Err(cycle) = result {
let cycle = report_cycle(tcx.dep_context().sess(), cycle);
let value = query.handle_cycle_error(tcx, cycle);
let value = cache.cache.store_nocache(value);
return TryGetJob::Cycle(value);
@ -352,7 +356,7 @@ where
}
#[derive(Clone)]
pub struct CycleError {
pub(crate) struct CycleError {
/// The query and related span that uses the cycle.
pub usage: Option<(Span, QueryStackFrame)>,
pub cycle: Vec<QueryInfo>,