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),
52 impl_trait_ref.map(|impl_trait_ref| impl_trait_ref.instantiate(tcx, args)),
53 )
54 } else {
55 (
58 self_ty.instantiate_identity(),
59 impl_trait_ref.map(|impl_trait_ref| impl_trait_ref.instantiate_identity()),
60 )
61 };
62
63 self.default_print_impl_path(impl_def_id, self_ty, impl_trait_ref)
64 }
65
66 fn print_region(&mut self, region: ty::Region<'tcx>) -> Result<(), PrintError>;
68
69 fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError>;
71
72 fn print_dyn_existential(
74 &mut self,
75 predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
76 ) -> Result<(), PrintError>;
77
78 fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError>;
80
81 fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError>;
83
84 fn print_path_with_simple(
91 &mut self,
92 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
93 disambiguated_data: &DisambiguatedDefPathData,
94 ) -> Result<(), PrintError>;
95
96 fn print_path_with_impl(
101 &mut self,
102 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
103 self_ty: Ty<'tcx>,
104 trait_ref: Option<ty::TraitRef<'tcx>>,
105 ) -> Result<(), PrintError>;
106
107 fn print_path_with_generic_args(
114 &mut self,
115 print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
116 args: &[GenericArg<'tcx>],
117 ) -> Result<(), PrintError>;
118
119 fn print_path_with_qualified(
122 &mut self,
123 self_ty: Ty<'tcx>,
124 trait_ref: Option<ty::TraitRef<'tcx>>,
125 ) -> Result<(), PrintError>;
126
127 fn print_coroutine_with_kind(
128 &mut self,
129 def_id: DefId,
130 parent_args: &'tcx [GenericArg<'tcx>],
131 kind: Ty<'tcx>,
132 ) -> Result<(), PrintError> {
133 self.print_path_with_generic_args(|p| p.print_def_path(def_id, parent_args), &[kind.into()])
134 }
135
136 fn reset_path(&mut self) -> Result<(), PrintError> {
137 Ok(())
138 }
139
140 fn should_omit_parent_def_path(&self, _parent_def_id: DefId) -> bool {
141 false
142 }
143
144 #[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(145u32),
::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:152",
"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(152u32),
::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")]
146 fn default_print_def_path(
147 &mut self,
148 def_id: DefId,
149 args: &'tcx [GenericArg<'tcx>],
150 ) -> Result<(), PrintError> {
151 let key = self.tcx().def_key(def_id);
152 debug!(?key);
153
154 match key.disambiguated_data.data {
155 DefPathData::CrateRoot => {
156 assert!(key.parent.is_none());
157 self.print_crate_name(def_id.krate)
158 }
159
160 DefPathData::Impl => self.print_impl_path(def_id, args),
161
162 _ => {
163 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
164
165 let mut parent_args = args;
166 let mut trait_qualify_parent = false;
167 if !args.is_empty() {
168 let generics = self.tcx().generics_of(def_id);
169 parent_args = &args[..generics.parent_count.min(args.len())];
170
171 match key.disambiguated_data.data {
172 DefPathData::Closure => {
173 if let Some(hir::CoroutineKind::Desugared(
176 _,
177 hir::CoroutineSource::Closure,
178 )) = self.tcx().coroutine_kind(def_id)
179 && args.len() > parent_args.len()
180 {
181 return self.print_coroutine_with_kind(
182 def_id,
183 parent_args,
184 args[parent_args.len()].expect_ty(),
185 );
186 } else {
187 }
189 }
190 DefPathData::SyntheticCoroutineBody => {
191 }
194 DefPathData::AnonConst => {}
198
199 _ => {
202 if !generics.is_own_empty() && args.len() >= generics.count() {
203 let args = generics.own_args_no_defaults(self.tcx(), args);
204 return self.print_path_with_generic_args(
205 |p| p.print_def_path(def_id, parent_args),
206 args,
207 );
208 }
209 }
210 }
211
212 trait_qualify_parent = generics.has_self
215 && generics.parent == Some(parent_def_id)
216 && parent_args.len() == generics.parent_count
217 && self.tcx().generics_of(parent_def_id).parent_count == 0;
218 }
219
220 let omit_parent = matches!(key.disambiguated_data.data, DefPathData::TypeNs(..))
221 && self.should_omit_parent_def_path(parent_def_id);
222
223 self.print_path_with_simple(
224 |p: &mut Self| {
225 if omit_parent {
226 p.reset_path()?;
227 Ok(())
228 } else if trait_qualify_parent {
229 let trait_ref = ty::TraitRef::new(
230 p.tcx(),
231 parent_def_id,
232 parent_args.iter().copied(),
233 );
234 p.print_path_with_qualified(trait_ref.self_ty(), Some(trait_ref))
235 } else {
236 p.print_def_path(parent_def_id, parent_args)
237 }
238 },
239 &key.disambiguated_data,
240 )
241 }
242 }
243 }
244
245 fn default_print_impl_path(
246 &mut self,
247 impl_def_id: DefId,
248 self_ty: Ty<'tcx>,
249 impl_trait_ref: Option<ty::TraitRef<'tcx>>,
250 ) -> Result<(), PrintError> {
251 {
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:251",
"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(251u32),
::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!(
252 "default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
253 impl_def_id, self_ty, impl_trait_ref
254 );
255
256 let key = self.tcx().def_key(impl_def_id);
257 let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
258
259 let in_self_mod = match characteristic_def_id_of_type(self_ty) {
265 None => false,
266 Some(ty_def_id) => self.tcx().parent(ty_def_id) == parent_def_id,
267 };
268 let in_trait_mod = match impl_trait_ref {
269 None => false,
270 Some(trait_ref) => self.tcx().parent(trait_ref.def_id) == parent_def_id,
271 };
272
273 if !in_self_mod && !in_trait_mod {
274 self.print_path_with_impl(
278 |p| p.print_def_path(parent_def_id, &[]),
279 self_ty,
280 impl_trait_ref,
281 )
282 } else {
283 self.print_path_with_qualified(self_ty, impl_trait_ref)
286 }
287 }
288}
289
290fn characteristic_def_id_of_type_cached<'a>(
300 ty: Ty<'a>,
301 visited: &mut SsoHashSet<Ty<'a>>,
302) -> Option<DefId> {
303 match *ty.kind() {
304 ty::Adt(adt_def, _) => Some(adt_def.did()),
305
306 ty::Dynamic(data, ..) => data.principal_def_id(),
307
308 ty::Pat(subty, _) | ty::Array(subty, _) | ty::Slice(subty) => {
309 characteristic_def_id_of_type_cached(subty, visited)
310 }
311
312 ty::RawPtr(ty, _) => characteristic_def_id_of_type_cached(ty, visited),
313
314 ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited),
315
316 ty::Tuple(tys) => tys.iter().find_map(|ty| {
317 if visited.insert(ty) {
318 return characteristic_def_id_of_type_cached(ty, visited);
319 }
320 return None;
321 }),
322
323 ty::FnDef(def_id, _)
324 | ty::Closure(def_id, _)
325 | ty::CoroutineClosure(def_id, _)
326 | ty::Coroutine(def_id, _)
327 | ty::CoroutineWitness(def_id, _)
328 | ty::Foreign(def_id) => Some(def_id),
329
330 ty::Bool
331 | ty::Char
332 | ty::Int(_)
333 | ty::Uint(_)
334 | ty::Str
335 | ty::FnPtr(..)
336 | ty::UnsafeBinder(_)
337 | ty::Alias(..)
338 | ty::Placeholder(..)
339 | ty::Param(_)
340 | ty::Infer(_)
341 | ty::Bound(..)
342 | ty::Error(_)
343 | ty::Never
344 | ty::Float(_) => None,
345 }
346}
347pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
348 characteristic_def_id_of_type_cached(ty, &mut SsoHashSet::new())
349}
350
351impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'tcx> {
352 fn print(&self, p: &mut P) -> Result<(), PrintError> {
353 p.print_region(*self)
354 }
355}
356
357impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
358 fn print(&self, p: &mut P) -> Result<(), PrintError> {
359 p.print_type(*self)
360 }
361}
362
363impl<'tcx, P: Printer<'tcx> + std::fmt::Write> Print<'tcx, P> for ty::Instance<'tcx> {
364 fn print(&self, cx: &mut P) -> Result<(), PrintError> {
365 cx.print_def_path(self.def_id(), self.args)?;
366 match self.def {
367 ty::InstanceKind::Item(_) => {}
368 ty::InstanceKind::VTableShim(_) => cx.write_str(" - shim(vtable)")?,
369 ty::InstanceKind::ReifyShim(_, None) => cx.write_str(" - shim(reify)")?,
370 ty::InstanceKind::ReifyShim(_, Some(ty::ReifyReason::FnPtr)) => {
371 cx.write_str(" - shim(reify-fnptr)")?
372 }
373 ty::InstanceKind::ReifyShim(_, Some(ty::ReifyReason::Vtable)) => {
374 cx.write_str(" - shim(reify-vtable)")?
375 }
376 ty::InstanceKind::ThreadLocalShim(_) => cx.write_str(" - shim(tls)")?,
377 ty::InstanceKind::Intrinsic(_) => cx.write_str(" - intrinsic")?,
378 ty::InstanceKind::Virtual(_, num) => cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - virtual#{0}", num))
})format!(" - virtual#{num}"))?,
379 ty::InstanceKind::FnPtrShim(_, ty) => cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim({0})", ty))
})format!(" - shim({ty})"))?,
380 ty::InstanceKind::ClosureOnceShim { .. } => cx.write_str(" - shim")?,
381 ty::InstanceKind::ConstructCoroutineInClosureShim { .. } => cx.write_str(" - shim")?,
382 ty::InstanceKind::DropGlue(_, None) => cx.write_str(" - shim(None)")?,
383 ty::InstanceKind::DropGlue(_, Some(ty)) => {
384 cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim(Some({0}))", ty))
})format!(" - shim(Some({ty}))"))?
385 }
386 ty::InstanceKind::CloneShim(_, ty) => cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim({0})", ty))
})format!(" - shim({ty})"))?,
387 ty::InstanceKind::FnPtrAddrShim(_, ty) => cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim({0})", ty))
})format!(" - shim({ty})"))?,
388 ty::InstanceKind::FutureDropPollShim(_, proxy_ty, impl_ty) => {
389 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})"))?
390 }
391 ty::InstanceKind::AsyncDropGlue(_, ty) => cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim({0})", ty))
})format!(" - shim({ty})"))?,
392 ty::InstanceKind::AsyncDropGlueCtorShim(_, ty) => {
393 cx.write_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" - shim(Some({0}))", ty))
})format!(" - shim(Some({ty}))"))?
394 }
395 };
396 Ok(())
397 }
398}
399
400impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
401 fn print(&self, p: &mut P) -> Result<(), PrintError> {
402 p.print_dyn_existential(self)
403 }
404}
405
406impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> {
407 fn print(&self, p: &mut P) -> Result<(), PrintError> {
408 p.print_const(*self)
409 }
410}
411
412impl<T> rustc_type_ir::ir_print::IrPrint<T> for TyCtxt<'_>
413where
414 T: Copy + for<'a, 'tcx> Lift<TyCtxt<'tcx>, Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>>,
415{
416 fn print(t: &T, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
417 ty::tls::with(|tcx| {
418 let mut p = FmtPrinter::new(tcx, Namespace::TypeNS);
419 tcx.lift(*t).expect("could not lift for printing").print(&mut p)?;
420 fmt.write_str(&p.into_buffer())?;
421 Ok(())
422 })
423 }
424
425 fn print_debug(t: &T, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
426 { let _guard = NoTrimmedGuard::new(); Self::print(t, fmt) }with_no_trimmed_paths!(Self::print(t, fmt))
427 }
428}