authorbors <bors@rust-lang.org> 2026-03-13 07:28:46 UTC
committerbors <bors@rust-lang.org> 2026-03-13 07:28:46 UTC
logeaf4e7489b6ae3d4ba9a71b720b03b6d58e4f102
tree5e9930f4c37dbb927a7b46accf8981b5338426d6
parent7ad5c602172b132646213941b5102a75a77c10f6
parent03e3b1ee7549a41fab5793fc1486d09ab03cc6fa

Auto merge of #153812 - Zalathar:rollup-aZ9Qsob, r=Zalathar

Rollup of 3 pull requests Successful merges: - rust-lang/rust#153792 (tests/debuginfo/basic-stepping.rs: Add lldb test) - rust-lang/rust#153492 (Add a `TaggedQueryKey` to identify a query instance) - rust-lang/rust#153808 (rustfmt.toml: drop ignore of deleted test)

13 files changed, 195 insertions(+), 224 deletions(-)

Cargo.lock-1
......@@ -4575,7 +4575,6 @@ dependencies = [
45754575 "rustc_macros",
45764576 "rustc_middle",
45774577 "rustc_serialize",
4578 "rustc_session",
45794578 "rustc_span",
45804579 "rustc_thread_pool",
45814580 "tracing",
compiler/rustc_middle/src/query/job.rs+5-11
......@@ -7,21 +7,15 @@ use parking_lot::{Condvar, Mutex};
77use rustc_span::Span;
88
99use crate::query::plumbing::CycleError;
10use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
10use crate::query::stack::QueryStackFrame;
1111use crate::ty::TyCtxt;
1212
1313/// Represents a span and a query key.
1414#[derive(Clone, Debug)]
15pub struct QueryInfo<I> {
15pub struct QueryInfo<'tcx> {
1616 /// The span corresponding to the reason for which this query was required.
1717 pub span: Span,
18 pub frame: QueryStackFrame<I>,
19}
20
21impl<'tcx> QueryInfo<QueryStackDeferred<'tcx>> {
22 pub(crate) fn lift(&self) -> QueryInfo<QueryStackFrameExtra> {
23 QueryInfo { span: self.span, frame: self.frame.lift() }
24 }
18 pub frame: QueryStackFrame<'tcx>,
2519}
2620
2721/// A value uniquely identifying an active query job.
......@@ -74,7 +68,7 @@ pub struct QueryWaiter<'tcx> {
7468 pub query: Option<QueryJobId>,
7569 pub condvar: Condvar,
7670 pub span: Span,
77 pub cycle: Mutex<Option<CycleError<QueryStackDeferred<'tcx>>>>,
71 pub cycle: Mutex<Option<CycleError<'tcx>>>,
7872}
7973
8074#[derive(Clone, Debug)]
......@@ -94,7 +88,7 @@ impl<'tcx> QueryLatch<'tcx> {
9488 tcx: TyCtxt<'tcx>,
9589 query: Option<QueryJobId>,
9690 span: Span,
97 ) -> Result<(), CycleError<QueryStackDeferred<'tcx>>> {
91 ) -> Result<(), CycleError<'tcx>> {
9892 let mut waiters_guard = self.waiters.lock();
9993 let Some(waiters) = &mut *waiters_guard else {
10094 return Ok(()); // already complete
compiler/rustc_middle/src/query/mod.rs+1-1
......@@ -7,7 +7,7 @@ pub use self::plumbing::{
77 ActiveKeyStatus, CycleError, CycleErrorHandling, EnsureMode, IntoQueryParam, QueryMode,
88 QueryState, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, TyCtxtEnsureResult,
99};
10pub use self::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
10pub use self::stack::QueryStackFrame;
1111pub use crate::queries::Providers;
1212use crate::ty::TyCtxt;
1313
compiler/rustc_middle/src/query/plumbing.rs+70-20
......@@ -12,9 +12,9 @@ pub use sealed::IntoQueryParam;
1212
1313use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex};
1414use crate::ich::StableHashingContext;
15use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables};
15use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables, TaggedQueryKey};
1616use crate::query::on_disk_cache::OnDiskCache;
17use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
17use crate::query::stack::QueryStackFrame;
1818use crate::query::{QueryCache, QueryInfo, QueryJob};
1919use crate::ty::TyCtxt;
2020
......@@ -60,19 +60,10 @@ pub enum CycleErrorHandling {
6060}
6161
6262#[derive(Clone, Debug)]
63pub struct CycleError<I = QueryStackFrameExtra> {
63pub struct CycleError<'tcx> {
6464 /// The query and related span that uses the cycle.
65 pub usage: Option<(Span, QueryStackFrame<I>)>,
66 pub cycle: Vec<QueryInfo<I>>,
67}
68
69impl<'tcx> CycleError<QueryStackDeferred<'tcx>> {
70 pub fn lift(&self) -> CycleError<QueryStackFrameExtra> {
71 CycleError {
72 usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift())),
73 cycle: self.cycle.iter().map(|info| info.lift()).collect(),
74 }
75 }
65 pub usage: Option<(Span, QueryStackFrame<'tcx>)>,
66 pub cycle: Vec<QueryInfo<'tcx>>,
7667}
7768
7869#[derive(Debug)]
......@@ -139,16 +130,12 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
139130 pub value_from_cycle_error: fn(
140131 tcx: TyCtxt<'tcx>,
141132 key: C::Key,
142 cycle_error: CycleError,
133 cycle_error: CycleError<'tcx>,
143134 guar: ErrorGuaranteed,
144135 ) -> C::Value,
145136 pub format_value: fn(&C::Value) -> String,
146137
147 /// Formats a human-readable description of this query and its key, as
148 /// specified by the `desc` query modifier.
149 ///
150 /// Used when reporting query cycle errors and similar problems.
151 pub description_fn: fn(TyCtxt<'tcx>, C::Key) -> String,
138 pub create_tagged_key: fn(C::Key) -> TaggedQueryKey<'tcx>,
152139
153140 /// Function pointer that is called by the query methods on [`TyCtxt`] and
154141 /// friends[^1], after they have checked the in-memory cache and found no
......@@ -523,6 +510,69 @@ macro_rules! define_callbacks {
523510 }
524511 )*
525512
513 /// Identifies a query by kind and key. This is in contrast to `QueryJobId` which is just a number.
514 #[allow(non_camel_case_types)]
515 #[derive(Clone, Debug)]
516 pub enum TaggedQueryKey<'tcx> {
517 $(
518 $name($name::Key<'tcx>),
519 )*
520 }
521
522 impl<'tcx> TaggedQueryKey<'tcx> {
523 /// Formats a human-readable description of this query and its key, as
524 /// specified by the `desc` query modifier.
525 ///
526 /// Used when reporting query cycle errors and similar problems.
527 pub fn description(&self, tcx: TyCtxt<'tcx>) -> String {
528 let (name, description) = ty::print::with_no_queries!(match self {
529 $(
530 TaggedQueryKey::$name(key) => (stringify!($name), _description_fns::$name(tcx, *key)),
531 )*
532 });
533 if tcx.sess.verbose_internals() {
534 format!("{description} [{name:?}]")
535 } else {
536 description
537 }
538 }
539
540 /// Returns the default span for this query if `span` is a dummy span.
541 pub fn default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span {
542 if !span.is_dummy() {
543 return span
544 }
545 if let TaggedQueryKey::def_span(..) = self {
546 // The `def_span` query is used to calculate `default_span`,
547 // so exit to avoid infinite recursion.
548 return DUMMY_SP
549 }
550 match self {
551 $(
552 TaggedQueryKey::$name(key) => crate::query::QueryKey::default_span(key, tcx),
553 )*
554 }
555 }
556
557 pub fn def_kind(&self, tcx: TyCtxt<'tcx>) -> Option<DefKind> {
558 // This is used to reduce code generation as it
559 // can be reused for queries with the same key type.
560 fn inner<'tcx>(key: &impl crate::query::QueryKey, tcx: TyCtxt<'tcx>) -> Option<DefKind> {
561 key.key_as_def_id().and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
562 }
563
564 if let TaggedQueryKey::def_kind(..) = self {
565 // Try to avoid infinite recursion.
566 return None
567 }
568 match self {
569 $(
570 TaggedQueryKey::$name(key) => inner(key, tcx),
571 )*
572 }
573 }
574 }
575
526576 /// Holds a `QueryVTable` for each query.
527577 pub struct QueryVTables<'tcx> {
528578 $(
compiler/rustc_middle/src/query/stack.rs+3-91
......@@ -1,106 +1,18 @@
11use std::fmt::Debug;
2use std::marker::PhantomData;
3use std::mem::transmute;
4use std::sync::Arc;
52
6use rustc_data_structures::sync::{DynSend, DynSync};
7use rustc_hir::def::DefKind;
8use rustc_span::Span;
93use rustc_span::def_id::DefId;
104
115use crate::dep_graph::DepKind;
6use crate::queries::TaggedQueryKey;
127
138/// Description of a frame in the query stack.
149///
1510/// This is mostly used in case of cycles for error reporting.
1611#[derive(Clone, Debug)]
17pub struct QueryStackFrame<I> {
18 /// This field initially stores a `QueryStackDeferred` during collection,
19 /// but can later be changed to `QueryStackFrameExtra` containing concrete information
20 /// by calling `lift`. This is done so that collecting query does not need to invoke
21 /// queries, instead `lift` will call queries in a more appropriate location.
22 pub info: I,
23
12pub struct QueryStackFrame<'tcx> {
13 pub tagged_key: TaggedQueryKey<'tcx>,
2414 pub dep_kind: DepKind,
2515 pub def_id: Option<DefId>,
2616 /// A def-id that is extracted from a `Ty` in a query key
2717 pub def_id_for_ty_in_cycle: Option<DefId>,
2818}
29
30impl<'tcx> QueryStackFrame<QueryStackDeferred<'tcx>> {
31 #[inline]
32 pub fn new(
33 info: QueryStackDeferred<'tcx>,
34 dep_kind: DepKind,
35 def_id: Option<DefId>,
36 def_id_for_ty_in_cycle: Option<DefId>,
37 ) -> Self {
38 Self { info, def_id, dep_kind, def_id_for_ty_in_cycle }
39 }
40
41 pub fn lift(&self) -> QueryStackFrame<QueryStackFrameExtra> {
42 QueryStackFrame {
43 info: self.info.extract(),
44 dep_kind: self.dep_kind,
45 def_id: self.def_id,
46 def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle,
47 }
48 }
49}
50
51#[derive(Clone, Debug)]
52pub struct QueryStackFrameExtra {
53 pub description: String,
54 pub span: Option<Span>,
55 pub def_kind: Option<DefKind>,
56}
57
58impl QueryStackFrameExtra {
59 #[inline]
60 pub fn new(description: String, span: Option<Span>, def_kind: Option<DefKind>) -> Self {
61 Self { description, span, def_kind }
62 }
63
64 // FIXME(eddyb) Get more valid `Span`s on queries.
65 #[inline]
66 pub fn default_span(&self, span: Span) -> Span {
67 if !span.is_dummy() {
68 return span;
69 }
70 self.span.unwrap_or(span)
71 }
72}
73
74/// Track a 'side effect' for a particular query.
75/// This is used to hold a closure which can create `QueryStackFrameExtra`.
76#[derive(Clone)]
77pub struct QueryStackDeferred<'tcx> {
78 _dummy: PhantomData<&'tcx ()>,
79
80 // `extract` may contain references to 'tcx, but we can't tell drop checking that it won't
81 // access it in the destructor.
82 extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend>,
83}
84
85impl<'tcx> QueryStackDeferred<'tcx> {
86 pub fn new<C: Copy + DynSync + DynSend + 'tcx>(
87 context: C,
88 extract: fn(C) -> QueryStackFrameExtra,
89 ) -> Self {
90 let extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend + 'tcx> =
91 Arc::new(move || extract(context));
92 // SAFETY: The `extract` closure does not access 'tcx in its destructor as the only
93 // captured variable is `context` which is Copy and cannot have a destructor.
94 Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } }
95 }
96
97 pub fn extract(&self) -> QueryStackFrameExtra {
98 (self.extract)()
99 }
100}
101
102impl<'tcx> Debug for QueryStackDeferred<'tcx> {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 f.write_str("QueryStackDeferred")
105 }
106}
compiler/rustc_query_impl/Cargo.toml-1
......@@ -14,7 +14,6 @@ rustc_index = { path = "../rustc_index" }
1414rustc_macros = { path = "../rustc_macros" }
1515rustc_middle = { path = "../rustc_middle" }
1616rustc_serialize = { path = "../rustc_serialize" }
17rustc_session = { path = "../rustc_session" }
1817rustc_span = { path = "../rustc_span" }
1918rustc_thread_pool = { path = "../rustc_thread_pool" }
2019tracing = "0.1"
compiler/rustc_query_impl/src/execution.rs+6-7
......@@ -48,7 +48,7 @@ pub fn collect_active_jobs_from_all_queries<'tcx>(
4848 let mut complete = true;
4949
5050 for_each_query_vtable!(ALL, tcx, |query| {
51 let res = gather_active_jobs(query, tcx, require_complete, &mut job_map_out);
51 let res = gather_active_jobs(query, require_complete, &mut job_map_out);
5252 if res.is_none() {
5353 complete = false;
5454 }
......@@ -66,7 +66,6 @@ pub fn collect_active_jobs_from_all_queries<'tcx>(
6666/// grep for.)
6767fn gather_active_jobs<'tcx, C>(
6868 query: &'tcx QueryVTable<'tcx, C>,
69 tcx: TyCtxt<'tcx>,
7069 require_complete: bool,
7170 job_map_out: &mut QueryJobMap<'tcx>, // Out-param; job info is gathered into this map
7271) -> Option<()>
......@@ -113,7 +112,7 @@ where
113112 // Call `make_frame` while we're not holding a `state.active` lock as `make_frame` may call
114113 // queries leading to a deadlock.
115114 for (key, job) in active {
116 let frame = crate::plumbing::create_deferred_query_stack_frame(tcx, query, key);
115 let frame = crate::plumbing::create_query_stack_frame(query, key);
117116 job_map_out.insert(job.id, QueryJobInfo { frame, job });
118117 }
119118
......@@ -126,9 +125,9 @@ fn mk_cycle<'tcx, C: QueryCache>(
126125 query: &'tcx QueryVTable<'tcx, C>,
127126 tcx: TyCtxt<'tcx>,
128127 key: C::Key,
129 cycle_error: CycleError,
128 cycle_error: CycleError<'tcx>,
130129) -> C::Value {
131 let error = report_cycle(tcx.sess, &cycle_error);
130 let error = report_cycle(tcx, &cycle_error);
132131 match query.cycle_error_handling {
133132 CycleErrorHandling::Error => {
134133 let guar = error.emit();
......@@ -231,7 +230,7 @@ fn cycle_error<'tcx, C: QueryCache>(
231230 .expect("failed to collect active queries");
232231
233232 let error = find_cycle_in_stack(try_execute, job_map, &current_query_job(), span);
234 (mk_cycle(query, tcx, key, error.lift()), None)
233 (mk_cycle(query, tcx, key, error), None)
235234}
236235
237236#[inline(always)]
......@@ -275,7 +274,7 @@ fn wait_for_query<'tcx, C: QueryCache>(
275274
276275 (v, Some(index))
277276 }
278 Err(cycle) => (mk_cycle(query, tcx, key, cycle.lift()), None),
277 Err(cycle) => (mk_cycle(query, tcx, key, cycle), None),
279278 }
280279}
281280
compiler/rustc_query_impl/src/from_cycle_error.rs+11-7
......@@ -45,7 +45,11 @@ pub(crate) fn specialize_query_vtables<'tcx>(vtables: &mut QueryVTables<'tcx>) {
4545 |tcx, _, cycle, guar| erase_val(layout_of(tcx, cycle, guar));
4646}
4747
48pub(crate) fn default<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError, query_name: &str) -> ! {
48pub(crate) fn default<'tcx>(
49 tcx: TyCtxt<'tcx>,
50 cycle_error: CycleError<'tcx>,
51 query_name: &str,
52) -> ! {
4953 let Some(guar) = tcx.sess.dcx().has_errors() else {
5054 bug!(
5155 "`from_cycle_error_default` on query `{query_name}` called without errors: {:#?}",
......@@ -82,7 +86,7 @@ fn fn_sig<'tcx>(
8286
8387fn check_representability<'tcx>(
8488 tcx: TyCtxt<'tcx>,
85 cycle_error: CycleError,
89 cycle_error: CycleError<'tcx>,
8690 _guar: ErrorGuaranteed,
8791) -> ! {
8892 let mut item_and_field_ids = Vec::new();
......@@ -91,7 +95,7 @@ fn check_representability<'tcx>(
9195 if info.frame.dep_kind == DepKind::check_representability
9296 && let Some(field_id) = info.frame.def_id
9397 && let Some(field_id) = field_id.as_local()
94 && let Some(DefKind::Field) = info.frame.info.def_kind
98 && let Some(DefKind::Field) = info.frame.tagged_key.def_kind(tcx)
9599 {
96100 let parent_id = tcx.parent(field_id.to_def_id());
97101 let item_id = match tcx.def_kind(parent_id) {
......@@ -118,7 +122,7 @@ fn check_representability<'tcx>(
118122
119123fn variances_of<'tcx>(
120124 tcx: TyCtxt<'tcx>,
121 cycle_error: CycleError,
125 cycle_error: CycleError<'tcx>,
122126 _guar: ErrorGuaranteed,
123127) -> &'tcx [ty::Variance] {
124128 search_for_cycle_permutation(
......@@ -164,7 +168,7 @@ fn search_for_cycle_permutation<Q, T>(
164168
165169fn layout_of<'tcx>(
166170 tcx: TyCtxt<'tcx>,
167 cycle_error: CycleError,
171 cycle_error: CycleError<'tcx>,
168172 _guar: ErrorGuaranteed,
169173) -> Result<TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> {
170174 let diag = search_for_cycle_permutation(
......@@ -205,7 +209,7 @@ fn layout_of<'tcx>(
205209 continue;
206210 };
207211 let frame_span =
208 info.frame.info.default_span(cycle[(i + 1) % cycle.len()].span);
212 info.frame.tagged_key.default_span(tcx, cycle[(i + 1) % cycle.len()].span);
209213 if frame_span.is_dummy() {
210214 continue;
211215 }
......@@ -239,7 +243,7 @@ fn layout_of<'tcx>(
239243 ControlFlow::Continue(())
240244 }
241245 },
242 || report_cycle(tcx.sess, &cycle_error),
246 || report_cycle(tcx, &cycle_error),
243247 );
244248
245249 let guar = diag.emit();
compiler/rustc_query_impl/src/job.rs+31-28
......@@ -7,11 +7,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
77use rustc_errors::{Diag, DiagCtxtHandle};
88use rustc_hir::def::DefKind;
99use rustc_middle::query::{
10 CycleError, QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryStackDeferred, QueryStackFrame,
11 QueryWaiter,
10 CycleError, QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryStackFrame, QueryWaiter,
1211};
1312use rustc_middle::ty::TyCtxt;
14use rustc_session::Session;
1513use rustc_span::{DUMMY_SP, Span};
1614
1715use crate::execution::collect_active_jobs_from_all_queries;
......@@ -31,7 +29,7 @@ impl<'tcx> QueryJobMap<'tcx> {
3129 self.map.insert(id, info);
3230 }
3331
34 fn frame_of(&self, id: QueryJobId) -> &QueryStackFrame<QueryStackDeferred<'tcx>> {
32 fn frame_of(&self, id: QueryJobId) -> &QueryStackFrame<'tcx> {
3533 &self.map[&id].frame
3634 }
3735
......@@ -50,7 +48,7 @@ impl<'tcx> QueryJobMap<'tcx> {
5048
5149#[derive(Clone, Debug)]
5250pub(crate) struct QueryJobInfo<'tcx> {
53 pub(crate) frame: QueryStackFrame<QueryStackDeferred<'tcx>>,
51 pub(crate) frame: QueryStackFrame<'tcx>,
5452 pub(crate) job: QueryJob<'tcx>,
5553}
5654
......@@ -59,7 +57,7 @@ pub(crate) fn find_cycle_in_stack<'tcx>(
5957 job_map: QueryJobMap<'tcx>,
6058 current_job: &Option<QueryJobId>,
6159 span: Span,
62) -> CycleError<QueryStackDeferred<'tcx>> {
60) -> CycleError<'tcx> {
6361 // Find the waitee amongst `current_job` parents
6462 let mut cycle = Vec::new();
6563 let mut current_job = Option::clone(current_job);
......@@ -395,12 +393,12 @@ pub fn print_query_stack<'tcx>(
395393 let Some(query_info) = job_map.map.get(&query) else {
396394 break;
397395 };
398 let query_extra = query_info.frame.info.extract();
396 let description = query_info.frame.tagged_key.description(tcx);
399397 if Some(count_printed) < limit_frames || limit_frames.is_none() {
400398 // Only print to stderr as many stack frames as `num_frames` when present.
401399 dcx.struct_failure_note(format!(
402400 "#{} [{:?}] {}",
403 count_printed, query_info.frame.dep_kind, query_extra.description
401 count_printed, query_info.frame.dep_kind, description
404402 ))
405403 .with_span(query_info.job.span)
406404 .emit();
......@@ -411,7 +409,7 @@ pub fn print_query_stack<'tcx>(
411409 let _ = writeln!(
412410 file,
413411 "#{} [{:?}] {}",
414 count_total, query_info.frame.dep_kind, query_extra.description
412 count_total, query_info.frame.dep_kind, description
415413 );
416414 }
417415
......@@ -427,18 +425,18 @@ pub fn print_query_stack<'tcx>(
427425
428426#[inline(never)]
429427#[cold]
430pub(crate) fn report_cycle<'a>(
431 sess: &'a Session,
432 CycleError { usage, cycle: stack }: &CycleError,
433) -> Diag<'a> {
428pub(crate) fn report_cycle<'tcx>(
429 tcx: TyCtxt<'tcx>,
430 CycleError { usage, cycle: stack }: &CycleError<'tcx>,
431) -> Diag<'tcx> {
434432 assert!(!stack.is_empty());
435433
436 let span = stack[0].frame.info.default_span(stack[1 % stack.len()].span);
434 let span = stack[0].frame.tagged_key.default_span(tcx, stack[1 % stack.len()].span);
437435
438436 let mut cycle_stack = Vec::new();
439437
440438 use crate::error::StackCount;
441 let stack_bottom = stack[0].frame.info.description.to_owned();
439 let stack_bottom = stack[0].frame.tagged_key.description(tcx);
442440 let stack_count = if stack.len() == 1 {
443441 StackCount::Single { stack_bottom: stack_bottom.clone() }
444442 } else {
......@@ -447,27 +445,32 @@ pub(crate) fn report_cycle<'a>(
447445
448446 for i in 1..stack.len() {
449447 let frame = &stack[i].frame;
450 let span = frame.info.default_span(stack[(i + 1) % stack.len()].span);
448 let span = frame.tagged_key.default_span(tcx, stack[(i + 1) % stack.len()].span);
451449 cycle_stack
452 .push(crate::error::CycleStack { span, desc: frame.info.description.to_owned() });
450 .push(crate::error::CycleStack { span, desc: frame.tagged_key.description(tcx) });
453451 }
454452
455453 let mut cycle_usage = None;
456454 if let Some((span, ref query)) = *usage {
457455 cycle_usage = Some(crate::error::CycleUsage {
458 span: query.info.default_span(span),
459 usage: query.info.description.to_string(),
456 span: query.tagged_key.default_span(tcx, span),
457 usage: query.tagged_key.description(tcx),
460458 });
461459 }
462460
463 let alias =
464 if stack.iter().all(|entry| matches!(entry.frame.info.def_kind, Some(DefKind::TyAlias))) {
465 Some(crate::error::Alias::Ty)
466 } else if stack.iter().all(|entry| entry.frame.info.def_kind == Some(DefKind::TraitAlias)) {
467 Some(crate::error::Alias::Trait)
468 } else {
469 None
470 };
461 let alias = if stack
462 .iter()
463 .all(|entry| matches!(entry.frame.tagged_key.def_kind(tcx), Some(DefKind::TyAlias)))
464 {
465 Some(crate::error::Alias::Ty)
466 } else if stack
467 .iter()
468 .all(|entry| entry.frame.tagged_key.def_kind(tcx) == Some(DefKind::TraitAlias))
469 {
470 Some(crate::error::Alias::Trait)
471 } else {
472 None
473 };
471474
472475 let cycle_diag = crate::error::Cycle {
473476 span,
......@@ -479,5 +482,5 @@ pub(crate) fn report_cycle<'a>(
479482 note_span: (),
480483 };
481484
482 sess.dcx().create_err(cycle_diag)
485 tcx.sess.dcx().create_err(cycle_diag)
483486}
compiler/rustc_query_impl/src/lib.rs+1-1
......@@ -10,7 +10,7 @@
1010
1111use rustc_data_structures::sync::AtomicU64;
1212use rustc_middle::dep_graph;
13use rustc_middle::queries::{self, ExternProviders, Providers};
13use rustc_middle::queries::{self, ExternProviders, Providers, TaggedQueryKey};
1414use rustc_middle::query::on_disk_cache::OnDiskCache;
1515use rustc_middle::query::plumbing::{QuerySystem, QueryVTable};
1616use rustc_middle::query::{AsLocalQueryKey, QueryCache, QueryMode};
compiler/rustc_query_impl/src/plumbing.rs+12-53
......@@ -18,14 +18,10 @@ use rustc_middle::query::on_disk_cache::{
1818 AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex,
1919};
2020use rustc_middle::query::plumbing::QueryVTable;
21use rustc_middle::query::{
22 QueryCache, QueryJobId, QueryKey, QueryMode, QueryStackDeferred, QueryStackFrame,
23 QueryStackFrameExtra, erase,
24};
21use rustc_middle::query::{QueryCache, QueryJobId, QueryKey, QueryMode, QueryStackFrame, erase};
22use rustc_middle::ty::TyCtxt;
2523use rustc_middle::ty::codec::TyEncoder;
26use rustc_middle::ty::print::with_reduced_queries;
2724use rustc_middle::ty::tls::{self, ImplicitCtxt};
28use rustc_middle::ty::{self, TyCtxt};
2925use rustc_serialize::{Decodable, Encodable};
3026use rustc_span::DUMMY_SP;
3127use rustc_span::def_id::LOCAL_CRATE;
......@@ -47,7 +43,7 @@ fn depth_limit_error<'tcx>(tcx: TyCtxt<'tcx>, job: QueryJobId) {
4743
4844 tcx.sess.dcx().emit_fatal(QueryOverflow {
4945 span: info.job.span,
50 note: QueryOverflowNote { desc: info.frame.info.extract().description, depth },
46 note: QueryOverflowNote { desc: info.frame.tagged_key.description(tcx), depth },
5147 suggested_limit,
5248 crate_name: tcx.crate_name(LOCAL_CRATE),
5349 });
......@@ -90,60 +86,23 @@ pub(crate) fn start_query<R>(
9086 })
9187}
9288
93/// The deferred part of a deferred query stack frame.
94fn mk_query_stack_frame_extra<'tcx, Cache>(
95 (tcx, vtable, key): (TyCtxt<'tcx>, &'tcx QueryVTable<'tcx, Cache>, Cache::Key),
96) -> QueryStackFrameExtra
97where
98 Cache: QueryCache,
99 Cache::Key: QueryKey,
100{
101 let def_id = key.key_as_def_id();
102
103 // If reduced queries are requested, we may be printing a query stack due
104 // to a panic. Avoid using `default_span` and `def_kind` in that case.
105 let reduce_queries = with_reduced_queries();
106
107 // Avoid calling queries while formatting the description
108 let description = ty::print::with_no_queries!((vtable.description_fn)(tcx, key));
109 let description = if tcx.sess.verbose_internals() {
110 format!("{description} [{name:?}]", name = vtable.name)
111 } else {
112 description
113 };
114 let span = if vtable.dep_kind == DepKind::def_span || reduce_queries {
115 // The `def_span` query is used to calculate `default_span`,
116 // so exit to avoid infinite recursion.
117 None
118 } else {
119 Some(key.default_span(tcx))
120 };
121
122 let def_kind = if vtable.dep_kind == DepKind::def_kind || reduce_queries {
123 // Try to avoid infinite recursion.
124 None
125 } else {
126 def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
127 };
128 QueryStackFrameExtra::new(description, span, def_kind)
129}
130
131pub(crate) fn create_deferred_query_stack_frame<'tcx, C>(
132 tcx: TyCtxt<'tcx>,
89pub(crate) fn create_query_stack_frame<'tcx, C>(
13390 vtable: &'tcx QueryVTable<'tcx, C>,
13491 key: C::Key,
135) -> QueryStackFrame<QueryStackDeferred<'tcx>>
92) -> QueryStackFrame<'tcx>
13693where
13794 C: QueryCache<Key: QueryKey + DynSend + DynSync>,
13895 QueryVTable<'tcx, C>: DynSync,
13996{
140 let kind = vtable.dep_kind;
141
14297 let def_id: Option<DefId> = key.key_as_def_id();
14398 let def_id_for_ty_in_cycle: Option<DefId> = key.def_id_for_ty_in_cycle();
14499
145 let info = QueryStackDeferred::new((tcx, vtable, key), mk_query_stack_frame_extra);
146 QueryStackFrame::new(info, kind, def_id, def_id_for_ty_in_cycle)
100 QueryStackFrame {
101 tagged_key: (vtable.create_tagged_key)(key),
102 dep_kind: vtable.dep_kind,
103 def_id,
104 def_id_for_ty_in_cycle,
105 }
147106}
148107
149108pub(crate) fn encode_all_query_results<'tcx>(
......@@ -500,7 +459,7 @@ macro_rules! define_queries {
500459 }),
501460
502461 format_value: |value| format!("{:?}", erase::restore_val::<queries::$name::Value<'tcx>>(*value)),
503 description_fn: $crate::queries::_description_fns::$name,
462 create_tagged_key: TaggedQueryKey::$name,
504463 execute_query_fn: if incremental {
505464 query_impl::$name::execute_query_incr::__rust_end_short_backtrace
506465 } else {
rustfmt.toml-1
......@@ -20,7 +20,6 @@ ignore = [
2020 "/tests/incremental/", # These tests are somewhat sensitive to source code layout.
2121 "/tests/pretty/", # These tests are very sensitive to source code layout.
2222 "/tests/run-make/export", # These tests contain syntax errors.
23 "/tests/run-make/translation/test.rs", # This test contains syntax errors.
2423 "/tests/rustdoc-html/", # Some have syntax errors, some are whitespace-sensitive.
2524 "/tests/rustdoc-gui/", # Some tests are sensitive to source code layout.
2625 "/tests/rustdoc-ui/", # Some have syntax errors, some are whitespace-sensitive.
tests/debuginfo/basic-stepping.rs+55-2
......@@ -14,9 +14,9 @@
1414//@ revisions: default-mir-passes no-SingleUseConsts-mir-pass
1515//@ [no-SingleUseConsts-mir-pass] compile-flags: -Zmir-enable-passes=-SingleUseConsts
1616
17// === GDB TESTS ===================================================================================
18
1719//@ gdb-command: run
18// FIXME(#97083): Should we be able to break on initialization of zero-sized types?
19// FIXME(#97083): Right now the first breakable line is:
2020//@ gdb-check: let mut c = 27;
2121//@ gdb-command: next
2222//@ gdb-check: let d = c = 99;
......@@ -39,9 +39,62 @@
3939//@ gdb-command: next
4040//@ gdb-check: let m: *const() = &a;
4141
42// === LLDB TESTS ==================================================================================
43
44// Unlike gdb, lldb will display 7 lines of context by default. It seems
45// impossible to get it down to 1. The best we can do is to show the current
46// line and one above. That is not ideal, but it will do for now.
47//@ lldb-command: settings set stop-line-count-before 1
48//@ lldb-command: settings set stop-line-count-after 0
49
50//@ lldb-command: run
51// In `breakpoint_callback()` in `./src/etc/lldb_batchmode.py` we do
52// `SetSelectedFrame()`, which causes LLDB to show the current line and one line
53// before (since we changed `stop-line-count-before`). Note that
54// `normalize_whitespace()` in `lldb_batchmode.py` removes the newlines of the
55// output. So the current line and the line before actually ends up on the same
56// output line. That's fine.
57//@ lldb-check: [...]let mut c = 27;[...]
58//@ lldb-command: next
59// From now on we must manually `frame select` to see the current line (and one
60// line before).
61//@ lldb-command: frame select
62//@ lldb-check: [...]let d = c = 99;[...]
63//@ lldb-command: next
64//@ lldb-command: frame select
65//@ [no-SingleUseConsts-mir-pass] lldb-check: [...]let e = "hi bob";[...]
66//@ [no-SingleUseConsts-mir-pass] lldb-command: next
67//@ [no-SingleUseConsts-mir-pass] lldb-command: frame select
68//@ [no-SingleUseConsts-mir-pass] lldb-check: [...]let f = b"hi bob";[...]
69//@ [no-SingleUseConsts-mir-pass] lldb-command: next
70//@ [no-SingleUseConsts-mir-pass] lldb-command: frame select
71//@ [no-SingleUseConsts-mir-pass] lldb-check: [...]let g = b'9';[...]
72//@ [no-SingleUseConsts-mir-pass] lldb-command: next
73//@ [no-SingleUseConsts-mir-pass] lldb-command: frame select
74//@ lldb-check: [...]let h = ["whatever"; 8];[...]
75//@ lldb-command: next
76//@ lldb-command: frame select
77//@ lldb-check: [...]let i = [1,2,3,4];[...]
78//@ lldb-command: next
79//@ lldb-command: frame select
80//@ lldb-check: [...]let j = (23, "hi");[...]
81//@ lldb-command: next
82//@ lldb-command: frame select
83//@ lldb-check: [...]let k = 2..3;[...]
84//@ lldb-command: next
85//@ lldb-command: frame select
86//@ lldb-check: [...]let l = &i[k];[...]
87//@ lldb-command: next
88//@ lldb-command: frame select
89//@ lldb-check: [...]let m: *const() = &a;[...]
90
91#![allow(unused_assignments, unused_variables)]
92
4293fn main () {
4394 let a = (); // #break
4495 let b : [i32; 0] = [];
96 // FIXME(#97083): Should we be able to break on initialization of zero-sized types?
97 // FIXME(#97083): Right now the first breakable line is:
4598 let mut c = 27;
4699 let d = c = 99;
47100 let e = "hi bob";