3 subst::{UnpackedKind, Kind},
4 print::{Printer, PrettyPrinter, Print},
7 use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
8 use rustc::hir::def_id::CrateNum;
10 use rustc::mir::interpret::{Allocation, ConstValue};
12 struct AbsolutePathPrinter<'tcx> {
13 tcx: TyCtxt<'tcx, 'tcx>,
17 impl<'tcx> Printer<'tcx, 'tcx> for AbsolutePathPrinter<'tcx> {
18 type Error = std::fmt::Error;
23 type DynExistential = Self;
26 fn tcx(&self) -> TyCtxt<'tcx, 'tcx> {
30 fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
34 fn print_type(self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
36 // types without identity
53 // should be unreachable, but there's no hurt in printing it (and better than ICEing)
55 => self.pretty_print_type(ty),
61 | ty::UnnormalizedProjection(_)
62 | ty::GeneratorWitness(_)
64 "{:#?} in `type_name` should not happen because we are always monomorphized",
67 // types with identity (print the module path instead)
68 | ty::FnDef(did, substs)
69 | ty::Opaque(did, substs)
70 => self.print_def_path(did, substs),
71 ty::Closure(did, substs) => self.print_def_path(did, substs.substs),
72 ty::Generator(did, substs, _) => self.print_def_path(did, substs.substs),
78 _: &'tcx ty::Const<'tcx>,
79 ) -> Result<Self::Const, Self::Error> {
80 // don't print constants to the user
84 fn print_dyn_existential(
86 predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
87 ) -> Result<Self::DynExistential, Self::Error> {
94 self = p.print(self)?;
99 fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
100 self.path.push_str(&self.tcx.original_crate_name(cnum).as_str());
107 trait_ref: Option<ty::TraitRef<'tcx>>,
108 ) -> Result<Self::Path, Self::Error> {
109 self.pretty_path_qualified(self_ty, trait_ref)
114 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
115 _disambiguated_data: &DisambiguatedDefPathData,
117 trait_ref: Option<ty::TraitRef<'tcx>>,
118 ) -> Result<Self::Path, Self::Error> {
119 self.pretty_path_append_impl(
121 cx = print_prefix(cx)?;
123 cx.path.push_str("::");
134 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
135 disambiguated_data: &DisambiguatedDefPathData,
136 ) -> Result<Self::Path, Self::Error> {
137 self = print_prefix(self)?;
139 // Skip `::{{constructor}}` on tuple/unit structs.
140 match disambiguated_data.data {
141 DefPathData::Ctor => return Ok(self),
145 self.path.push_str("::");
147 self.path.push_str(&disambiguated_data.data.as_interned_str().as_str());
151 fn path_generic_args(
153 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
155 ) -> Result<Self::Path, Self::Error> {
156 self = print_prefix(self)?;
157 let args = args.iter().cloned().filter(|arg| {
159 UnpackedKind::Lifetime(_) => false,
163 if args.clone().next().is_some() {
164 self.generic_delimiters(|cx| cx.comma_sep(args))
170 impl PrettyPrinter<'tcx, 'tcx> for AbsolutePathPrinter<'tcx> {
171 fn region_should_not_be_omitted(
173 _region: ty::Region<'_>,
179 mut elems: impl Iterator<Item = T>,
180 ) -> Result<Self, Self::Error>
181 where T: Print<'tcx, 'tcx, Self, Output = Self, Error = Self::Error>
183 if let Some(first) = elems.next() {
184 self = first.print(self)?;
186 self.path.push_str(", ");
187 self = elem.print(self)?;
193 fn generic_delimiters(
195 f: impl FnOnce(Self) -> Result<Self, Self::Error>,
196 ) -> Result<Self, Self::Error> {
207 impl Write for AbsolutePathPrinter<'_> {
208 fn write_str(&mut self, s: &str) -> std::fmt::Result {
209 Ok(self.path.push_str(s))
213 /// Produces an absolute path representation of the given type. See also the documentation on
214 /// `std::any::type_name`
215 pub fn type_name<'tcx>(tcx: TyCtxt<'tcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
216 let alloc = alloc_type_name(tcx, ty);
217 tcx.mk_const(ty::Const {
218 val: ConstValue::Slice {
221 end: alloc.bytes.len(),
223 ty: tcx.mk_static_str(),
227 /// Directly returns an `Allocation` containing an absolute path representation of the given type.
228 pub(super) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
229 let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
230 let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
231 tcx.intern_const_alloc(alloc)