]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/interpret/intrinsics/type_name.rs
Print constants in `type_name` for const generics
[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, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
73         self.pretty_print_const(ct, false)
74     }
75
76     fn print_dyn_existential(
77         mut self,
78         predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
79     ) -> Result<Self::DynExistential, Self::Error> {
80         let mut first = true;
81         for p in predicates {
82             if !first {
83                 write!(self, "+")?;
84             }
85             first = false;
86             self = p.print(self)?;
87         }
88         Ok(self)
89     }
90
91     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
92         self.path.push_str(&self.tcx.original_crate_name(cnum).as_str());
93         Ok(self)
94     }
95
96     fn path_qualified(
97         self,
98         self_ty: Ty<'tcx>,
99         trait_ref: Option<ty::TraitRef<'tcx>>,
100     ) -> Result<Self::Path, Self::Error> {
101         self.pretty_path_qualified(self_ty, trait_ref)
102     }
103
104     fn path_append_impl(
105         self,
106         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
107         _disambiguated_data: &DisambiguatedDefPathData,
108         self_ty: Ty<'tcx>,
109         trait_ref: Option<ty::TraitRef<'tcx>>,
110     ) -> Result<Self::Path, Self::Error> {
111         self.pretty_path_append_impl(
112             |mut cx| {
113                 cx = print_prefix(cx)?;
114
115                 cx.path.push_str("::");
116
117                 Ok(cx)
118             },
119             self_ty,
120             trait_ref,
121         )
122     }
123
124     fn path_append(
125         mut self,
126         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
127         disambiguated_data: &DisambiguatedDefPathData,
128     ) -> Result<Self::Path, Self::Error> {
129         self = print_prefix(self)?;
130
131         // Skip `::{{constructor}}` on tuple/unit structs.
132         match disambiguated_data.data {
133             DefPathData::Ctor => return Ok(self),
134             _ => {}
135         }
136
137         self.path.push_str("::");
138
139         self.path.push_str(&disambiguated_data.data.as_symbol().as_str());
140         Ok(self)
141     }
142
143     fn path_generic_args(
144         mut self,
145         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
146         args: &[GenericArg<'tcx>],
147     ) -> Result<Self::Path, Self::Error> {
148         self = print_prefix(self)?;
149         let args = args.iter().cloned().filter(|arg| match arg.unpack() {
150             GenericArgKind::Lifetime(_) => false,
151             _ => true,
152         });
153         if args.clone().next().is_some() {
154             self.generic_delimiters(|cx| cx.comma_sep(args))
155         } else {
156             Ok(self)
157         }
158     }
159 }
160 impl PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
161     fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool {
162         false
163     }
164     fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
165     where
166         T: Print<'tcx, Self, Output = Self, Error = Self::Error>,
167     {
168         if let Some(first) = elems.next() {
169             self = first.print(self)?;
170             for elem in elems {
171                 self.path.push_str(", ");
172                 self = elem.print(self)?;
173             }
174         }
175         Ok(self)
176     }
177
178     fn generic_delimiters(
179         mut self,
180         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
181     ) -> Result<Self, Self::Error> {
182         write!(self, "<")?;
183
184         self = f(self)?;
185
186         write!(self, ">")?;
187
188         Ok(self)
189     }
190 }
191
192 impl Write for AbsolutePathPrinter<'_> {
193     fn write_str(&mut self, s: &str) -> std::fmt::Result {
194         Ok(self.path.push_str(s))
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 }