diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_query_impl/src/keys.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_query_impl/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_query_impl/src/plumbing.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_query_impl/src/util.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_query_system/src/query/job.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_query_system/src/query/mod.rs | 29 |
6 files changed, 81 insertions, 2 deletions
diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 38ab26d66ac..40b820c8d8e 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -20,6 +20,12 @@ pub trait Key { /// In the event that a cycle occurs, if no explicit span has been /// given for a query with key `self`, what span should we use? fn default_span(&self, tcx: TyCtxt<'_>) -> Span; + + /// If the key is a [`DefId`] or `DefId`--equivalent, return that `DefId`. + /// Otherwise, return `None`. + fn key_as_def_id(&self) -> Option<DefId> { + None + } } impl Key for () { @@ -95,6 +101,9 @@ impl Key for LocalDefId { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.to_def_id().default_span(tcx) } + fn key_as_def_id(&self) -> Option<DefId> { + Some(self.to_def_id()) + } } impl Key for DefId { @@ -105,6 +114,10 @@ impl Key for DefId { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(*self) } + #[inline(always)] + fn key_as_def_id(&self) -> Option<DefId> { + Some(*self) + } } impl Key for ty::WithOptConstParam<LocalDefId> { diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 5022bf26532..bb0e6511159 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -51,6 +51,8 @@ pub use on_disk_cache::OnDiskCache; mod profiling_support; pub use self::profiling_support::alloc_self_profile_query_strings; +mod util; + rustc_query_append! { [define_queries!][<'tcx>] } impl<'tcx> Queries<'tcx> { diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 5774d021373..476085c8725 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -337,6 +337,11 @@ macro_rules! define_queries { } else { Some(key.default_span(*tcx)) }; + let def_id = key.key_as_def_id(); + let def_kind = def_id.map(|def_id| { + let def_kind = tcx.def_kind(def_id); + $crate::util::def_kind_to_simple_def_kind(def_kind) + }); let hash = || { let mut hcx = tcx.create_stable_hashing_context(); let mut hasher = StableHasher::new(); @@ -345,7 +350,7 @@ macro_rules! define_queries { hasher.finish::<u64>() }; - QueryStackFrame::new(name, description, span, hash) + QueryStackFrame::new(name, description, span, def_kind, hash) })* } diff --git a/compiler/rustc_query_impl/src/util.rs b/compiler/rustc_query_impl/src/util.rs new file mode 100644 index 00000000000..517c107b5d9 --- /dev/null +++ b/compiler/rustc_query_impl/src/util.rs @@ -0,0 +1,18 @@ +use rustc_hir::def::DefKind; +use rustc_query_system::query::SimpleDefKind; + +/// Convert a [`DefKind`] to a [`SimpleDefKind`]. +/// +/// *See [`SimpleDefKind`]'s docs for more information.* +pub(crate) fn def_kind_to_simple_def_kind(def_kind: DefKind) -> SimpleDefKind { + match def_kind { + DefKind::Struct => SimpleDefKind::Struct, + DefKind::Enum => SimpleDefKind::Enum, + DefKind::Union => SimpleDefKind::Union, + DefKind::Trait => SimpleDefKind::Trait, + DefKind::TyAlias => SimpleDefKind::TyAlias, + DefKind::TraitAlias => SimpleDefKind::TraitAlias, + + _ => SimpleDefKind::Other, + } +} diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index b7ac42546dd..f8ba0babab0 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -1,6 +1,6 @@ use crate::dep_graph::DepContext; use crate::query::plumbing::CycleError; -use crate::query::{QueryContext, QueryStackFrame}; +use crate::query::{QueryContext, QueryStackFrame, SimpleDefKind}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, Handler, Level}; @@ -600,6 +600,18 @@ pub(crate) fn report_cycle<'a>( )); } + if !stack.is_empty() + && stack.iter().all(|entry| { + entry.query.def_kind.map_or(false, |def_kind| { + matches!(def_kind, SimpleDefKind::TyAlias | SimpleDefKind::TraitAlias) + }) + }) + { + err.note("type aliases cannot be recursive"); + err.help("consider using a struct, enum, or union instead to break the cycle"); + err.help("see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information"); + } + if let Some((span, query)) = usage { err.span_note(fix_span(span, &query), &format!("cycle used when {}", query.description)); } diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 7288aaef8f2..dffe7f3689f 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -29,24 +29,53 @@ pub struct QueryStackFrame { pub name: &'static str, pub description: String, span: Option<Span>, + /// The `DefKind` this query frame is associated with, if applicable. + /// + /// We can't use `rustc_hir::def::DefKind` because `rustc_hir` is not + /// available in `rustc_query_system`. Instead, we have a simplified + /// custom version of it, called [`SimpleDefKind`]. + def_kind: Option<SimpleDefKind>, /// This hash is used to deterministically pick /// a query to remove cycles in the parallel compiler. #[cfg(parallel_compiler)] hash: u64, } +/// A simplified version of `rustc_hir::def::DefKind`. +/// +/// It was added to help improve cycle errors caused by recursive type aliases. +/// As of August 2021, `rustc_query_system` cannot depend on `rustc_hir` +/// because it would create a dependency cycle. So, instead, a simplified +/// version of `DefKind` was added to `rustc_query_system`. +/// +/// `DefKind`s are converted to `SimpleDefKind`s in `rustc_query_impl`. +#[derive(Debug, Copy, Clone)] +pub enum SimpleDefKind { + Struct, + Enum, + Union, + Trait, + TyAlias, + TraitAlias, + + // FIXME: add more from `rustc_hir::def::DefKind` and then remove `Other` + Other, +} + impl QueryStackFrame { #[inline] pub fn new( name: &'static str, description: String, span: Option<Span>, + def_kind: Option<SimpleDefKind>, _hash: impl FnOnce() -> u64, ) -> Self { Self { name, description, span, + def_kind, #[cfg(parallel_compiler)] hash: _hash(), } |
