rustc_interface/
callbacks.rs1use std::fmt;
13use std::fmt::Arguments;
14use std::panic::Location;
15
16use rustc_errors::{DiagInner, DiagLocation, Level};
17use rustc_middle::dep_graph::{QuerySideEffect, TaskDepsRef};
18use rustc_middle::ty::tls;
19use rustc_span::{Span, Symbol};
20
21fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
22 tls::with_context_opt(|icx| {
23 if let Some(icx) = icx {
24 let tracks_deps = match icx.task_deps {
27 TaskDepsRef::Allow(..) => true,
28 TaskDepsRef::EvalAlways | TaskDepsRef::Ignore | TaskDepsRef::Forbid => false,
29 };
30 if tracks_deps {
31 let _span = icx.tcx.source_span(def_id);
32 if true {
{
match (&_span.data_untracked().parent, &None) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(_span.data_untracked().parent, None);
34 }
35 }
36 })
37}
38
39fn track_diagnostic<R>(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
43 tls::with_context_opt(|icx| {
44 if let Some(icx) = icx {
45 icx.tcx.dep_graph.record_diagnostic(icx.tcx, &diagnostic);
46
47 let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..*icx };
49 tls::enter_context(&icx, move || (*f)(diagnostic))
50 } else {
51 (*f)(diagnostic)
53 }
54 })
55}
56
57fn track_feature(feature: Symbol) {
58 tls::with_context_opt(|icx| {
59 let Some(icx) = icx else {
60 return;
61 };
62 let tcx = icx.tcx;
63
64 if let Some(dep_node_index) = tcx.query_system.used_features.lock().get(&feature).copied() {
65 tcx.dep_graph.read_index(dep_node_index);
66 } else {
67 let dep_node_index = tcx
68 .dep_graph
69 .encode_side_effect(tcx, QuerySideEffect::CheckFeature { symbol: feature });
70 tcx.query_system.used_features.lock().insert(feature, dep_node_index);
71 tcx.dep_graph.read_index(dep_node_index);
72 }
73 })
74}
75
76fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 f.write_fmt(format_args!("DefId({0}:{1}", def_id.krate, def_id.index.index()))write!(f, "DefId({}:{}", def_id.krate, def_id.index.index())?;
80 tls::with_opt(|opt_tcx| {
81 if let Some(tcx) = opt_tcx {
82 f.write_fmt(format_args!(" ~ {0}", tcx.def_path_debug_str(def_id)))write!(f, " ~ {}", tcx.def_path_debug_str(def_id))?;
83 }
84 Ok(())
85 })?;
86 f.write_fmt(format_args!(")"))write!(f, ")")
87}
88
89fn emit_bug_diagnostic(
91 span: Option<Span>,
92 args: Arguments<'_>,
93 location: &'static Location<'static>,
94) -> bool {
95 tls::with_opt(move |tcx| {
96 if let Some(tcx) = tcx {
97 let mut diag = DiagInner::new(Level::Bug, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", location, args))
})format!("{location}: {args}"));
98 if let Some(span) = span {
99 diag.span = span.into();
100 }
101 diag.emitted_at = DiagLocation::from_location(location);
102 tcx.dcx().emit_diagnostic(diag);
106 true
107 } else {
108 false
109 }
110 })
111}
112
113pub fn setup_callbacks() {
116 rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_)));
117 rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
118 rustc_errors::TRACK_DIAGNOSTIC.swap(&(track_diagnostic as _));
119 rustc_feature::TRACK_FEATURE.swap(&(track_feature as _));
120 rustc_span::macros::EMIT_BUG_DIAGNOSTIC.swap(&(emit_bug_diagnostic as _));
121 rustc_expand_queries::setup_callbacks();
122}