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_system/src/query/job.rs | 14 +++++++++++++- compiler/rustc_query_system/src/query/mod.rs | 29 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) (limited to 'compiler/rustc_query_system') 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 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, + /// 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, /// 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, + def_kind: Option, _hash: impl FnOnce() -> u64, ) -> Self { Self { name, description, span, + def_kind, #[cfg(parallel_compiler)] hash: _hash(), } -- cgit 1.4.1-3-g733a5