about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_error_messages/locales/en-US/query_system.ftl3
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs29
-rw-r--r--compiler/rustc_query_system/src/error.rs20
-rw-r--r--compiler/rustc_query_system/src/lib.rs2
-rw-r--r--compiler/rustc_query_system/src/query/job.rs21
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs6
6 files changed, 72 insertions, 9 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..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,3 +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}
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 6f39bbfc0dc..d819f4774d5 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;
@@ -109,7 +111,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.
@@ -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 3fb06cbedbd..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,5 +77,20 @@ pub struct IncrementCompilation {
 }
 
 #[derive(SessionDiagnostic)]
+#[help]
 #[diag(query_system::query_overflow)]
-pub struct QueryOverflow;
+pub struct QueryOverflow {
+    #[primary_span]
+    pub span: Option<Span>,
+    #[subdiagnostic]
+    pub layout_of_depth: Option<LayoutOfDepth>,
+    pub suggested_limit: Limit,
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[note(query_system::layout_of_depth)]
+pub struct LayoutOfDepth {
+    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 f92c3831f26..5987651322a 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 45b4079fb54..95305eabd0d 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,24 @@ impl QueryJobId {
 
         panic!("did not find a cycle")
     }
+
+    #[cold]
+    #[inline(never)]
+    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;
+
+        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..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,7 +123,5 @@ 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);
 }