diff --git a/compiler/rustc_error_messages/locales/en-US/query_system.ftl b/compiler/rustc_error_messages/locales/en-US/query_system.ftl index 167704e46c0..050a41fc7f9 100644 --- a/compiler/rustc_error_messages/locales/en-US/query_system.ftl +++ b/compiler/rustc_error_messages/locales/en-US/query_system.ftl @@ -23,3 +23,5 @@ query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive query_system_cycle_which_requires = ...which requires {$desc}... query_system_query_overflow = queries overflow the depth limit! + +query_system_layout_of_depth = Query depth increased by {$depth} when {$desc}! diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 6fb3c69b1f4..3ca657cbca1 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -109,7 +109,7 @@ impl QueryContext for QueryCtxt<'_> { // when accessing the `ImplicitCtxt`. tls::with_related_context(**self, move |current_icx| { if depth_limit && !self.recursion_limit().value_within_limit(current_icx.query_depth) { - self.depth_limit_error(); + self.depth_limit_error(token); } // Update the `ImplicitCtxt` to point to our new query job. diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs index 3fb06cbedbd..5f57a1510aa 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_system/src/error.rs @@ -77,4 +77,16 @@ pub struct IncrementCompilation { #[derive(SessionDiagnostic)] #[diag(query_system::query_overflow)] -pub struct QueryOverflow; +pub struct QueryOverflow { + #[subdiagnostic] + pub layout_of_depth: Option, +} + +#[derive(SessionSubdiagnostic)] +#[note(query_system::layout_of_depth)] +pub struct LayoutOfDepth { + #[primary_span] + pub span: Span, + pub desc: String, + pub depth: usize, +} diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 45b4079fb54..a5ea3a098a6 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -59,6 +59,7 @@ impl QueryJobId { } } +#[derive(Clone)] pub struct QueryJobInfo { pub query: QueryStackFrame, pub job: QueryJob, @@ -116,10 +117,10 @@ impl QueryJob { } } -#[cfg(not(parallel_compiler))] impl QueryJobId { #[cold] #[inline(never)] + #[cfg(not(parallel_compiler))] pub(super) fn find_cycle_in_stack( &self, query_map: QueryMap, @@ -156,6 +157,27 @@ impl QueryJobId { panic!("did not find a cycle") } + + #[cold] + #[inline(never)] + pub(super) fn try_find_layout_root( + &self, + query_map: QueryMap, + ) -> Option<(QueryJobInfo, usize)> { + let mut last_layout = None; + let mut current_id = Some(*self); + let mut depth = 0; + + while let Some(id) = current_id { + let info = query_map.get(&id).unwrap(); + if info.query.name == "layout_of" { + depth += 1; + last_layout = Some((info.clone(), depth)); + } + current_id = info.job.parent; + } + last_layout + } } #[cfg(parallel_compiler)] diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 0b07bb64b6a..e29e8815331 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -123,7 +123,18 @@ pub trait QueryContext: HasDepContext { compute: impl FnOnce() -> R, ) -> R; - fn depth_limit_error(&self) { - self.dep_context().sess().emit_fatal(crate::error::QueryOverflow); + fn depth_limit_error(&self, job: QueryJobId) { + let sess = self.dep_context().sess(); + let mut layout_of_depth = None; + if let Some(map) = self.try_collect_active_jobs() { + if let Some((info, depth)) = job.try_find_layout_root(map) { + layout_of_depth = Some(crate::error::LayoutOfDepth { + span: info.job.span, + desc: info.query.description, + depth, + }); + } + } + sess.emit_fatal(crate::error::QueryOverflow { layout_of_depth }); } }