From cd0fc444fb0edb4df0bd8091706d3819313a9df4 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Thu, 19 Aug 2021 20:30:33 -0700 Subject: Note that type aliases cannot be recursive --- compiler/rustc_query_impl/src/keys.rs | 13 +++++++++++++ compiler/rustc_query_impl/src/lib.rs | 2 ++ compiler/rustc_query_impl/src/plumbing.rs | 7 ++++++- compiler/rustc_query_impl/src/util.rs | 18 ++++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_query_impl/src/util.rs (limited to 'compiler/rustc_query_impl/src') 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 { + 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 { + 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 { + Some(*self) + } } impl Key for ty::WithOptConstParam { 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::() }; - 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, + } +} -- cgit 1.4.1-3-g733a5 From c8619647359903a707891e7d40f68264d1e6ed94 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sat, 21 Aug 2021 14:19:59 -0700 Subject: Note that trait aliases cannot be recursive --- compiler/rustc_query_impl/src/keys.rs | 4 ++++ compiler/rustc_query_system/src/query/job.rs | 25 ++++++++++++++-------- .../infinite/infinite-trait-alias-recursion.stderr | 1 + 3 files changed, 21 insertions(+), 9 deletions(-) (limited to 'compiler/rustc_query_impl/src') diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 40b820c8d8e..88ab7597eac 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -178,6 +178,10 @@ impl Key for (DefId, Option) { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.0) } + #[inline(always)] + fn key_as_def_id(&self) -> Option { + Some(self.0) + } } impl Key for (DefId, LocalDefId, Ident) { diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index f8ba0babab0..63a8f062475 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -600,16 +600,23 @@ 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) - }) + if 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 for more information"); + }) { + if stack.iter().all(|entry| { + entry + .query + .def_kind + .map_or(false, |def_kind| matches!(def_kind, SimpleDefKind::TyAlias)) + }) { + err.note("type aliases cannot be recursive"); + err.help("consider using a struct, enum, or union instead to break the cycle"); + err.help("see for more information"); + } else { + err.note("trait aliases cannot be recursive"); + } } if let Some((span, query)) = usage { diff --git a/src/test/ui/infinite/infinite-trait-alias-recursion.stderr b/src/test/ui/infinite/infinite-trait-alias-recursion.stderr index c8e67740d79..5ecaedb3cb2 100644 --- a/src/test/ui/infinite/infinite-trait-alias-recursion.stderr +++ b/src/test/ui/infinite/infinite-trait-alias-recursion.stderr @@ -30,6 +30,7 @@ note: ...which requires computing the super traits of `T3`... LL | trait T3 = T1 + T3; | ^^ = note: ...which again requires computing the super predicates of `T1`, completing the cycle + = note: trait aliases cannot be recursive note: cycle used when collecting item types in top-level module --> $DIR/infinite-trait-alias-recursion.rs:3:1 | -- cgit 1.4.1-3-g733a5 From d96234bed72e1935d8ab9a0c7a7e70027c86ad77 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sun, 29 Aug 2021 19:02:47 -0700 Subject: Retrieve `DefKind` from HIR map to reduce chance of cycles `tcx.def_kind()` could theoretically invoke another query, which could cause an infinite query loop. Accessing the HIR map directly makes that less likely to happen. I also changed it to use `as_local()` (`tcx.def_kind()` seems to implicitly call `expect_local()`) and `opt_def_kind()` to reduce the chance of panicking on valid code. --- compiler/rustc_query_impl/src/plumbing.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'compiler/rustc_query_impl/src') diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 476085c8725..90a6ba474b4 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -338,10 +338,12 @@ macro_rules! define_queries { 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 def_kind = def_id + .and_then(|def_id| def_id.as_local()) + // Use `tcx.hir().opt_def_kind()` to reduce the chance of + // accidentally triggering an infinite query loop. + .and_then(|def_id| tcx.hir().opt_def_kind(def_id)) + .map(|def_kind| $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(); -- cgit 1.4.1-3-g733a5