Skip to content

Commit 58cc179

Browse files
committed
Change value_from_cycle_error signature.
Currently if a cycle error occurs the error is created, then handled according to `CycleErrorHandling` (which comes from the `cycle_*` query modifers), and then `value_from_cycle_error` is called. This commit changes things so the error is created and then just passed to `value_from_cycle_error`. This gives `value_from_cycle_error` full control over how it's handled, eliminating the need for `CycleErrorHandling`. This makes things simpler overall.
1 parent ea4a2de commit 58cc179

File tree

9 files changed

+55
-106
lines changed

9 files changed

+55
-106
lines changed

compiler/rustc_macros/src/query.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ struct QueryModifiers {
143143
anon: Option<Ident>,
144144
arena_cache: Option<Ident>,
145145
cache_on_disk_if: Option<CacheOnDiskIf>,
146-
cycle_delay_bug: Option<Ident>,
147146
depth_limit: Option<Ident>,
148147
desc: Desc,
149148
eval_always: Option<Ident>,
@@ -157,7 +156,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
157156
let mut arena_cache = None;
158157
let mut cache_on_disk_if = None;
159158
let mut desc = None;
160-
let mut cycle_delay_bug = None;
161159
let mut no_hash = None;
162160
let mut anon = None;
163161
let mut eval_always = None;
@@ -191,8 +189,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
191189
try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, block });
192190
} else if modifier == "arena_cache" {
193191
try_insert!(arena_cache = modifier);
194-
} else if modifier == "cycle_delay_bug" {
195-
try_insert!(cycle_delay_bug = modifier);
196192
} else if modifier == "no_hash" {
197193
try_insert!(no_hash = modifier);
198194
} else if modifier == "anon" {
@@ -216,7 +212,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
216212
arena_cache,
217213
cache_on_disk_if,
218214
desc,
219-
cycle_delay_bug,
220215
no_hash,
221216
anon,
222217
eval_always,
@@ -251,7 +246,6 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream {
251246
anon,
252247
arena_cache,
253248
cache_on_disk_if,
254-
cycle_delay_bug,
255249
depth_limit,
256250
desc: _,
257251
eval_always,
@@ -264,13 +258,6 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream {
264258
let anon = anon.is_some();
265259
let arena_cache = arena_cache.is_some();
266260
let cache_on_disk = cache_on_disk_if.is_some();
267-
268-
let cycle_error_handling = if cycle_delay_bug.is_some() {
269-
quote! { DelayBug }
270-
} else {
271-
quote! { Error }
272-
};
273-
274261
let depth_limit = depth_limit.is_some();
275262
let eval_always = eval_always.is_some();
276263
let feedable = feedable.is_some();
@@ -289,7 +276,6 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream {
289276
anon: #anon,
290277
arena_cache: #arena_cache,
291278
cache_on_disk: #cache_on_disk,
292-
cycle_error_handling: #cycle_error_handling,
293279
depth_limit: #depth_limit,
294280
eval_always: #eval_always,
295281
feedable: #feedable,
@@ -402,7 +388,6 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke
402388

403389
doc_link!(
404390
arena_cache,
405-
cycle_delay_bug,
406391
no_hash,
407392
anon,
408393
eval_always,

compiler/rustc_middle/src/queries.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
//! - `arena_cache`: Use an arena for in-memory caching of the query result.
3333
//! - `cache_on_disk_if { ... }`: Cache the query result to disk if the provided block evaluates to
3434
//! true. The query key identifier is available for use within the block, as is `tcx`.
35-
//! - `cycle_delay_bug`: If a dependency cycle is detected, emit a delayed bug instead of aborting immediately.
3635
//! - `no_hash`: Do not hash the query result for incremental compilation; just mark as dirty if recomputed.
3736
//! - `anon`: Make the query anonymous in the dependency graph (no dep node is created).
3837
//! - `eval_always`: Always evaluate the query, ignoring its dependencies and cached results.
@@ -580,13 +579,13 @@ rustc_queries! {
580579
}
581580

582581
/// Checks whether a type is representable or infinitely sized
582+
//
583+
// Infinitely sized types will cause a cycle. The `value_from_cycle_error` impl will print
584+
// a custom error about the infinite size and then abort compilation. (In the past we
585+
// recovered and continued, but in practice that leads to confusing subsequent error
586+
// messages about cycles that then abort.)
583587
query check_representability(key: LocalDefId) {
584588
desc { "checking if `{}` is representable", tcx.def_path_str(key) }
585-
// Infinitely sized types will cause a cycle. The custom `FromCycleError` impl for
586-
// `Representability` will print a custom error about the infinite size and then abort
587-
// compilation. (In the past we recovered and continued, but in practice that leads to
588-
// confusing subsequent error messages about cycles that then abort.)
589-
cycle_delay_bug
590589
// We don't want recursive representability calls to be forced with
591590
// incremental compilation because, if a cycle occurs, we need the
592591
// entire cycle to be in memory for diagnostics. This means we can't
@@ -598,7 +597,6 @@ rustc_queries! {
598597
/// details, particularly on the modifiers.
599598
query check_representability_adt_ty(key: Ty<'tcx>) {
600599
desc { "checking if `{}` is representable", key }
601-
cycle_delay_bug
602600
anon
603601
}
604602

@@ -1043,7 +1041,6 @@ rustc_queries! {
10431041
desc { "computing the variances of `{}`", tcx.def_path_str(def_id) }
10441042
cache_on_disk_if { def_id.is_local() }
10451043
separate_provide_extern
1046-
cycle_delay_bug
10471044
}
10481045

10491046
/// Gets a map with the inferred outlives-predicates of every item in the local crate.
@@ -1176,7 +1173,6 @@ rustc_queries! {
11761173
desc { "computing function signature of `{}`", tcx.def_path_str(key) }
11771174
cache_on_disk_if { key.is_local() }
11781175
separate_provide_extern
1179-
cycle_delay_bug
11801176
}
11811177

11821178
/// Performs lint checking for the module.
@@ -1767,8 +1763,6 @@ rustc_queries! {
17671763
) -> Result<ty::layout::TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> {
17681764
depth_limit
17691765
desc { "computing layout of `{}`", key.value }
1770-
// we emit our own error during query cycle handling
1771-
cycle_delay_bug
17721766
}
17731767

17741768
/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.

compiler/rustc_middle/src/query/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCac
44
pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter};
55
pub use self::keys::{AsLocalQueryKey, LocalCrate, QueryKey};
66
pub use self::plumbing::{
7-
ActiveKeyStatus, CycleError, CycleErrorHandling, EnsureMode, IntoQueryParam, QueryMode,
8-
QueryState, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, TyCtxtEnsureResult,
7+
ActiveKeyStatus, CycleError, EnsureMode, IntoQueryParam, QueryMode, QueryState, TyCtxtAt,
8+
TyCtxtEnsureDone, TyCtxtEnsureOk, TyCtxtEnsureResult,
99
};
1010
pub use self::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
1111
pub use crate::queries::Providers;

compiler/rustc_middle/src/query/modifiers.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ pub(crate) struct arena_cache;
2323
/// Cache the query to disk if the `Block` returns true.
2424
pub(crate) struct cache_on_disk_if;
2525

26-
/// # `cycle_delay_bug` query modifier
27-
///
28-
/// A cycle error results in a delay_bug call
29-
pub(crate) struct cycle_delay_bug;
30-
3126
/// # `depth_limit` query modifier
3227
///
3328
/// Whether the query has a call depth limit

compiler/rustc_middle/src/query/plumbing.rs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ use rustc_data_structures::fingerprint::Fingerprint;
55
use rustc_data_structures::hash_table::HashTable;
66
use rustc_data_structures::sharded::Sharded;
77
use rustc_data_structures::sync::{AtomicU64, WorkerLocal};
8+
use rustc_errors::Diag;
89
use rustc_hir::def_id::{DefId, LocalDefId};
910
use rustc_hir::hir_id::OwnerId;
10-
use rustc_span::{ErrorGuaranteed, Span};
11+
use rustc_span::Span;
1112
pub use sealed::IntoQueryParam;
1213

1314
use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex};
@@ -49,16 +50,6 @@ pub enum ActiveKeyStatus<'tcx> {
4950
Poisoned,
5051
}
5152

52-
/// How a particular query deals with query cycle errors.
53-
///
54-
/// Inspected by the code that actually handles cycle errors, to decide what
55-
/// approach to use.
56-
#[derive(Copy, Clone)]
57-
pub enum CycleErrorHandling {
58-
Error,
59-
DelayBug,
60-
}
61-
6253
#[derive(Clone, Debug)]
6354
pub struct CycleError<I = QueryStackFrameExtra> {
6455
/// The query and related span that uses the cycle.
@@ -107,8 +98,6 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
10798
pub feedable: bool,
10899

109100
pub dep_kind: DepKind,
110-
/// How this query deals with query cycle errors.
111-
pub cycle_error_handling: CycleErrorHandling,
112101
pub state: QueryState<'tcx, C::Key>,
113102
pub cache: C,
114103

@@ -136,12 +125,12 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
136125
/// For `no_hash` queries, this function pointer is None.
137126
pub hash_value_fn: Option<fn(&mut StableHashingContext<'_>, &C::Value) -> Fingerprint>,
138127

139-
pub value_from_cycle_error: fn(
140-
tcx: TyCtxt<'tcx>,
141-
key: C::Key,
142-
cycle_error: CycleError,
143-
guar: ErrorGuaranteed,
144-
) -> C::Value,
128+
/// Function pointer that handles a cycle error. `error` must be consumed, e.g. with `emit` (if
129+
/// it should be emitted) or `delay_as_bug` (if it need not be emitted because an alternative
130+
/// error is created and emitted).
131+
pub value_from_cycle_error:
132+
fn(tcx: TyCtxt<'tcx>, key: C::Key, cycle_error: CycleError, error: Diag<'_>) -> C::Value,
133+
145134
pub format_value: fn(&C::Value) -> String,
146135

147136
/// Formats a human-readable description of this query and its key, as
@@ -308,7 +297,6 @@ macro_rules! define_callbacks {
308297
anon: $anon:literal,
309298
arena_cache: $arena_cache:literal,
310299
cache_on_disk: $cache_on_disk:literal,
311-
cycle_error_handling: $cycle_error_handling:ident,
312300
depth_limit: $depth_limit:literal,
313301
eval_always: $eval_always:literal,
314302
feedable: $feedable:literal,

compiler/rustc_query_impl/src/dep_kind_vtables.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ macro_rules! define_dep_kind_vtables {
136136
anon: $anon:literal,
137137
arena_cache: $arena_cache:literal,
138138
cache_on_disk: $cache_on_disk:literal,
139-
cycle_error_handling: $cycle_error_handling:ident,
140139
depth_limit: $depth_limit:literal,
141140
eval_always: $eval_always:literal,
142141
feedable: $feedable:literal,

compiler/rustc_query_impl/src/execution.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use rustc_errors::FatalError;
99
use rustc_middle::dep_graph::{DepGraphData, DepNodeKey, SerializedDepNodeIndex};
1010
use rustc_middle::query::plumbing::QueryVTable;
1111
use rustc_middle::query::{
12-
ActiveKeyStatus, CycleError, CycleErrorHandling, EnsureMode, QueryCache, QueryJob, QueryJobId,
13-
QueryKey, QueryLatch, QueryMode, QueryState,
12+
ActiveKeyStatus, CycleError, EnsureMode, QueryCache, QueryJob, QueryJobId, QueryKey,
13+
QueryLatch, QueryMode, QueryState,
1414
};
1515
use rustc_middle::ty::TyCtxt;
1616
use rustc_middle::verify_ich::incremental_verify_ich;
@@ -129,16 +129,7 @@ fn mk_cycle<'tcx, C: QueryCache>(
129129
cycle_error: CycleError,
130130
) -> C::Value {
131131
let error = report_cycle(tcx.sess, &cycle_error);
132-
match query.cycle_error_handling {
133-
CycleErrorHandling::Error => {
134-
let guar = error.emit();
135-
(query.value_from_cycle_error)(tcx, key, cycle_error, guar)
136-
}
137-
CycleErrorHandling::DelayBug => {
138-
let guar = error.delay_as_bug();
139-
(query.value_from_cycle_error)(tcx, key, cycle_error, guar)
140-
}
141-
}
132+
(query.value_from_cycle_error)(tcx, key, cycle_error, error)
142133
}
143134

144135
/// Guard object representing the responsibility to execute a query job and

compiler/rustc_query_impl/src/from_cycle_error.rs

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ use std::ops::ControlFlow;
55

66
use rustc_data_structures::fx::FxHashSet;
77
use rustc_errors::codes::*;
8-
use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err};
8+
use rustc_errors::{Applicability, Diag, MultiSpan, pluralize, struct_span_code_err};
99
use rustc_hir as hir;
1010
use rustc_hir::def::{DefKind, Res};
1111
use rustc_middle::dep_graph::DepKind;
1212
use rustc_middle::queries::QueryVTables;
1313
use rustc_middle::query::CycleError;
1414
use rustc_middle::query::erase::erase_val;
15-
use rustc_middle::ty::layout::{LayoutError, TyAndLayout};
15+
use rustc_middle::ty::layout::LayoutError;
1616
use rustc_middle::ty::{self, Ty, TyCtxt};
1717
use rustc_middle::{bug, span_bug};
1818
use rustc_span::def_id::{DefId, LocalDefId};
@@ -21,37 +21,45 @@ use rustc_span::{ErrorGuaranteed, Span};
2121
use crate::job::report_cycle;
2222

2323
pub(crate) fn specialize_query_vtables<'tcx>(vtables: &mut QueryVTables<'tcx>) {
24-
vtables.type_of.value_from_cycle_error =
25-
|tcx, _, _, guar| erase_val(ty::EarlyBinder::bind(Ty::new_error(tcx, guar)));
24+
vtables.type_of.value_from_cycle_error = |tcx, _, _, err| {
25+
let guar = err.emit();
26+
erase_val(ty::EarlyBinder::bind(Ty::new_error(tcx, guar)))
27+
};
2628

27-
vtables.type_of_opaque_hir_typeck.value_from_cycle_error =
28-
|tcx, _, _, guar| erase_val(ty::EarlyBinder::bind(Ty::new_error(tcx, guar)));
29+
vtables.type_of_opaque_hir_typeck.value_from_cycle_error = |tcx, _, _, err| {
30+
let guar = err.emit();
31+
erase_val(ty::EarlyBinder::bind(Ty::new_error(tcx, guar)))
32+
};
2933

30-
vtables.erase_and_anonymize_regions_ty.value_from_cycle_error =
31-
|tcx, _, _, guar| erase_val(Ty::new_error(tcx, guar));
34+
vtables.erase_and_anonymize_regions_ty.value_from_cycle_error = |tcx, _, _, err| {
35+
let guar = err.emit();
36+
erase_val(Ty::new_error(tcx, guar))
37+
};
3238

33-
vtables.fn_sig.value_from_cycle_error = |tcx, key, _, guar| erase_val(fn_sig(tcx, key, guar));
39+
vtables.fn_sig.value_from_cycle_error = |tcx, key, _, err| {
40+
let guar = err.delay_as_bug();
41+
erase_val(fn_sig(tcx, key, guar))
42+
};
3443

3544
vtables.check_representability.value_from_cycle_error =
36-
|tcx, _, cycle, guar| check_representability(tcx, cycle, guar);
45+
|tcx, _, cycle, _err| check_representability(tcx, cycle);
3746

3847
vtables.check_representability_adt_ty.value_from_cycle_error =
39-
|tcx, _, cycle, guar| check_representability(tcx, cycle, guar);
48+
|tcx, _, cycle, _err| check_representability(tcx, cycle);
4049

41-
vtables.variances_of.value_from_cycle_error =
42-
|tcx, _, cycle, guar| erase_val(variances_of(tcx, cycle, guar));
50+
vtables.variances_of.value_from_cycle_error = |tcx, _, cycle, err| {
51+
let _guar = err.delay_as_bug();
52+
erase_val(variances_of(tcx, cycle))
53+
};
4354

44-
vtables.layout_of.value_from_cycle_error =
45-
|tcx, _, cycle, guar| erase_val(layout_of(tcx, cycle, guar));
55+
vtables.layout_of.value_from_cycle_error = |tcx, _, cycle, err| {
56+
let _guar = err.delay_as_bug();
57+
erase_val(Err(layout_of(tcx, cycle)))
58+
}
4659
}
4760

48-
pub(crate) fn default<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError, query_name: &str) -> ! {
49-
let Some(guar) = tcx.sess.dcx().has_errors() else {
50-
bug!(
51-
"`from_cycle_error_default` on query `{query_name}` called without errors: {:#?}",
52-
cycle_error.cycle,
53-
);
54-
};
61+
pub(crate) fn default(err: Diag<'_>) -> ! {
62+
let guar = err.emit();
5563
guar.raise_fatal()
5664
}
5765

@@ -80,11 +88,7 @@ fn fn_sig<'tcx>(
8088
)))
8189
}
8290

83-
fn check_representability<'tcx>(
84-
tcx: TyCtxt<'tcx>,
85-
cycle_error: CycleError,
86-
_guar: ErrorGuaranteed,
87-
) -> ! {
91+
fn check_representability<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError) -> ! {
8892
let mut item_and_field_ids = Vec::new();
8993
let mut representable_ids = FxHashSet::default();
9094
for info in &cycle_error.cycle {
@@ -116,11 +120,7 @@ fn check_representability<'tcx>(
116120
guar.raise_fatal()
117121
}
118122

119-
fn variances_of<'tcx>(
120-
tcx: TyCtxt<'tcx>,
121-
cycle_error: CycleError,
122-
_guar: ErrorGuaranteed,
123-
) -> &'tcx [ty::Variance] {
123+
fn variances_of<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError) -> &'tcx [ty::Variance] {
124124
search_for_cycle_permutation(
125125
&cycle_error.cycle,
126126
|cycle| {
@@ -165,8 +165,7 @@ fn search_for_cycle_permutation<Q, T>(
165165
fn layout_of<'tcx>(
166166
tcx: TyCtxt<'tcx>,
167167
cycle_error: CycleError,
168-
_guar: ErrorGuaranteed,
169-
) -> Result<TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> {
168+
) -> &'tcx ty::layout::LayoutError<'tcx> {
170169
let diag = search_for_cycle_permutation(
171170
&cycle_error.cycle,
172171
|cycle| {
@@ -243,7 +242,7 @@ fn layout_of<'tcx>(
243242
);
244243

245244
let guar = diag.emit();
246-
Err(tcx.arena.alloc(LayoutError::Cycle(guar)))
245+
tcx.arena.alloc(LayoutError::Cycle(guar))
247246
}
248247

249248
// item_and_field_ids should form a cycle where each field contains the

0 commit comments

Comments
 (0)