From 44506f38e079caec1b6c14e05a9b86e19544757f Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Wed, 14 Sep 2022 21:00:00 +0800 Subject: [PATCH 1/2] add note for `layout_of` when query depth overflows --- .../locales/en-US/query_system.ftl | 2 ++ compiler/rustc_query_impl/src/plumbing.rs | 2 +- compiler/rustc_query_system/src/error.rs | 14 ++++++++++- compiler/rustc_query_system/src/query/job.rs | 24 ++++++++++++++++++- compiler/rustc_query_system/src/query/mod.rs | 15 ++++++++++-- 5 files changed, 52 insertions(+), 5 deletions(-) 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 }); } } From 89fd6ae458c96f7c3be00d93861ed3f0aa53d95b Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Thu, 15 Sep 2022 15:45:17 +0800 Subject: [PATCH 2/2] correct span, add help message and add UI test when query depth overflows --- .../locales/en-US/query_system.ftl | 3 +- compiler/rustc_query_impl/src/plumbing.rs | 27 +++++++++++++++- compiler/rustc_query_system/src/error.rs | 10 ++++-- compiler/rustc_query_system/src/lib.rs | 2 ++ compiler/rustc_query_system/src/query/job.rs | 5 +-- compiler/rustc_query_system/src/query/mod.rs | 17 ++-------- src/test/ui/query-system/query_depth.rs | 31 +++++++++++++++++++ src/test/ui/query-system/query_depth.stderr | 11 +++++++ 8 files changed, 82 insertions(+), 24 deletions(-) create mode 100644 src/test/ui/query-system/query_depth.rs create mode 100644 src/test/ui/query-system/query_depth.stderr 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 050a41fc7f9..b914ba52a73 100644 --- a/compiler/rustc_error_messages/locales/en-US/query_system.ftl +++ b/compiler/rustc_error_messages/locales/en-US/query_system.ftl @@ -23,5 +23,6 @@ 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! + .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) -query_system_layout_of_depth = Query depth increased by {$depth} when {$desc}! +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 3ca657cbca1..b9edb757b56 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -19,8 +19,10 @@ use rustc_query_system::query::{ force_query, QueryConfig, QueryContext, QueryDescription, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame, }; -use rustc_query_system::Value; +use rustc_query_system::{LayoutOfDepth, QueryOverflow, Value}; use rustc_serialize::Decodable; +use rustc_session::Limit; +use rustc_span::def_id::LOCAL_CRATE; use std::any::Any; use std::num::NonZeroU64; use thin_vec::ThinVec; @@ -127,6 +129,29 @@ impl QueryContext for QueryCtxt<'_> { }) }) } + + fn depth_limit_error(&self, job: QueryJobId) { + let mut span = None; + 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) { + span = Some(info.job.span); + layout_of_depth = Some(LayoutOfDepth { desc: info.query.description, depth }); + } + } + + let suggested_limit = match self.recursion_limit() { + Limit(0) => Limit(2), + limit => limit * 2, + }; + + self.sess.emit_fatal(QueryOverflow { + span, + layout_of_depth, + suggested_limit, + crate_name: self.crate_name(LOCAL_CRATE), + }); + } } impl<'tcx> QueryCtxt<'tcx> { diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs index 5f57a1510aa..bececca7585 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_system/src/error.rs @@ -1,5 +1,6 @@ use rustc_errors::AddSubdiagnostic; -use rustc_span::Span; +use rustc_session::Limit; +use rustc_span::{Span, Symbol}; pub struct CycleStack { pub span: Span, @@ -76,17 +77,20 @@ pub struct IncrementCompilation { } #[derive(SessionDiagnostic)] +#[help] #[diag(query_system::query_overflow)] pub struct QueryOverflow { + #[primary_span] + pub span: Option, #[subdiagnostic] pub layout_of_depth: Option, + pub suggested_limit: Limit, + pub crate_name: Symbol, } #[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/lib.rs b/compiler/rustc_query_system/src/lib.rs index 8a88b5c3340..78b06f520a8 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -23,4 +23,6 @@ pub mod query; mod values; pub use error::HandleCycleError; +pub use error::LayoutOfDepth; +pub use error::QueryOverflow; pub use values::Value; diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index a5ea3a098a6..95305eabd0d 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -160,10 +160,7 @@ impl QueryJobId { #[cold] #[inline(never)] - pub(super) fn try_find_layout_root( - &self, - query_map: QueryMap, - ) -> Option<(QueryJobInfo, usize)> { + pub 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; diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index e29e8815331..7a96c53b604 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -14,7 +14,7 @@ pub use self::caches::{ mod config; pub use self::config::{QueryConfig, QueryDescription, QueryVTable}; -use crate::dep_graph::{DepContext, DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; +use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; use rustc_data_structures::sync::Lock; use rustc_errors::Diagnostic; use rustc_hir::def::DefKind; @@ -123,18 +123,5 @@ pub trait QueryContext: HasDepContext { compute: impl FnOnce() -> R, ) -> R; - 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 }); - } + fn depth_limit_error(&self, job: QueryJobId); } diff --git a/src/test/ui/query-system/query_depth.rs b/src/test/ui/query-system/query_depth.rs new file mode 100644 index 00000000000..e600c1c08e5 --- /dev/null +++ b/src/test/ui/query-system/query_depth.rs @@ -0,0 +1,31 @@ +// build-fail + +#![recursion_limit = "64"] +type Byte = Option + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> +>>>> >>>>; + +fn main() { +//~^ ERROR: queries overflow the depth limit! + println!("{}", std::mem::size_of::()); +} diff --git a/src/test/ui/query-system/query_depth.stderr b/src/test/ui/query-system/query_depth.stderr new file mode 100644 index 00000000000..43a18b4e074 --- /dev/null +++ b/src/test/ui/query-system/query_depth.stderr @@ -0,0 +1,11 @@ +error: queries overflow the depth limit! + --> $DIR/query_depth.rs:28:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "128"]` attribute to your crate (`query_depth`) + = note: query depth increased by 66 when computing layout of `core::option::Option>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + +error: aborting due to previous error +