From c26d965714e38d62b1610780f67bec14dafe25c3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 29 Nov 2020 00:21:56 +0100 Subject: [PATCH] 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. --- compiler/rustc_query_impl/src/lib.rs | 2 +- compiler/rustc_query_impl/src/plumbing.rs | 62 ++----------------- .../rustc_query_system/src/query/config.rs | 10 +-- compiler/rustc_query_system/src/query/job.rs | 36 +++++++++++ .../rustc_query_system/src/query/plumbing.rs | 8 ++- 5 files changed, 54 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index bfba7c7410e..176c68cf0fc 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -18,7 +18,7 @@ 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; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 01fb5a7ba20..00392fbcf56 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -8,15 +8,13 @@ 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 @@ fn start_query( } 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 @@ fn hash_result( fn handle_cycle_error( tcx: QueryCtxt<'tcx>, - error: CycleError, + mut error: DiagnosticBuilder<'_>, ) -> Self::Value { handle_cycle_error!([$($modifiers)*][tcx, error]) } diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index d01b0de3b48..4e2515c3ac3 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -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 { pub compute: fn(CTX, K) -> V, pub hash_result: fn(&mut CTX::StableHashingContext, &V) -> Option, - 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, } @@ -52,8 +52,8 @@ pub(crate) fn hash_result( (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 @@ fn hash_result( result: &Self::Value, ) -> Option; - fn handle_cycle_error(tcx: CTX, error: CycleError) -> Self::Value; + fn handle_cycle_error(tcx: CTX, diag: DiagnosticBuilder<'_>) -> Self::Value; } pub trait QueryDescription: QueryAccessors { diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index cc3cefe46be..a30cd078d6c 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -2,6 +2,8 @@ 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(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 +} diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 28ee1a17994..0050670b338 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -6,7 +6,9 @@ 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 @@ fn try_start<'b, CTX>( &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 @@ fn try_start<'b, CTX>( 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 @@ fn drop(&mut self) { } #[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,