]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/interpret/intrinsics/type_name.rs
bootstrap: Configurable musl libdir
[rust.git] / src / librustc_mir / interpret / intrinsics / type_name.rs
1 use rustc_hir::def_id::CrateNum;
2 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
3 use rustc_middle::mir::interpret::Allocation;
4 use rustc_middle::ty::{
5     self,
6     print::{PrettyPrinter, Print, Printer},
7     subst::{GenericArg, GenericArgKind},
8     Ty, TyCtxt,
9 };
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::Closure(def_id, substs)
64             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
65             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
66
67             ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"),
68         }
69     }
70
71     fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
72         self.pretty_print_const(ct, false)
73     }
74
75     fn print_dyn_existential(
76         mut self,
77         predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
78     ) -> Result<Self::DynExistential, Self::Error> {
79         let mut first = true;
80         for p in predicates {
81             if !first {
82                 write!(self, "+")?;
83             }
84             first = false;
85             self = p.print(self)?;
86         }
87         Ok(self)
88     }
89
90     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
91         self.path.push_str(&self.tcx.original_crate_name(cnum).as_str());
92         Ok(self)
93     }
94
95     fn path_qualified(
96         self,
97         self_ty: Ty<'tcx>,
98         trait_ref: Option<ty::TraitRef<'tcx>>,
99     ) -> Result<Self::Path, Self::Error> {
100         self.pretty_path_qualified(self_ty, trait_ref)
101     }
102
103     fn path_append_impl(
104         self,
105         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
106         _disambiguated_data: &DisambiguatedDefPathData,
107         self_ty: Ty<'tcx>,
108         trait_ref: Option<ty::TraitRef<'tcx>>,
109     ) -> Result<Self::Path, Self::Error> {
110         self.pretty_path_append_impl(
111             |mut cx| {
112                 cx = print_prefix(cx)?;
113
114                 cx.path.push_str("::");
115
116                 Ok(cx)
117             },
118             self_ty,
119             trait_ref,
120         )
121     }
122
123     fn path_append(
124         mut self,
125         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
126         disambiguated_data: &DisambiguatedDefPathData,
127     ) -> Result<Self::Path, Self::Error> {
128         self = print_prefix(self)?;
129
130         // Skip `::{{constructor}}` on tuple/unit structs.
131         if disambiguated_data.data == DefPathData::Ctor {
132             return Ok(self);
133         }
134
135         self.path.push_str("::");
136
137         self.path.push_str(&disambiguated_data.data.as_symbol().as_str());
138         Ok(self)
139     }
140
141     fn path_generic_args(
142         mut self,
143         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
144         args: &[GenericArg<'tcx>],
145     ) -> Result<Self::Path, Self::Error> {
146         self = print_prefix(self)?;
147         let args = args.iter().cloned().filter(|arg| match arg.unpack() {
148             GenericArgKind::Lifetime(_) => false,
149             _ => true,
150         });
151         if args.clone().next().is_some() {
152             self.generic_delimiters(|cx| cx.comma_sep(args))
153         } else {
154             Ok(self)
155         }
156     }
157 }
158
159 impl PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
160     fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool {
161         false
162     }
163     fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
164     where
165         T: Print<'tcx, Self, Output = Self, Error = Self::Error>,
166     {
167         if let Some(first) = elems.next() {
168             self = first.print(self)?;
169             for elem in elems {
170                 self.path.push_str(", ");
171                 self = elem.print(self)?;
172             }
173         }
174         Ok(self)
175     }
176
177     fn generic_delimiters(
178         mut self,
179         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
180     ) -> Result<Self, Self::Error> {
181         write!(self, "<")?;
182
183         self = f(self)?;
184
185         write!(self, ">")?;
186
187         Ok(self)
188     }
189 }
190
191 impl Write for AbsolutePathPrinter<'_> {
192     fn write_str(&mut self, s: &str) -> std::fmt::Result {
193         self.path.push_str(s);
194         Ok(())
195     }
196 }
197
198 /// Directly returns an `Allocation` containing an absolute path representation of the given type.
199 crate fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
200     let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
201     let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
202     tcx.intern_const_alloc(alloc)
203 }