]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/interpret/intrinsics/type_name.rs
eed47c147c60d48d9e9aa9a03e5470ee4d0bf474
[rust.git] / src / librustc_mir / interpret / intrinsics / type_name.rs
1 use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
2 use rustc::mir::interpret::Allocation;
3 use rustc::ty::{
4     self,
5     print::{PrettyPrinter, Print, Printer},
6     subst::{GenericArg, GenericArgKind},
7     Ty, TyCtxt,
8 };
9 use rustc_hir::def_id::CrateNum;
10 use std::fmt::Write;
11
12 struct AbsolutePathPrinter<'tcx> {
13     tcx: TyCtxt<'tcx>,
14     path: String,
15 }
16
17 impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
18     type Error = std::fmt::Error;
19
20     type Path = Self;
21     type Region = Self;
22     type Type = Self;
23     type DynExistential = Self;
24     type Const = Self;
25
26     fn tcx(&self) -> TyCtxt<'tcx> {
27         self.tcx
28     }
29
30     fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
31         Ok(self)
32     }
33
34     fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
35         match ty.kind {
36             // Types without identity.
37             ty::Bool
38             | ty::Char
39             | ty::Int(_)
40             | ty::Uint(_)
41             | ty::Float(_)
42             | ty::Str
43             | ty::Array(_, _)
44             | ty::Slice(_)
45             | ty::RawPtr(_)
46             | ty::Ref(_, _, _)
47             | ty::FnPtr(_)
48             | ty::Never
49             | ty::Tuple(_)
50             | ty::Dynamic(_, _) => self.pretty_print_type(ty),
51
52             // Placeholders (all printed as `_` to uniformize them).
53             ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error => {
54                 write!(self, "_")?;
55                 Ok(self)
56             }
57
58             // Types with identity (print the module path).
59             ty::Adt(&ty::AdtDef { did: def_id, .. }, substs)
60             | ty::FnDef(def_id, substs)
61             | ty::Opaque(def_id, substs)
62             | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
63             | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs })
64             | ty::Closure(def_id, substs)
65             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
66             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
67
68             ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"),
69         }
70     }
71
72     fn print_const(self, _: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
73         // don't print constants to the user
74         Ok(self)
75     }
76
77     fn print_dyn_existential(
78         mut self,
79         predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
80     ) -> Result<Self::DynExistential, Self::Error> {
81         let mut first = true;
82         for p in predicates {
83             if !first {
84                 write!(self, "+")?;
85             }
86             first = false;
87             self = p.print(self)?;
88         }
89         Ok(self)
90     }
91
92     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
93         self.path.push_str(&self.tcx.original_crate_name(cnum).as_str());
94         Ok(self)
95     }
96
97     fn path_qualified(
98         self,
99         self_ty: Ty<'tcx>,
100         trait_ref: Option<ty::TraitRef<'tcx>>,
101     ) -> Result<Self::Path, Self::Error> {
102         self.pretty_path_qualified(self_ty, trait_ref)
103     }
104
105     fn path_append_impl(
106         self,
107         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
108         _disambiguated_data: &DisambiguatedDefPathData,
109         self_ty: Ty<'tcx>,
110         trait_ref: Option<ty::TraitRef<'tcx>>,
111     ) -> Result<Self::Path, Self::Error> {
112         self.pretty_path_append_impl(
113             |mut cx| {
114                 cx = print_prefix(cx)?;
115
116                 cx.path.push_str("::");
117
118                 Ok(cx)
119             },
120             self_ty,
121             trait_ref,
122         )
123     }
124
125     fn path_append(
126         mut self,
127         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
128         disambiguated_data: &DisambiguatedDefPathData,
129     ) -> Result<Self::Path, Self::Error> {
130         self = print_prefix(self)?;
131
132         // Skip `::{{constructor}}` on tuple/unit structs.
133         match disambiguated_data.data {
134             DefPathData::Ctor => return Ok(self),
135             _ => {}
136         }
137
138         self.path.push_str("::");
139
140         self.path.push_str(&disambiguated_data.data.as_symbol().as_str());
141         Ok(self)
142     }
143
144     fn path_generic_args(
145         mut self,
146         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
147         args: &[GenericArg<'tcx>],
148     ) -> Result<Self::Path, Self::Error> {
149         self = print_prefix(self)?;
150         let args = args.iter().cloned().filter(|arg| match arg.unpack() {
151             GenericArgKind::Lifetime(_) => false,
152             _ => true,
153         });
154         if args.clone().next().is_some() {
155             self.generic_delimiters(|cx| cx.comma_sep(args))
156         } else {
157             Ok(self)
158         }
159     }
160 }
161 impl PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
162     fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool {
163         false
164     }
165     fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
166     where
167         T: Print<'tcx, Self, Output = Self, Error = Self::Error>,
168     {
169         if let Some(first) = elems.next() {
170             self = first.print(self)?;
171             for elem in elems {
172                 self.path.push_str(", ");
173                 self = elem.print(self)?;
174             }
175         }
176         Ok(self)
177     }
178
179     fn generic_delimiters(
180         mut self,
181         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
182     ) -> Result<Self, Self::Error> {
183         write!(self, "<")?;
184
185         self = f(self)?;
186
187         write!(self, ">")?;
188
189         Ok(self)
190     }
191 }
192
193 impl Write for AbsolutePathPrinter<'_> {
194     fn write_str(&mut self, s: &str) -> std::fmt::Result {
195         Ok(self.path.push_str(s))
196     }
197 }
198
199 /// Directly returns an `Allocation` containing an absolute path representation of the given type.
200 crate fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
201     let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
202     let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
203     tcx.intern_const_alloc(alloc)
204 }