diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index ed5951fe1c034..a0c5b38d01362 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -143,7 +143,6 @@ struct QueryModifiers { anon: Option, arena_cache: Option, cache_on_disk_if: Option, - cycle_delay_bug: Option, depth_limit: Option, desc: Desc, eval_always: Option, @@ -157,7 +156,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { let mut arena_cache = None; let mut cache_on_disk_if = None; let mut desc = None; - let mut cycle_delay_bug = None; let mut no_hash = None; let mut anon = None; let mut eval_always = None; @@ -191,8 +189,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, block }); } else if modifier == "arena_cache" { try_insert!(arena_cache = modifier); - } else if modifier == "cycle_delay_bug" { - try_insert!(cycle_delay_bug = modifier); } else if modifier == "no_hash" { try_insert!(no_hash = modifier); } else if modifier == "anon" { @@ -216,7 +212,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { arena_cache, cache_on_disk_if, desc, - cycle_delay_bug, no_hash, anon, eval_always, @@ -251,7 +246,6 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { anon, arena_cache, cache_on_disk_if, - cycle_delay_bug, depth_limit, desc: _, eval_always, @@ -264,13 +258,6 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { let anon = anon.is_some(); let arena_cache = arena_cache.is_some(); let cache_on_disk = cache_on_disk_if.is_some(); - - let cycle_error_handling = if cycle_delay_bug.is_some() { - quote! { DelayBug } - } else { - quote! { Error } - }; - let depth_limit = depth_limit.is_some(); let eval_always = eval_always.is_some(); let feedable = feedable.is_some(); @@ -289,7 +276,6 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { anon: #anon, arena_cache: #arena_cache, cache_on_disk: #cache_on_disk, - cycle_error_handling: #cycle_error_handling, depth_limit: #depth_limit, eval_always: #eval_always, feedable: #feedable, @@ -402,7 +388,6 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke doc_link!( arena_cache, - cycle_delay_bug, no_hash, anon, eval_always, diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index d4d9b9c0189d9..6c30762725b77 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -564,13 +564,13 @@ rustc_queries! { } /// Checks whether a type is representable or infinitely sized - query check_representability(key: LocalDefId) -> rustc_middle::ty::Representability { + // + // Infinitely sized types will cause a cycle. The `value_from_cycle_error` impl will print + // a custom error about the infinite size and then abort compilation. (In the past we + // recovered and continued, but in practice that leads to confusing subsequent error + // messages about cycles that then abort.) + query check_representability(key: LocalDefId) { desc { "checking if `{}` is representable", tcx.def_path_str(key) } - // Infinitely sized types will cause a cycle. The custom `FromCycleError` impl for - // `Representability` will print a custom error about the infinite size and then abort - // compilation. (In the past we recovered and continued, but in practice that leads to - // confusing subsequent error messages about cycles that then abort.) - cycle_delay_bug // We don't want recursive representability calls to be forced with // incremental compilation because, if a cycle occurs, we need the // entire cycle to be in memory for diagnostics. This means we can't @@ -580,9 +580,8 @@ rustc_queries! { /// An implementation detail for the `check_representability` query. See that query for more /// details, particularly on the modifiers. - query check_representability_adt_ty(key: Ty<'tcx>) -> rustc_middle::ty::Representability { + query check_representability_adt_ty(key: Ty<'tcx>) { desc { "checking if `{}` is representable", key } - cycle_delay_bug anon } @@ -1027,7 +1026,6 @@ rustc_queries! { desc { "computing the variances of `{}`", tcx.def_path_str(def_id) } cache_on_disk_if { def_id.is_local() } separate_provide_extern - cycle_delay_bug } /// Gets a map with the inferred outlives-predicates of every item in the local crate. @@ -1160,7 +1158,6 @@ rustc_queries! { desc { "computing function signature of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern - cycle_delay_bug } /// Performs lint checking for the module. @@ -1751,8 +1748,6 @@ rustc_queries! { ) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { depth_limit desc { "computing layout of `{}`", key.value } - // we emit our own error during query cycle handling - cycle_delay_bug } /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 65c6b7551bc63..d15e0b2a122b9 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -383,7 +383,6 @@ impl_erasable_for_simple_types! { rustc_middle::ty::Destructor, rustc_middle::ty::fast_reject::SimplifiedType, rustc_middle::ty::ImplPolarity, - rustc_middle::ty::Representability, rustc_middle::ty::UnusedGenericParams, rustc_middle::ty::util::AlwaysRequiresDrop, rustc_middle::ty::Visibility, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9876441f5218d..b8fd88f2af17d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -4,8 +4,8 @@ pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCac pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter}; pub use self::keys::{AsLocalQueryKey, LocalCrate, QueryKey}; pub use self::plumbing::{ - ActiveKeyStatus, CycleError, CycleErrorHandling, EnsureMode, IntoQueryParam, QueryMode, - QueryState, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, TyCtxtEnsureResult, + ActiveKeyStatus, CycleError, EnsureMode, IntoQueryParam, QueryMode, QueryState, TyCtxtAt, + TyCtxtEnsureDone, TyCtxtEnsureOk, TyCtxtEnsureResult, }; pub use self::stack::QueryStackFrame; pub use crate::queries::Providers; diff --git a/compiler/rustc_middle/src/query/modifiers.rs b/compiler/rustc_middle/src/query/modifiers.rs index 100d1ac527693..ad9b9de119d55 100644 --- a/compiler/rustc_middle/src/query/modifiers.rs +++ b/compiler/rustc_middle/src/query/modifiers.rs @@ -29,11 +29,6 @@ pub(crate) struct arena_cache; /// identifier is available for use within the block, as is `tcx`. pub(crate) struct cache_on_disk_if; -/// # `cycle_delay_bug` query modifier -/// -/// If a dependency cycle is detected, emit a delayed bug instead of a normal error. -pub(crate) struct cycle_delay_bug; - /// # `depth_limit` query modifier /// /// Impose a recursion call depth limit on the query to prevent stack overflow. diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index a85412158830b..f388898465246 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -5,9 +5,10 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::hash_table::HashTable; use rustc_data_structures::sharded::Sharded; use rustc_data_structures::sync::{AtomicU64, WorkerLocal}; +use rustc_errors::Diag; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::OwnerId; -use rustc_span::{ErrorGuaranteed, Span}; +use rustc_span::Span; pub use sealed::IntoQueryParam; use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex}; @@ -49,16 +50,6 @@ pub enum ActiveKeyStatus<'tcx> { Poisoned, } -/// How a particular query deals with query cycle errors. -/// -/// Inspected by the code that actually handles cycle errors, to decide what -/// approach to use. -#[derive(Copy, Clone)] -pub enum CycleErrorHandling { - Error, - DelayBug, -} - #[derive(Clone, Debug)] pub struct CycleError<'tcx> { /// The query and related span that uses the cycle. @@ -98,8 +89,6 @@ pub struct QueryVTable<'tcx, C: QueryCache> { pub feedable: bool, pub dep_kind: DepKind, - /// How this query deals with query cycle errors. - pub cycle_error_handling: CycleErrorHandling, pub state: QueryState<'tcx, C::Key>, pub cache: C, @@ -127,12 +116,16 @@ pub struct QueryVTable<'tcx, C: QueryCache> { /// For `no_hash` queries, this function pointer is None. pub hash_value_fn: Option, &C::Value) -> Fingerprint>, + /// Function pointer that handles a cycle error. `error` must be consumed, e.g. with `emit` (if + /// it should be emitted) or `delay_as_bug` (if it need not be emitted because an alternative + /// error is created and emitted). pub value_from_cycle_error: fn( tcx: TyCtxt<'tcx>, key: C::Key, cycle_error: CycleError<'tcx>, - guar: ErrorGuaranteed, + error: Diag<'_>, ) -> C::Value, + pub format_value: fn(&C::Value) -> String, pub create_tagged_key: fn(C::Key) -> TaggedQueryKey<'tcx>, @@ -295,7 +288,6 @@ macro_rules! define_callbacks { anon: $anon:literal, arena_cache: $arena_cache:literal, cache_on_disk: $cache_on_disk:literal, - cycle_error_handling: $cycle_error_handling:ident, depth_limit: $depth_limit:literal, eval_always: $eval_always:literal, feedable: $feedable:literal, diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index ac51e5bd2289a..ae3c45877900b 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -751,8 +751,3 @@ impl<'tcx> AdtDef<'tcx> { if self.is_struct() { tcx.adt_sizedness_constraint((self.did(), sizedness)) } else { None } } } - -/// This type exists just so a `FromCycleError` impl can be made for the `check_representability` -/// query. -#[derive(Clone, Copy, Debug, HashStable)] -pub struct Representability; diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs index 3bc2e35b02bcd..34ef70f141b94 100644 --- a/compiler/rustc_query_impl/src/dep_kind_vtables.rs +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -136,7 +136,6 @@ macro_rules! define_dep_kind_vtables { anon: $anon:literal, arena_cache: $arena_cache:literal, cache_on_disk: $cache_on_disk:literal, - cycle_error_handling: $cycle_error_handling:ident, depth_limit: $depth_limit:literal, eval_always: $eval_always:literal, feedable: $feedable:literal, diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 9cb6eababbce8..b4823954a4ea3 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -9,8 +9,8 @@ use rustc_errors::FatalError; use rustc_middle::dep_graph::{DepGraphData, DepNodeKey, SerializedDepNodeIndex}; use rustc_middle::query::plumbing::QueryVTable; use rustc_middle::query::{ - ActiveKeyStatus, CycleError, CycleErrorHandling, EnsureMode, QueryCache, QueryJob, QueryJobId, - QueryKey, QueryLatch, QueryMode, QueryState, + ActiveKeyStatus, CycleError, EnsureMode, QueryCache, QueryJob, QueryJobId, QueryKey, + QueryLatch, QueryMode, QueryState, }; use rustc_middle::ty::TyCtxt; use rustc_middle::verify_ich::incremental_verify_ich; @@ -128,16 +128,7 @@ fn mk_cycle<'tcx, C: QueryCache>( cycle_error: CycleError<'tcx>, ) -> C::Value { let error = report_cycle(tcx, &cycle_error); - match query.cycle_error_handling { - CycleErrorHandling::Error => { - let guar = error.emit(); - (query.value_from_cycle_error)(tcx, key, cycle_error, guar) - } - CycleErrorHandling::DelayBug => { - let guar = error.delay_as_bug(); - (query.value_from_cycle_error)(tcx, key, cycle_error, guar) - } - } + (query.value_from_cycle_error)(tcx, key, cycle_error, error) } /// Guard object representing the responsibility to execute a query job and diff --git a/compiler/rustc_query_impl/src/from_cycle_error.rs b/compiler/rustc_query_impl/src/from_cycle_error.rs index 10baaa9209d01..6a3155c02949e 100644 --- a/compiler/rustc_query_impl/src/from_cycle_error.rs +++ b/compiler/rustc_query_impl/src/from_cycle_error.rs @@ -5,14 +5,14 @@ use std::ops::ControlFlow; use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; -use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err}; +use rustc_errors::{Applicability, Diag, MultiSpan, pluralize, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_middle::dep_graph::DepKind; use rustc_middle::queries::QueryVTables; use rustc_middle::query::CycleError; use rustc_middle::query::erase::erase_val; -use rustc_middle::ty::layout::{LayoutError, TyAndLayout}; +use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{DefId, LocalDefId}; @@ -21,41 +21,45 @@ use rustc_span::{ErrorGuaranteed, Span}; use crate::job::report_cycle; pub(crate) fn specialize_query_vtables<'tcx>(vtables: &mut QueryVTables<'tcx>) { - vtables.type_of.value_from_cycle_error = - |tcx, _, _, guar| erase_val(ty::EarlyBinder::bind(Ty::new_error(tcx, guar))); + vtables.type_of.value_from_cycle_error = |tcx, _, _, err| { + let guar = err.emit(); + erase_val(ty::EarlyBinder::bind(Ty::new_error(tcx, guar))) + }; - vtables.type_of_opaque_hir_typeck.value_from_cycle_error = - |tcx, _, _, guar| erase_val(ty::EarlyBinder::bind(Ty::new_error(tcx, guar))); + vtables.type_of_opaque_hir_typeck.value_from_cycle_error = |tcx, _, _, err| { + let guar = err.emit(); + erase_val(ty::EarlyBinder::bind(Ty::new_error(tcx, guar))) + }; - vtables.erase_and_anonymize_regions_ty.value_from_cycle_error = - |tcx, _, _, guar| erase_val(Ty::new_error(tcx, guar)); + vtables.erase_and_anonymize_regions_ty.value_from_cycle_error = |tcx, _, _, err| { + let guar = err.emit(); + erase_val(Ty::new_error(tcx, guar)) + }; - vtables.fn_sig.value_from_cycle_error = |tcx, key, _, guar| erase_val(fn_sig(tcx, key, guar)); + vtables.fn_sig.value_from_cycle_error = |tcx, key, _, err| { + let guar = err.delay_as_bug(); + erase_val(fn_sig(tcx, key, guar)) + }; vtables.check_representability.value_from_cycle_error = - |tcx, _, cycle, guar| check_representability(tcx, cycle, guar); + |tcx, _, cycle, _err| check_representability(tcx, cycle); vtables.check_representability_adt_ty.value_from_cycle_error = - |tcx, _, cycle, guar| check_representability(tcx, cycle, guar); + |tcx, _, cycle, _err| check_representability(tcx, cycle); - vtables.variances_of.value_from_cycle_error = - |tcx, _, cycle, guar| erase_val(variances_of(tcx, cycle, guar)); + vtables.variances_of.value_from_cycle_error = |tcx, _, cycle, err| { + let _guar = err.delay_as_bug(); + erase_val(variances_of(tcx, cycle)) + }; - vtables.layout_of.value_from_cycle_error = - |tcx, _, cycle, guar| erase_val(layout_of(tcx, cycle, guar)); + vtables.layout_of.value_from_cycle_error = |tcx, _, cycle, err| { + let _guar = err.delay_as_bug(); + erase_val(Err(layout_of(tcx, cycle))) + } } -pub(crate) fn default<'tcx>( - tcx: TyCtxt<'tcx>, - cycle_error: CycleError<'tcx>, - query_name: &str, -) -> ! { - let Some(guar) = tcx.sess.dcx().has_errors() else { - bug!( - "`from_cycle_error_default` on query `{query_name}` called without errors: {:#?}", - cycle_error.cycle, - ); - }; +pub(crate) fn default(err: Diag<'_>) -> ! { + let guar = err.emit(); guar.raise_fatal() } @@ -84,11 +88,7 @@ fn fn_sig<'tcx>( ))) } -fn check_representability<'tcx>( - tcx: TyCtxt<'tcx>, - cycle_error: CycleError<'tcx>, - _guar: ErrorGuaranteed, -) -> ! { +fn check_representability<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError<'tcx>) -> ! { let mut item_and_field_ids = Vec::new(); let mut representable_ids = FxHashSet::default(); for info in &cycle_error.cycle { @@ -120,11 +120,7 @@ fn check_representability<'tcx>( guar.raise_fatal() } -fn variances_of<'tcx>( - tcx: TyCtxt<'tcx>, - cycle_error: CycleError<'tcx>, - _guar: ErrorGuaranteed, -) -> &'tcx [ty::Variance] { +fn variances_of<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError<'tcx>) -> &'tcx [ty::Variance] { search_for_cycle_permutation( &cycle_error.cycle, |cycle| { @@ -169,8 +165,7 @@ fn search_for_cycle_permutation( fn layout_of<'tcx>( tcx: TyCtxt<'tcx>, cycle_error: CycleError<'tcx>, - _guar: ErrorGuaranteed, -) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { +) -> &'tcx ty::layout::LayoutError<'tcx> { let diag = search_for_cycle_permutation( &cycle_error.cycle, |cycle| { @@ -247,7 +242,7 @@ fn layout_of<'tcx>( ); let guar = diag.emit(); - Err(tcx.arena.alloc(LayoutError::Cycle(guar))) + tcx.arena.alloc(LayoutError::Cycle(guar)) } // item_and_field_ids should form a cycle where each field contains the diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 0a84a8b23c076..661ea99bbf02a 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -295,7 +295,6 @@ macro_rules! define_queries { anon: $anon:literal, arena_cache: $arena_cache:literal, cache_on_disk: $cache_on_disk:literal, - cycle_error_handling: $cycle_error_handling:ident, depth_limit: $depth_limit:literal, eval_always: $eval_always:literal, feedable: $feedable:literal, @@ -409,8 +408,6 @@ macro_rules! define_queries { depth_limit: $depth_limit, feedable: $feedable, dep_kind: dep_graph::DepKind::$name, - cycle_error_handling: - rustc_middle::query::CycleErrorHandling::$cycle_error_handling, state: Default::default(), cache: Default::default(), @@ -446,8 +443,11 @@ macro_rules! define_queries { #[cfg(not($cache_on_disk))] is_loadable_from_disk_fn: |_tcx, _key, _index| false, - value_from_cycle_error: |tcx, _, cycle, _| { - $crate::from_cycle_error::default(tcx, cycle, stringify!($name)) + // The default just emits `err` and then aborts. + // `from_cycle_error::specialize_query_vtables` overwrites this default for + // certain queries. + value_from_cycle_error: |_tcx, _key, _cycle, err| { + $crate::from_cycle_error::default(err) }, #[cfg($no_hash)] diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index 1814e7604a2d1..cef964ab139ae 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -2,7 +2,7 @@ use rustc_hir::def::DefKind; use rustc_index::bit_set::DenseBitSet; use rustc_middle::bug; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, Representability, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; pub(crate) fn provide(providers: &mut Providers) { @@ -14,7 +14,7 @@ pub(crate) fn provide(providers: &mut Providers) { }; } -fn check_representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability { +fn check_representability(tcx: TyCtxt<'_>, def_id: LocalDefId) { match tcx.def_kind(def_id) { DefKind::Struct | DefKind::Union | DefKind::Enum => { for variant in tcx.adt_def(def_id).variants() { @@ -28,7 +28,6 @@ fn check_representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representabili } def_kind => bug!("unexpected {def_kind:?}"), } - Representability } fn check_representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) { @@ -67,7 +66,7 @@ fn check_representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) { // Looking at the query cycle above, we know that `Bar` is representable // because `check_representability_adt_ty(Bar<..>)` is in the cycle and // `check_representability(Bar)` is *not* in the cycle. -fn check_representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability { +fn check_representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) { let ty::Adt(adt, args) = ty.kind() else { bug!("expected adt") }; if let Some(def_id) = adt.did().as_local() { let _ = tcx.check_representability(def_id); @@ -82,7 +81,6 @@ fn check_representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Repre } } } - Representability } fn params_in_repr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DenseBitSet {