]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/interpret/intrinsics/type_name.rs
Auto merge of #61100 - varkor:must_use-tuple-expr, r=cramertj
[rust.git] / src / librustc_mir / interpret / intrinsics / type_name.rs
1 use rustc::ty::{
2     TyCtxt, Ty,
3     subst::{UnpackedKind, Kind},
4     print::{Printer, PrettyPrinter, Print},
5     self,
6 };
7 use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
8 use rustc::hir::def_id::CrateNum;
9 use std::fmt::Write;
10 use rustc::mir::interpret::{Allocation, ConstValue};
11
12 struct AbsolutePathPrinter<'a, 'tcx> {
13     tcx: TyCtxt<'a, 'tcx, 'tcx>,
14     path: String,
15 }
16
17 impl<'tcx> Printer<'tcx, '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<'a>(&'a self) -> TyCtxt<'a, 'tcx, '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(self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
35         match ty.sty {
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(_, _)
51             | ty::Adt(..)
52             | ty::Foreign(_)
53             // should be unreachable, but there's no hurt in printing it (and better than ICEing)
54             | ty::Error
55             => self.pretty_print_type(ty),
56             | ty::Infer(_)
57             | ty::Bound(_, _)
58             | ty::Param(_)
59             | ty::Placeholder(_)
60             | ty::Projection(_)
61             | ty::UnnormalizedProjection(_)
62             | ty::GeneratorWitness(_)
63             => bug!(
64                 "{:#?} in `type_name` should not happen because we are always monomorphized",
65                 ty,
66             ),
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),
73         }
74     }
75
76     fn print_const(
77         self,
78         _: &'tcx ty::Const<'tcx>,
79     ) -> Result<Self::Const, Self::Error> {
80         // don't print constants to the user
81         Ok(self)
82     }
83
84     fn print_dyn_existential(
85         mut self,
86         predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
87     ) -> Result<Self::DynExistential, Self::Error> {
88         let mut first = true;
89         for p in predicates {
90             if !first {
91                 write!(self, "+")?;
92             }
93             first = false;
94             self = p.print(self)?;
95         }
96         Ok(self)
97     }
98
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());
101         Ok(self)
102     }
103
104     fn path_qualified(
105         self,
106         self_ty: Ty<'tcx>,
107         trait_ref: Option<ty::TraitRef<'tcx>>,
108     ) -> Result<Self::Path, Self::Error> {
109         self.pretty_path_qualified(self_ty, trait_ref)
110     }
111
112     fn path_append_impl(
113         self,
114         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
115         _disambiguated_data: &DisambiguatedDefPathData,
116         self_ty: Ty<'tcx>,
117         trait_ref: Option<ty::TraitRef<'tcx>>,
118     ) -> Result<Self::Path, Self::Error> {
119         self.pretty_path_append_impl(
120             |mut cx| {
121                 cx = print_prefix(cx)?;
122
123                 cx.path.push_str("::");
124
125                 Ok(cx)
126             },
127             self_ty,
128             trait_ref,
129         )
130     }
131
132     fn path_append(
133         mut self,
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)?;
138
139         // Skip `::{{constructor}}` on tuple/unit structs.
140         match disambiguated_data.data {
141             DefPathData::Ctor => return Ok(self),
142             _ => {}
143         }
144
145         self.path.push_str("::");
146
147         self.path.push_str(&disambiguated_data.data.as_interned_str().as_str());
148         Ok(self)
149     }
150
151     fn path_generic_args(
152         mut self,
153         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
154         args: &[Kind<'tcx>],
155     ) -> Result<Self::Path, Self::Error> {
156         self = print_prefix(self)?;
157         let args = args.iter().cloned().filter(|arg| {
158             match arg.unpack() {
159                 UnpackedKind::Lifetime(_) => false,
160                 _ => true,
161             }
162         });
163         if args.clone().next().is_some() {
164             self.generic_delimiters(|cx| cx.comma_sep(args))
165         } else {
166             Ok(self)
167         }
168     }
169 }
170 impl PrettyPrinter<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> {
171     fn region_should_not_be_omitted(
172         &self,
173         _region: ty::Region<'_>,
174     ) -> bool {
175         false
176     }
177     fn comma_sep<T>(
178         mut self,
179         mut elems: impl Iterator<Item = T>,
180     ) -> Result<Self, Self::Error>
181         where T: Print<'tcx, 'tcx, Self, Output = Self, Error = Self::Error>
182     {
183         if let Some(first) = elems.next() {
184             self = first.print(self)?;
185             for elem in elems {
186                 self.path.push_str(", ");
187                 self = elem.print(self)?;
188             }
189         }
190         Ok(self)
191     }
192
193     fn generic_delimiters(
194         mut self,
195         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
196     ) -> Result<Self, Self::Error> {
197         write!(self, "<")?;
198
199         self = f(self)?;
200
201         write!(self, ">")?;
202
203         Ok(self)
204     }
205 }
206
207 impl Write for AbsolutePathPrinter<'_, '_> {
208     fn write_str(&mut self, s: &str) -> std::fmt::Result {
209         Ok(self.path.push_str(s))
210     }
211 }
212
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<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
216     let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
217     let len = path.len();
218     let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
219     let alloc = tcx.intern_const_alloc(alloc);
220     tcx.mk_const(ty::Const {
221         val: ConstValue::Slice {
222             data: alloc,
223             start: 0,
224             end: len,
225         },
226         ty: tcx.mk_static_str(),
227     })
228 }