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