diff --git a/Cargo.lock b/Cargo.lock index 741c51dcb3e7..3019ff581f37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4503,6 +4503,7 @@ dependencies = [ "rustc_middle", "rustc_query_system", "rustc_serialize", + "rustc_session", "rustc_span", "rustc_thread_pool", "tracing", diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index ee50ec073bc8..a8edc1129481 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -16,6 +16,7 @@ rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } +rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_thread_pool = { path = "../rustc_thread_pool" } tracing = "0.1" diff --git a/compiler/rustc_query_impl/src/error.rs b/compiler/rustc_query_impl/src/error.rs index b109172d8e49..6d3eb2950982 100644 --- a/compiler/rustc_query_impl/src/error.rs +++ b/compiler/rustc_query_impl/src/error.rs @@ -1,3 +1,4 @@ +use rustc_errors::codes::*; use rustc_hir::limit::Limit; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; @@ -22,3 +23,59 @@ pub(crate) struct QueryOverflowNote { pub desc: String, pub depth: usize, } + +#[derive(Subdiagnostic)] +#[note("...which requires {$desc}...")] +pub(crate) struct CycleStack { + #[primary_span] + pub span: Span, + pub desc: String, +} + +#[derive(Subdiagnostic)] +pub(crate) enum StackCount { + #[note("...which immediately requires {$stack_bottom} again")] + Single, + #[note("...which again requires {$stack_bottom}, completing the cycle")] + Multiple, +} + +#[derive(Subdiagnostic)] +pub(crate) enum Alias { + #[note("type aliases cannot be recursive")] + #[help("consider using a struct, enum, or union instead to break the cycle")] + #[help( + "see for more information" + )] + Ty, + #[note("trait aliases cannot be recursive")] + Trait, +} + +#[derive(Subdiagnostic)] +#[note("cycle used when {$usage}")] +pub(crate) struct CycleUsage { + #[primary_span] + pub span: Span, + pub usage: String, +} + +#[derive(Diagnostic)] +#[diag("cycle detected when {$stack_bottom}", code = E0391)] +pub(crate) struct Cycle { + #[primary_span] + pub span: Span, + pub stack_bottom: String, + #[subdiagnostic] + pub cycle_stack: Vec, + #[subdiagnostic] + pub stack_count: StackCount, + #[subdiagnostic] + pub alias: Option, + #[subdiagnostic] + pub cycle_usage: Option, + #[note( + "see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information" + )] + pub note_span: (), +} diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 6f16932cb2eb..d7e95d43ecaa 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -11,12 +11,11 @@ use rustc_query_system::query::{ ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryJob, QueryJobId, QueryLatch, QueryMode, QueryStackDeferred, QueryStackFrame, QueryState, incremental_verify_ich, - report_cycle, }; use rustc_span::{DUMMY_SP, Span}; use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; -use crate::job::{QueryJobInfo, QueryMap, find_cycle_in_stack}; +use crate::job::{QueryJobInfo, QueryMap, find_cycle_in_stack, report_cycle}; use crate::{QueryCtxt, QueryFlags, SemiDynamicQueryDispatcher}; #[inline] diff --git a/compiler/rustc_query_impl/src/job.rs b/compiler/rustc_query_impl/src/job.rs index cb0a13d32ad2..f1eba0f76d17 100644 --- a/compiler/rustc_query_impl/src/job.rs +++ b/compiler/rustc_query_impl/src/job.rs @@ -3,11 +3,13 @@ use std::sync::Arc; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::DiagCtxtHandle; +use rustc_errors::{Diag, DiagCtxtHandle}; +use rustc_hir::def::DefKind; use rustc_query_system::query::{ CycleError, QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryStackDeferred, QueryStackFrame, QueryWaiter, }; +use rustc_session::Session; use rustc_span::{DUMMY_SP, Span}; use crate::QueryCtxt; @@ -444,3 +446,55 @@ pub fn print_query_stack<'tcx>( } count_total } + +#[inline(never)] +#[cold] +pub(crate) fn report_cycle<'a>( + sess: &'a Session, + CycleError { usage, cycle: stack }: &CycleError, +) -> Diag<'a> { + assert!(!stack.is_empty()); + + let span = stack[0].frame.info.default_span(stack[1 % stack.len()].span); + + let mut cycle_stack = Vec::new(); + + use crate::error::StackCount; + let stack_count = if stack.len() == 1 { StackCount::Single } else { StackCount::Multiple }; + + for i in 1..stack.len() { + let frame = &stack[i].frame; + let span = frame.info.default_span(stack[(i + 1) % stack.len()].span); + cycle_stack + .push(crate::error::CycleStack { span, desc: frame.info.description.to_owned() }); + } + + let mut cycle_usage = None; + if let Some((span, ref query)) = *usage { + cycle_usage = Some(crate::error::CycleUsage { + span: query.info.default_span(span), + usage: query.info.description.to_string(), + }); + } + + let alias = + if stack.iter().all(|entry| matches!(entry.frame.info.def_kind, Some(DefKind::TyAlias))) { + Some(crate::error::Alias::Ty) + } else if stack.iter().all(|entry| entry.frame.info.def_kind == Some(DefKind::TraitAlias)) { + Some(crate::error::Alias::Trait) + } else { + None + }; + + let cycle_diag = crate::error::Cycle { + span, + cycle_stack, + stack_bottom: stack[0].frame.info.description.to_owned(), + alias, + cycle_usage, + stack_count, + note_span: (), + }; + + sess.dcx().create_err(cycle_diag) +} diff --git a/compiler/rustc_query_impl/src/values.rs b/compiler/rustc_query_impl/src/values.rs index 2fe3808f3d6e..783e7a10d12a 100644 --- a/compiler/rustc_query_impl/src/values.rs +++ b/compiler/rustc_query_impl/src/values.rs @@ -11,10 +11,12 @@ use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::ty::{self, Representability, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; -use rustc_query_system::query::{CycleError, report_cycle}; +use rustc_query_system::query::CycleError; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span}; +use crate::job::report_cycle; + pub(crate) trait Value<'tcx>: Sized { fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> Self; diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs index adce85bf31be..f48afe6f75fa 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_system/src/error.rs @@ -1,62 +1,4 @@ -use rustc_errors::codes::*; -use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_span::Span; - -#[derive(Subdiagnostic)] -#[note("...which requires {$desc}...")] -pub(crate) struct CycleStack { - #[primary_span] - pub span: Span, - pub desc: String, -} - -#[derive(Subdiagnostic)] -pub(crate) enum StackCount { - #[note("...which immediately requires {$stack_bottom} again")] - Single, - #[note("...which again requires {$stack_bottom}, completing the cycle")] - Multiple, -} - -#[derive(Subdiagnostic)] -pub(crate) enum Alias { - #[note("type aliases cannot be recursive")] - #[help("consider using a struct, enum, or union instead to break the cycle")] - #[help( - "see for more information" - )] - Ty, - #[note("trait aliases cannot be recursive")] - Trait, -} - -#[derive(Subdiagnostic)] -#[note("cycle used when {$usage}")] -pub(crate) struct CycleUsage { - #[primary_span] - pub span: Span, - pub usage: String, -} - -#[derive(Diagnostic)] -#[diag("cycle detected when {$stack_bottom}", code = E0391)] -pub(crate) struct Cycle { - #[primary_span] - pub span: Span, - pub stack_bottom: String, - #[subdiagnostic] - pub cycle_stack: Vec, - #[subdiagnostic] - pub stack_count: StackCount, - #[subdiagnostic] - pub alias: Option, - #[subdiagnostic] - pub cycle_usage: Option, - #[note( - "see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information" - )] - pub note_span: (), -} +use rustc_macros::Diagnostic; #[derive(Diagnostic)] #[diag("internal compiler error: reentrant incremental verify failure, suppressing message")] diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index e8acb8064f7e..7349fe223ef9 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -4,13 +4,9 @@ use std::sync::Arc; use parking_lot::{Condvar, Mutex}; -use rustc_errors::Diag; -use rustc_hir::def::DefKind; -use rustc_session::Session; use rustc_span::Span; use super::{QueryStackDeferred, QueryStackFrameExtra}; -use crate::error::CycleStack; use crate::query::plumbing::CycleError; use crate::query::{QueryContext, QueryStackFrame}; @@ -163,54 +159,3 @@ pub fn extract_waiter(&self, waiter: usize) -> Arc> { info.waiters.remove(waiter) } } - -#[inline(never)] -#[cold] -pub fn report_cycle<'a>( - sess: &'a Session, - CycleError { usage, cycle: stack }: &CycleError, -) -> Diag<'a> { - assert!(!stack.is_empty()); - - let span = stack[0].frame.info.default_span(stack[1 % stack.len()].span); - - let mut cycle_stack = Vec::new(); - - use crate::error::StackCount; - let stack_count = if stack.len() == 1 { StackCount::Single } else { StackCount::Multiple }; - - for i in 1..stack.len() { - let frame = &stack[i].frame; - let span = frame.info.default_span(stack[(i + 1) % stack.len()].span); - cycle_stack.push(CycleStack { span, desc: frame.info.description.to_owned() }); - } - - let mut cycle_usage = None; - if let Some((span, ref query)) = *usage { - cycle_usage = Some(crate::error::CycleUsage { - span: query.info.default_span(span), - usage: query.info.description.to_string(), - }); - } - - let alias = - if stack.iter().all(|entry| matches!(entry.frame.info.def_kind, Some(DefKind::TyAlias))) { - Some(crate::error::Alias::Ty) - } else if stack.iter().all(|entry| entry.frame.info.def_kind == Some(DefKind::TraitAlias)) { - Some(crate::error::Alias::Trait) - } else { - None - }; - - let cycle_diag = crate::error::Cycle { - span, - cycle_stack, - stack_bottom: stack[0].frame.info.description.to_owned(), - alias, - cycle_usage, - stack_count, - note_span: (), - }; - - sess.dcx().create_err(cycle_diag) -} diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 6067f7dafd5c..c33af941f802 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -15,7 +15,7 @@ pub use self::caches::{ DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, }; -pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter, report_cycle}; +pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter}; pub use self::plumbing::*; use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};