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