]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/print/obsolete.rs
Rollup merge of #68108 - varkor:chained-comparison-suggestions, r=Centril
[rust.git] / src / librustc / ty / print / obsolete.rs
1 //! Allows for producing a unique string key for a mono item.
2 //! These keys are used by the handwritten auto-tests, so they need to be
3 //! predictable and human-readable.
4 //!
5 //! Note: A lot of this could looks very similar to what's already in `ty::print`.
6 //! FIXME(eddyb) implement a custom `PrettyPrinter` for this.
7
8 use rustc::bug;
9 use rustc::ty::subst::SubstsRef;
10 use rustc::ty::{self, Const, Instance, Ty, TyCtxt};
11 use rustc_hir as hir;
12 use rustc_hir::def_id::DefId;
13 use std::fmt::Write;
14 use std::iter;
15
16 /// Same as `unique_type_name()` but with the result pushed onto the given
17 /// `output` parameter.
18 pub struct DefPathBasedNames<'tcx> {
19     tcx: TyCtxt<'tcx>,
20     omit_disambiguators: bool,
21     omit_local_crate_name: bool,
22 }
23
24 impl DefPathBasedNames<'tcx> {
25     pub fn new(tcx: TyCtxt<'tcx>, omit_disambiguators: bool, omit_local_crate_name: bool) -> Self {
26         DefPathBasedNames { tcx, omit_disambiguators, omit_local_crate_name }
27     }
28
29     // Pushes the type name of the specified type to the provided string.
30     // If `debug` is true, printing normally unprintable types is allowed
31     // (e.g. `ty::GeneratorWitness`). This parameter should only be set when
32     // this method is being used for logging purposes (e.g. with `debug!` or `info!`)
33     // When being used for codegen purposes, `debug` should be set to `false`
34     // in order to catch unexpected types that should never end up in a type name.
35     pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
36         match t.kind {
37             ty::Bool => output.push_str("bool"),
38             ty::Char => output.push_str("char"),
39             ty::Str => output.push_str("str"),
40             ty::Never => output.push_str("!"),
41             ty::Int(ty) => output.push_str(ty.name_str()),
42             ty::Uint(ty) => output.push_str(ty.name_str()),
43             ty::Float(ty) => output.push_str(ty.name_str()),
44             ty::Adt(adt_def, substs) => {
45                 self.push_def_path(adt_def.did, output);
46                 self.push_generic_params(substs, iter::empty(), output, debug);
47             }
48             ty::Tuple(component_types) => {
49                 output.push('(');
50                 for &component_type in component_types {
51                     self.push_type_name(component_type.expect_ty(), output, debug);
52                     output.push_str(", ");
53                 }
54                 if !component_types.is_empty() {
55                     output.pop();
56                     output.pop();
57                 }
58                 output.push(')');
59             }
60             ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => {
61                 output.push('*');
62                 match mutbl {
63                     hir::Mutability::Not => output.push_str("const "),
64                     hir::Mutability::Mut => output.push_str("mut "),
65                 }
66
67                 self.push_type_name(inner_type, output, debug);
68             }
69             ty::Ref(_, inner_type, mutbl) => {
70                 output.push('&');
71                 output.push_str(mutbl.prefix_str());
72
73                 self.push_type_name(inner_type, output, debug);
74             }
75             ty::Array(inner_type, len) => {
76                 output.push('[');
77                 self.push_type_name(inner_type, output, debug);
78                 let len = len.eval_usize(self.tcx, ty::ParamEnv::reveal_all());
79                 write!(output, "; {}", len).unwrap();
80                 output.push(']');
81             }
82             ty::Slice(inner_type) => {
83                 output.push('[');
84                 self.push_type_name(inner_type, output, debug);
85                 output.push(']');
86             }
87             ty::Dynamic(ref trait_data, ..) => {
88                 if let Some(principal) = trait_data.principal() {
89                     self.push_def_path(principal.def_id(), output);
90                     self.push_generic_params(
91                         principal.skip_binder().substs,
92                         trait_data.projection_bounds(),
93                         output,
94                         debug,
95                     );
96                 } else {
97                     output.push_str("dyn '_");
98                 }
99             }
100             ty::Foreign(did) => self.push_def_path(did, output),
101             ty::FnDef(..) | ty::FnPtr(_) => {
102                 let sig = t.fn_sig(self.tcx);
103                 output.push_str(sig.unsafety().prefix_str());
104
105                 let abi = sig.abi();
106                 if abi != ::rustc_target::spec::abi::Abi::Rust {
107                     output.push_str("extern \"");
108                     output.push_str(abi.name());
109                     output.push_str("\" ");
110                 }
111
112                 output.push_str("fn(");
113
114                 let sig =
115                     self.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
116
117                 if !sig.inputs().is_empty() {
118                     for &parameter_type in sig.inputs() {
119                         self.push_type_name(parameter_type, output, debug);
120                         output.push_str(", ");
121                     }
122                     output.pop();
123                     output.pop();
124                 }
125
126                 if sig.c_variadic {
127                     if !sig.inputs().is_empty() {
128                         output.push_str(", ...");
129                     } else {
130                         output.push_str("...");
131                     }
132                 }
133
134                 output.push(')');
135
136                 if !sig.output().is_unit() {
137                     output.push_str(" -> ");
138                     self.push_type_name(sig.output(), output, debug);
139                 }
140             }
141             ty::Generator(def_id, substs, _) | ty::Closure(def_id, substs) => {
142                 self.push_def_path(def_id, output);
143                 let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
144                 let substs = substs.truncate_to(self.tcx, generics);
145                 self.push_generic_params(substs, iter::empty(), output, debug);
146             }
147             ty::Error
148             | ty::Bound(..)
149             | ty::Infer(_)
150             | ty::Placeholder(..)
151             | ty::UnnormalizedProjection(..)
152             | ty::Projection(..)
153             | ty::Param(_)
154             | ty::GeneratorWitness(_)
155             | ty::Opaque(..) => {
156                 if debug {
157                     output.push_str(&format!("`{:?}`", t));
158                 } else {
159                     bug!(
160                         "DefPathBasedNames: trying to create type name for unexpected type: {:?}",
161                         t,
162                     );
163                 }
164             }
165         }
166     }
167
168     // Pushes the the name of the specified const to the provided string.
169     // If `debug` is true, the unprintable types of constants will be printed with `fmt::Debug`
170     // (see `push_type_name` for more details).
171     pub fn push_const_name(&self, ct: &Const<'tcx>, output: &mut String, debug: bool) {
172         write!(output, "{}", ct).unwrap();
173         output.push_str(": ");
174         self.push_type_name(ct.ty, output, debug);
175     }
176
177     pub fn push_def_path(&self, def_id: DefId, output: &mut String) {
178         let def_path = self.tcx.def_path(def_id);
179
180         // some_crate::
181         if !(self.omit_local_crate_name && def_id.is_local()) {
182             output.push_str(&self.tcx.crate_name(def_path.krate).as_str());
183             output.push_str("::");
184         }
185
186         // foo::bar::ItemName::
187         for part in self.tcx.def_path(def_id).data {
188             if self.omit_disambiguators {
189                 write!(output, "{}::", part.data.as_symbol()).unwrap();
190             } else {
191                 write!(output, "{}[{}]::", part.data.as_symbol(), part.disambiguator).unwrap();
192             }
193         }
194
195         // remove final "::"
196         output.pop();
197         output.pop();
198     }
199
200     fn push_generic_params<I>(
201         &self,
202         substs: SubstsRef<'tcx>,
203         projections: I,
204         output: &mut String,
205         debug: bool,
206     ) where
207         I: Iterator<Item = ty::PolyExistentialProjection<'tcx>>,
208     {
209         let mut projections = projections.peekable();
210         if substs.non_erasable_generics().next().is_none() && projections.peek().is_none() {
211             return;
212         }
213
214         output.push('<');
215
216         for type_parameter in substs.types() {
217             self.push_type_name(type_parameter, output, debug);
218             output.push_str(", ");
219         }
220
221         for projection in projections {
222             let projection = projection.skip_binder();
223             let name = &self.tcx.associated_item(projection.item_def_id).ident.as_str();
224             output.push_str(name);
225             output.push_str("=");
226             self.push_type_name(projection.ty, output, debug);
227             output.push_str(", ");
228         }
229
230         for const_parameter in substs.consts() {
231             self.push_const_name(const_parameter, output, debug);
232             output.push_str(", ");
233         }
234
235         output.pop();
236         output.pop();
237
238         output.push('>');
239     }
240
241     pub fn push_instance_as_string(
242         &self,
243         instance: Instance<'tcx>,
244         output: &mut String,
245         debug: bool,
246     ) {
247         self.push_def_path(instance.def_id(), output);
248         self.push_generic_params(instance.substs, iter::empty(), output, debug);
249     }
250 }