1use hir::def::Namespace;
2use rustc_data_structures::fx::FxHashSet;
3use rustc_data_structures::sso::SsoHashSet;
4use rustc_hir as hir;
5use rustc_hir::def_id::{CrateNum, DefId};
6use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
7use tracing::{debug, instrument, trace};
8
9use crate::ty::{self, GenericArg, Ty, TyCtxt};
10
11mod pretty;
13pub use self::pretty::*;
14use super::Lift;
15
16pub type PrintError = std::fmt::Error;
17
18pub trait Print<'tcx, P> {
19 fn print(&self, p: &mut P) -> Result<(), PrintError>;
20}
21
22pub trait Printer<'tcx>: Sized {
29 fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
30
31 fn print_def_path(
33 &mut self,
34 def_id: DefId,
35 args: &'tcx [GenericArg<'tcx>],
36 ) -> Result<(), PrintError> {
37 self.default_print_def_path(def_id, args)
38 }
39
40 fn print_impl_path(
42 &mut self,
43 impl_def_id: DefId,
44 args: &'tcx [GenericArg<'tcx>],
45 ) -> Result<(), PrintError> {
46 let tcx = self.tcx();
47 let self_ty = tcx.type_of(impl_def_id);
48 let impl_trait_ref = tcx.impl_opt_trait_ref(impl_def_id);
49 let (self_ty, impl_trait_ref) = if tcx.generics_of(impl_def_id).count() <= args.len() {
50 (
51 self_ty.instantiate(tcx, args).skip_norm_wip(),
52 impl_trait_ref
53 .map(|impl_trait_ref| impl_trait_ref.instantiate(tcx, args).skip_norm_wip()),
54 )
55 } else {
56 (
59 self_ty.instantiate_identity().skip_norm_wip(),
60 impl_trait_ref
61 .map(|impl_trait_ref| impl_trait_ref.instantiate_identity().skip_norm_wip()),
62 )
63 };
64
65 self.default_print_impl_path(impl_def_id, self_ty, impl_trait_ref)
66 }
67
68 fn print_region(&mut self, region: ty::Region<'tcx>) -> Result<(), PrintError>;
70
71 fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError>;
73
74 fn print_dyn_existential(
76 &mut self,
77 predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
78 ) -> Result<(), PrintError>;
79
80 fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError>;
82
83 fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError>;
85
86 fn print_path_with_simple(
93 &mut self,
94 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
95 disambiguated_data: &DisambiguatedDefPathData,
96 ) -> Result<(), PrintError>;
97
98 fn print_path_with_impl(
103 &mut self,
104 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
105 self_ty: Ty<'tcx>,
106 trait_ref: Option<ty::TraitRef<'tcx>>,
107 ) -> Result<(), PrintError>;
108
109 fn print_path_with_generic_args(
116 &mut self,
117 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
118 args: &[GenericArg<'tcx>],
119 ) -> Result<(), PrintError>;
120
121 fn print_path_with_qualified(
124 &mut self,
125 self_ty: Ty<'tcx>,
126 trait_ref: Option<ty::TraitRef<'tcx>>,
127 ) -> Result<(), PrintError>;
128
129 fn print_coroutine_with_kind(
130 &mut self,
131 def_id: DefId,
132 parent_args: &'tcx [GenericArg<'tcx>],
133 kind: Ty<'tcx>,
134 ) -> Result<(), PrintError> {
135 self.print_path_with_generic_args(|p| p.print_def_path(def_id, parent_args), &[kind.into()])
136 }
137
138 fn reset_path(&mut self) -> Result<(), PrintError> {
139 Ok(())
140 }
141
142 fn should_omit_parent_def_path(&self, _parent_def_id: DefId) -> bool {
143 false
144 }
145
146 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("default_print_def_path",
"rustc_middle::ty::print", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/print/mod.rs"),
::tracing_core::__macro_support::Option::Some(147u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::print"),
::tracing_core::field::FieldSet::new(&["def_id", "args"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&args)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Result<(), PrintError> = loop {};
return __tracing_attr_fake_return;
}
{
let key = self.tcx().def_key(def_id);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/ty/print/mod.rs:154",
"rustc_middle::ty::print", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/print/mod.rs"),
::tracing_core::__macro_support::Option::Some(154u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::print"),
::tracing_core::field::FieldSet::new(&["key"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&key) as
&dyn Value))])
});
} else { ; }
};
match key.disambiguated_data.data {
DefPathData::CrateRoot => {
if !key.parent.is_none() {
::core::panicking::panic("assertion failed: key.parent.is_none()")
};
self.print_crate_name(def_id.krate)
}
DefPathData::Impl => self.print_impl_path(def_id, args),
_ => {
let parent_def_id =
DefId { index: key.parent.unwrap(), ..def_id };
let mut parent_args = args;
let mut trait_qualify_parent = false;
if !args.is_empty() {
let generics = self.tcx().generics_of(def_id);
parent_args =
&args[..generics.parent_count.min(args.len())];
match key.disambiguated_data.data {
DefPathData::Closure => {
if let Some(hir::CoroutineKind::Desugared(_,
hir::CoroutineSource::Closure)) =
self.tcx().coroutine_kind(def_id) &&
args.len() > parent_args.len() {
return self.print_coroutine_with_kind(def_id, parent_args,
args[parent_args.len()].expect_ty());
} else {}
}
DefPathData::SyntheticCoroutineBody => {}
DefPathData::AnonConst => {}
_ => {
if !generics.is_own_empty() &&
args.len() >= generics.count() {
let args = generics.own_args_no_defaults(self.tcx(), args);
return self.print_path_with_generic_args(|p|
p.print_def_path(def_id, parent_args), args);
}
}
}
trait_qualify_parent =
generics.has_self && generics.parent == Some(parent_def_id)
&& parent_args.len() == generics.parent_count &&
self.tcx().generics_of(parent_def_id).parent_count == 0;
}
let omit_parent =
#[allow(non_exhaustive_omitted_patterns)] match key.disambiguated_data.data
{
DefPathData::TypeNs(..) => true,
_ => false,
} && self.should_omit_parent_def_path(parent_def_id);
self.print_path_with_simple(|p: &mut Self|
{
if omit_parent {
p.reset_path()?;
Ok(())
} else if trait_qualify_parent {
let trait_ref =
ty::TraitRef::new(p.tcx(), parent_def_id,
parent_args.iter().copied());
p.print_path_with_qualified(trait_ref.self_ty(),
Some(trait_ref))
} else { p.print_def_path(parent_def_id, parent_args) }
}, &key.disambiguated_data)
}
}
}
}
}#[instrument(skip(self), level = "debug")]
148 fn default_print_def_path(
149 &mut self,
150 def_id: DefId,
151 args: &'tcx [GenericArg<'tcx>],
152 ) -> Result<(), PrintError> {
153 let key = self.tcx().def_key(def_id);
154 debug!(?key);
155
156 match key.disambiguated_data.data {
157 DefPathData::CrateRoot => {
158 assert!(key.parent.is_none());
159 self.print_crate_name(def_id.krate)
160 }
161
162 DefPathData::Impl => self.print_impl_path(def_id, args),
163
164 _ => {
165 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
166
167 let mut parent_args = args;
168 let mut trait_qualify_parent = false;
169 if !args.is_empty() {
170 let generics = self.tcx().generics_of(def_id);
171 parent_args = &args[..generics.parent_count.min(args.len())];
172
173 match key.disambiguated_data.data {
174 DefPathData::Closure => {
175 if let Some(hir::CoroutineKind::Desugared(
178 _,
179 hir::CoroutineSource::Closure,
180 )) = self.tcx().coroutine_kind(def_id)
181 && args.len() > parent_args.len()
182 {
183 return self.print_coroutine_with_kind(
184 def_id,
185 parent_args,
186 args[parent_args.len()].expect_ty(),
187 );
188 } else {
189 }
191 }
192 DefPathData::SyntheticCoroutineBody => {
193 }
196 DefPathData::AnonConst => {}
200
201 _ => {
204 if !generics.is_own_empty() && args.len() >= generics.count() {
205 let args = generics.own_args_no_defaults(self.tcx(), args);
206 return self.print_path_with_generic_args(
207 |p| p.print_def_path(def_id, parent_args),
208 args,
209 );
210 }
211 }
212 }
213
214 trait_qualify_parent = generics.has_self
217 && generics.parent == Some(parent_def_id)
218 && parent_args.len() == generics.parent_count
219 && self.tcx().generics_of(parent_def_id).parent_count == 0;
220 }
221
222 let omit_parent = matches!(key.disambiguated_data.data, DefPathData::TypeNs(..))
223 && self.should_omit_parent_def_path(parent_def_id);
224
225 self.print_path_with_simple(
226 |p: &mut Self| {
227 if omit_parent {
228 p.reset_path()?;
229 Ok(())
230 } else if trait_qualify_parent {
231 let trait_ref = ty::TraitRef::new(
232 p.tcx(),
233 parent_def_id,
234 parent_args.iter().copied(),
235 );
236 p.print_path_with_qualified(trait_ref.self_ty(), Some(trait_ref))
237 } else {
238 p.print_def_path(parent_def_id, parent_args)
239 }
240 },
241 &key.disambiguated_data,
242 )
243 }
244 }
245 }
246
247 fn default_print_impl_path(
248 &mut self,
249 impl_def_id: DefId,
250 self_ty: Ty<'tcx>,
251 impl_trait_ref: Option<ty::TraitRef<'tcx>>,
252 ) -> Result<(), PrintError> {
253 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/ty/print/mod.rs:253",
"rustc_middle::ty::print", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/print/mod.rs"),
::tracing_core::__macro_support::Option::Some(253u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::print"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("default_print_impl_path: impl_def_id={0:?}, self_ty={1}, impl_trait_ref={2:?}",
impl_def_id, self_ty, impl_trait_ref) as &dyn Value))])
});
} else { ; }
};debug!(
254 "default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
255 impl_def_id, self_ty, impl_trait_ref
256 );
257
258 let key = self.tcx().def_key(impl_def_id);
259 let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
260
261 let in_self_mod = match characteristic_def_id_of_type(self_ty) {
267 None => false,
268 Some(ty_def_id) => self.tcx().parent(ty_def_id) == parent_def_id,
269 };
270 let in_trait_mod = match impl_trait_ref {
271 None => false,
272 Some(trait_ref) => self.tcx().parent(trait_ref.def_id) == parent_def_id,
273 };
274
275 if !in_self_mod && !in_trait_mod {
276 self.print_path_with_impl(
280 |p| p.print_def_path(parent_def_id, &[]),
281 self_ty,
282 impl_trait_ref,
283 )
284 } else {
285 self.print_path_with_qualified(self_ty, impl_trait_ref)
288 }
289 }
290}
291
292fn characteristic_def_id_of_type_cached<'a>(
302 ty: Ty<'a>,
303 visited: &mut SsoHashSet<Ty<'a>>,
304) -> Option<DefId> {
305 match *ty.kind() {
306 ty::Adt(adt_def, _) => Some(adt_def.did()),
307
308 ty::Dynamic(data, ..) => data.principal_def_id(),
309
310 ty::Pat(subty, _) | ty::Array(subty, _) | ty::Slice(subty) => {
311 characteristic_def_id_of_type_cached(subty, visited)
312 }
313
314 ty::RawPtr(ty, _) => characteristic_def_id_of_type_cached(ty, visited),
315
316 ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited),
317
318 ty::Tuple(tys) => tys.iter().find_map(|ty| {
319 if visited.insert(ty) {
320 return characteristic_def_id_of_type_cached(ty, visited);
321 }
322 return None;
323 }),
324
325 ty::FnDef(def_id, _)
326 | ty::Closure(def_id, _)
327 | ty::CoroutineClosure(def_id, _)
328 | ty::Coroutine(def_id, _)
329 | ty::CoroutineWitness(def_id, _)
330 | ty::Foreign(def_id) => Some(def_id),
331
332 ty::Bool
333 | ty::Char
334 | ty::Int(_)
335 | ty::Uint(_)
336 | ty::Str
337 | ty::FnPtr(..)
338 | ty::UnsafeBinder(_)
339 | ty::Alias(..)
340 | ty::Placeholder(..)
341 | ty::Param(_)
342 | ty::Infer(_)
343 | ty::Bound(..)
344 | ty::Error(_)
345 | ty::Never
346 | ty::Float(_) => None,
347 }
348}
349pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
350 characteristic_def_id_of_type_cached(ty, &mut SsoHashSet::new())
351}
352
353impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'tcx> {
354 fn print(&self, p: &mut P) -> Result<(), PrintError> {
355 p.print_region(*self)
356 }
357}
358
359impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
360 fn print(&self, p: &mut P) -> Result<(), PrintError> {
361 p.print_type(*self)
362 }
363}
364
365impl<'tcx, P: Printer<'tcx> + std::fmt::Write> Print<'tcx, P> for ty::Instance<'tcx> {
366 fn print(&self, cx: &mut P) -> Result<(), PrintError> {
367 cx.print_def_path(self.def_id(), self.args)?;
368 match self.def {
369 ty::InstanceKind::Item(_) => {}
370 ty::InstanceKind::VTableShim(_) => cx.write_str(" - shim(vtable)")?,
371 ty::InstanceKind::ReifyShim(_, None) => cx.write_str(" - shim(reify)")?,
372 ty::InstanceKind::ReifyShim(_, Some(ty::ReifyReason::FnPtr)) => {
373 cx.write_str(" - shim(reify-fnptr)")?
374 }
375 ty::InstanceKind::ReifyShim(_, Some(ty::ReifyReason::Vtable)) => {
376 cx.write_str(" - shim(reify-vtable)")?
377 }
378 ty::InstanceKind::ThreadLocalShim(_) => cx.write_str(" - shim(tls)")?,
379 ty::InstanceKind::Intrinsic(_) => cx.write_str(" - intrinsic")?,
380 ty::InstanceKind::Virtual(_, num) => cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - virtual#{0}", num))
})format!(" - virtual#{num}"))?,
381 ty::InstanceKind::FnPtrShim(_, ty) => cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim({0})", ty))
})format!(" - shim({ty})"))?,
382 ty::InstanceKind::ClosureOnceShim { .. } => cx.write_str(" - shim")?,
383 ty::InstanceKind::ConstructCoroutineInClosureShim { .. } => cx.write_str(" - shim")?,
384 ty::InstanceKind::DropGlue(_, None) => cx.write_str(" - shim(None)")?,
385 ty::InstanceKind::DropGlue(_, Some(ty)) => {
386 cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim(Some({0}))", ty))
})format!(" - shim(Some({ty}))"))?
387 }
388 ty::InstanceKind::CloneShim(_, ty) => cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim({0})", ty))
})format!(" - shim({ty})"))?,
389 ty::InstanceKind::FnPtrAddrShim(_, ty) => cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim({0})", ty))
})format!(" - shim({ty})"))?,
390 ty::InstanceKind::FutureDropPollShim(_, proxy_ty, impl_ty) => {
391 cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - dropshim({0}-{1})", proxy_ty,
impl_ty))
})format!(" - dropshim({proxy_ty}-{impl_ty})"))?
392 }
393 ty::InstanceKind::AsyncDropGlue(_, ty) => cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim({0})", ty))
})format!(" - shim({ty})"))?,
394 ty::InstanceKind::AsyncDropGlueCtorShim(_, ty) => {
395 cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim(Some({0}))", ty))
})format!(" - shim(Some({ty}))"))?
396 }
397 };
398 Ok(())
399 }
400}
401
402impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
403 fn print(&self, p: &mut P) -> Result<(), PrintError> {
404 p.print_dyn_existential(self)
405 }
406}
407
408impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> {
409 fn print(&self, p: &mut P) -> Result<(), PrintError> {
410 p.print_const(*self)
411 }
412}
413
414impl<T> rustc_type_ir::ir_print::IrPrint<T> for TyCtxt<'_>
415where
416 T: Copy + for<'a, 'tcx> Lift<TyCtxt<'tcx>, Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>>,
417{
418 fn print(t: &T, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
419 ty::tls::with(|tcx| {
420 let mut p = FmtPrinter::new(tcx, Namespace::TypeNS);
421 tcx.lift(*t).expect("could not lift for printing").print(&mut p)?;
422 fmt.write_str(&p.into_buffer())?;
423 Ok(())
424 })
425 }
426
427 fn print_debug(t: &T, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
428 { let _guard = NoTrimmedGuard::new(); Self::print(t, fmt) }with_no_trimmed_paths!(Self::print(t, fmt))
429 }
430}