|
| 1 | +use rustc_hir as hir; |
1 | 2 | use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
|
2 | 3 | use rustc_hir::intravisit;
|
3 | 4 | use rustc_middle::hir::nested_filter;
|
4 |
| -use rustc_middle::ty::TyCtxt; |
| 5 | +use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; |
5 | 6 | use rustc_span::sym;
|
6 | 7 |
|
7 | 8 | pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) {
|
@@ -87,3 +88,82 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
|
87 | 88 | }
|
88 | 89 | }
|
89 | 90 | }
|
| 91 | + |
| 92 | +pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) { |
| 93 | + for id in tcx.hir().items() { |
| 94 | + let def_id = id.owner_id.def_id; |
| 95 | + |
| 96 | + let Some(attr) = tcx.get_attr(def_id, sym::rustc_dump_vtable) else { |
| 97 | + continue; |
| 98 | + }; |
| 99 | + |
| 100 | + let vtable_entries = match tcx.hir().item(id).kind { |
| 101 | + hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => { |
| 102 | + let trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate_identity(); |
| 103 | + if trait_ref.has_non_region_param() { |
| 104 | + tcx.dcx().span_err( |
| 105 | + attr.span, |
| 106 | + "`rustc_dump_vtable` must be applied to non-generic impl", |
| 107 | + ); |
| 108 | + continue; |
| 109 | + } |
| 110 | + if !tcx.is_dyn_compatible(trait_ref.def_id) { |
| 111 | + tcx.dcx().span_err( |
| 112 | + attr.span, |
| 113 | + "`rustc_dump_vtable` must be applied to dyn-compatible trait", |
| 114 | + ); |
| 115 | + continue; |
| 116 | + } |
| 117 | + let Ok(trait_ref) = tcx |
| 118 | + .try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref) |
| 119 | + else { |
| 120 | + tcx.dcx().span_err( |
| 121 | + attr.span, |
| 122 | + "`rustc_dump_vtable` applied to impl header that cannot be normalized", |
| 123 | + ); |
| 124 | + continue; |
| 125 | + }; |
| 126 | + tcx.vtable_entries(ty::Binder::dummy(trait_ref)) |
| 127 | + } |
| 128 | + hir::ItemKind::TyAlias(_, _) => { |
| 129 | + let ty = tcx.type_of(def_id).instantiate_identity(); |
| 130 | + if ty.has_non_region_param() { |
| 131 | + tcx.dcx().span_err( |
| 132 | + attr.span, |
| 133 | + "`rustc_dump_vtable` must be applied to non-generic type", |
| 134 | + ); |
| 135 | + continue; |
| 136 | + } |
| 137 | + let Ok(ty) = |
| 138 | + tcx.try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) |
| 139 | + else { |
| 140 | + tcx.dcx().span_err( |
| 141 | + attr.span, |
| 142 | + "`rustc_dump_vtable` applied to type alias that cannot be normalized", |
| 143 | + ); |
| 144 | + continue; |
| 145 | + }; |
| 146 | + let ty::Dynamic(data, _, _) = *ty.kind() else { |
| 147 | + tcx.dcx().span_err(attr.span, "`rustc_dump_vtable` to type alias of dyn type"); |
| 148 | + continue; |
| 149 | + }; |
| 150 | + if let Some(principal) = data.principal() { |
| 151 | + tcx.vtable_entries( |
| 152 | + principal.map_bound(|principal| principal.with_self_ty(tcx, ty)), |
| 153 | + ) |
| 154 | + } else { |
| 155 | + TyCtxt::COMMON_VTABLE_ENTRIES |
| 156 | + } |
| 157 | + } |
| 158 | + _ => { |
| 159 | + tcx.dcx().span_err( |
| 160 | + attr.span, |
| 161 | + "`rustc_dump_vtable` only applies to impl, or type alias of dyn type", |
| 162 | + ); |
| 163 | + continue; |
| 164 | + } |
| 165 | + }; |
| 166 | + |
| 167 | + tcx.dcx().span_err(tcx.def_span(def_id), format!("vtable entries: {vtable_entries:#?}")); |
| 168 | + } |
| 169 | +} |
0 commit comments