rustc_hir_analysis/collect/
dump.rs1use rustc_hir as hir;
2use rustc_hir::def::DefKind;
3use rustc_hir::def_id::LocalDefId;
4use rustc_hir::{find_attr, intravisit};
5use rustc_middle::hir::nested_filter;
6use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, Unnormalized};
7use rustc_span::sym;
8
9pub(crate) fn generics(tcx: TyCtxt<'_>) {
10 for did in tcx.hir_crate_items(()).definitions() {
11 if did == hir::def_id::CRATE_DEF_ID {
12 continue;
13 }
14
15 if {
{
'done:
{
for i in ::rustc_hir::attrs::HasAttrs::get_attrs(did, &tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcDumpGenerics) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(tcx, did, RustcDumpGenerics) {
16 let span = tcx.def_span(did);
17
18 let mut diag =
19 tcx.dcx().struct_span_err(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1:?}",
sym::rustc_dump_generics, did))
})format!("{}: {did:?}", sym::rustc_dump_generics));
20
21 let generics = tcx.generics_of(did);
22 diag.span_note(tcx.def_span(did), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:#?}", generics))
})format!("{generics:#?}"));
23 diag.emit();
24 }
25 }
26}
27
28pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) {
29 if !{
'done:
{
for i in tcx.hir_krate_attrs() {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcDumpHiddenTypeOfOpaques)
=> {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()find_attr!(tcx, crate, RustcDumpHiddenTypeOfOpaques) {
30 return;
31 }
32 for id in tcx.hir_crate_items(()).opaques() {
33 if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
34 | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } =
35 tcx.hir_expect_opaque_ty(id).origin
36 && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)
37 && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
38 {
39 continue;
40 }
41
42 let ty = tcx.type_of(id).instantiate_identity().skip_norm_wip();
43 let span = tcx.def_span(id);
44 tcx.dcx().emit_err(crate::diagnostics::TypeOf { span, ty });
45 }
46}
47
48pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
49 for id in tcx.hir_crate_items(()).owners() {
50 #[expect(deprecated)] let attrs = tcx.get_all_attrs(id);
52
53 if {
{
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcDumpPredicates) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, RustcDumpPredicates) {
54 let preds = tcx
55 .predicates_of(id)
56 .instantiate_identity(tcx)
57 .predicates
58 .into_iter()
59 .map(Unnormalized::skip_norm_wip);
60 let span = tcx.def_span(id);
61
62 let mut diag = tcx.dcx().struct_span_err(span, sym::rustc_dump_predicates.as_str());
63 for pred in preds {
64 diag.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", pred))
})format!("{pred:?}"));
65 }
66 diag.emit();
67 }
68
69 if {
{
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcDumpItemBounds) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, RustcDumpItemBounds) {
70 let name = sym::rustc_dump_item_bounds.as_str();
71
72 match tcx.def_kind(id) {
73 DefKind::AssocTy => {
74 let bounds = tcx.item_bounds(id).instantiate_identity().skip_norm_wip();
75 let span = tcx.def_span(id);
76
77 let mut diag = tcx.dcx().struct_span_err(span, name);
78 for bound in bounds {
79 diag.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", bound))
})format!("{bound:?}"));
80 }
81 diag.emit()
82 }
83 kind => tcx.dcx().span_delayed_bug(
84 tcx.def_span(id),
85 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("attr parsing didn\'t report an error for `#[{0}]` on {1:?}",
name, kind))
})format!("attr parsing didn't report an error for `#[{name}]` on {kind:?}"),
86 ),
87 };
88 }
89 }
90}
91
92pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
93 for iid in tcx.hir_free_items() {
94 let did = iid.owner_id.def_id;
95 if {
{
'done:
{
for i in ::rustc_hir::attrs::HasAttrs::get_attrs(did, &tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcDumpDefParents) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(tcx, did, RustcDumpDefParents) {
96 struct AnonConstFinder<'tcx> {
97 tcx: TyCtxt<'tcx>,
98 anon_consts: Vec<LocalDefId>,
99 }
100
101 impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> {
102 type NestedFilter = nested_filter::All;
103
104 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
105 self.tcx
106 }
107
108 fn visit_anon_const(&mut self, c: &'tcx rustc_hir::AnonConst) {
109 self.anon_consts.push(c.def_id);
110 intravisit::walk_anon_const(self, c)
111 }
112 }
113
114 let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: ::alloc::vec::Vec::new()vec![] };
118 intravisit::walk_item(&mut anon_ct_finder, tcx.hir_item(iid));
119
120 for did in [did].into_iter().chain(anon_ct_finder.anon_consts) {
121 let span = tcx.def_span(did);
122
123 let mut diag = tcx
124 .dcx()
125 .struct_span_err(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1:?}",
sym::rustc_dump_def_parents, did))
})format!("{}: {did:?}", sym::rustc_dump_def_parents));
126
127 let mut current_did = did.to_def_id();
128 while let Some(parent_did) = tcx.opt_parent(current_did) {
129 current_did = parent_did;
130 diag.span_note(tcx.def_span(parent_did), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", parent_did))
})format!("{parent_did:?}"));
131 }
132 diag.emit();
133 }
134 }
135 }
136}
137
138pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
139 for id in tcx.hir_free_items() {
140 let def_id = id.owner_id.def_id;
141
142 let Some(&attr_span) = {
{
'done:
{
for i in ::rustc_hir::attrs::HasAttrs::get_attrs(def_id, &tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcDumpVtable(span)) => {
break 'done Some(span);
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}find_attr!(tcx, def_id, RustcDumpVtable(span) => span) else {
143 continue;
144 };
145
146 let vtable_entries = match tcx.hir_item(id).kind {
147 hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => {
148 let trait_ref = tcx.impl_trait_ref(def_id).instantiate_identity();
149 if trait_ref.skip_normalization().has_non_region_param() {
150 tcx.dcx().span_err(
151 attr_span,
152 "`rustc_dump_vtable` must be applied to non-generic impl",
153 );
154 continue;
155 }
156 if !tcx.is_dyn_compatible(trait_ref.skip_normalization().def_id) {
157 tcx.dcx().span_err(
158 attr_span,
159 "`rustc_dump_vtable` must be applied to dyn-compatible trait",
160 );
161 continue;
162 }
163 let Ok(trait_ref) = tcx
164 .try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref)
165 else {
166 tcx.dcx().span_err(
167 attr_span,
168 "`rustc_dump_vtable` applied to impl header that cannot be normalized",
169 );
170 continue;
171 };
172 tcx.vtable_entries(trait_ref)
173 }
174 hir::ItemKind::TyAlias(..) => {
175 let ty = tcx.type_of(def_id).instantiate_identity();
176 if ty.has_non_region_param() {
177 tcx.dcx().span_err(
178 attr_span,
179 "`rustc_dump_vtable` must be applied to non-generic type",
180 );
181 continue;
182 }
183 let Ok(ty) =
184 tcx.try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
185 else {
186 tcx.dcx().span_err(
187 attr_span,
188 "`rustc_dump_vtable` applied to type alias that cannot be normalized",
189 );
190 continue;
191 };
192 let ty::Dynamic(data, _) = *ty.kind() else {
193 tcx.dcx().span_err(attr_span, "`rustc_dump_vtable` to type alias of dyn type");
194 continue;
195 };
196 if let Some(principal) = data.principal() {
197 tcx.vtable_entries(
198 tcx.instantiate_bound_regions_with_erased(principal).with_self_ty(tcx, ty),
199 )
200 } else {
201 TyCtxt::COMMON_VTABLE_ENTRIES
202 }
203 }
204 _ => {
205 tcx.dcx().span_err(
206 attr_span,
207 "`rustc_dump_vtable` only applies to impl, or type alias of dyn type",
208 );
209 continue;
210 }
211 };
212
213 tcx.dcx().span_err(tcx.def_span(def_id), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("vtable entries: {0:#?}",
vtable_entries))
})format!("vtable entries: {vtable_entries:#?}"));
214 }
215}