]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/print.rs
4e1fdf657bd5f25dcd6e69eba3f17b6606126b4a
[rust.git] / src / librustc / ty / print.rs
1 use crate::hir::def::Namespace;
2 use crate::hir::map::DefPathData;
3 use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
4 use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
5 use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind};
6 use crate::middle::cstore::{ExternCrate, ExternCrateSource};
7 use syntax::symbol::{keywords, Symbol};
8
9 use rustc_data_structures::fx::FxHashSet;
10 use syntax::symbol::InternedString;
11
12 use std::cell::Cell;
13 use std::fmt::{self, Write as _};
14 use std::iter;
15 use std::ops::Deref;
16
17 thread_local! {
18     static FORCE_IMPL_FILENAME_LINE: Cell<bool> = Cell::new(false);
19     static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = Cell::new(false);
20 }
21
22 /// Force us to name impls with just the filename/line number. We
23 /// normally try to use types. But at some points, notably while printing
24 /// cycle errors, this can result in extra or suboptimal error output,
25 /// so this variable disables that check.
26 pub fn with_forced_impl_filename_line<F: FnOnce() -> R, R>(f: F) -> R {
27     FORCE_IMPL_FILENAME_LINE.with(|force| {
28         let old = force.get();
29         force.set(true);
30         let result = f();
31         force.set(old);
32         result
33     })
34 }
35
36 /// Adds the `crate::` prefix to paths where appropriate.
37 pub fn with_crate_prefix<F: FnOnce() -> R, R>(f: F) -> R {
38     SHOULD_PREFIX_WITH_CRATE.with(|flag| {
39         let old = flag.get();
40         flag.set(true);
41         let result = f();
42         flag.set(old);
43         result
44     })
45 }
46
47 // FIXME(eddyb) this module uses `pub(crate)` for things used only
48 // from `ppaux` - when that is removed, they can be re-privatized.
49
50 /// The "region highlights" are used to control region printing during
51 /// specific error messages. When a "region highlight" is enabled, it
52 /// gives an alternate way to print specific regions. For now, we
53 /// always print those regions using a number, so something like "`'0`".
54 ///
55 /// Regions not selected by the region highlight mode are presently
56 /// unaffected.
57 #[derive(Copy, Clone, Default)]
58 pub struct RegionHighlightMode {
59     /// If enabled, when we see the selected region, use "`'N`"
60     /// instead of the ordinary behavior.
61     highlight_regions: [Option<(ty::RegionKind, usize)>; 3],
62
63     /// If enabled, when printing a "free region" that originated from
64     /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
65     /// have names print as normal.
66     ///
67     /// This is used when you have a signature like `fn foo(x: &u32,
68     /// y: &'a u32)` and we want to give a name to the region of the
69     /// reference `x`.
70     pub(crate) highlight_bound_region: Option<(ty::BoundRegion, usize)>,
71 }
72
73 impl RegionHighlightMode {
74     /// If `region` and `number` are both `Some`, invokes
75     /// `highlighting_region`.
76     pub fn maybe_highlighting_region(
77         &mut self,
78         region: Option<ty::Region<'_>>,
79         number: Option<usize>,
80     ) {
81         if let Some(k) = region {
82             if let Some(n) = number {
83                 self.highlighting_region(k, n);
84             }
85         }
86     }
87
88     /// Highlights the region inference variable `vid` as `'N`.
89     pub fn highlighting_region(
90         &mut self,
91         region: ty::Region<'_>,
92         number: usize,
93     ) {
94         let num_slots = self.highlight_regions.len();
95         let first_avail_slot = self.highlight_regions.iter_mut()
96             .filter(|s| s.is_none())
97             .next()
98             .unwrap_or_else(|| {
99                 bug!(
100                     "can only highlight {} placeholders at a time",
101                     num_slots,
102                 )
103             });
104         *first_avail_slot = Some((*region, number));
105     }
106
107     /// Convenience wrapper for `highlighting_region`.
108     pub fn highlighting_region_vid(
109         &mut self,
110         vid: ty::RegionVid,
111         number: usize,
112     ) {
113         self.highlighting_region(&ty::ReVar(vid), number)
114     }
115
116     /// Returns `Some(n)` with the number to use for the given region, if any.
117     pub(crate) fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
118         self
119             .highlight_regions
120             .iter()
121             .filter_map(|h| match h {
122                 Some((r, n)) if r == region => Some(*n),
123                 _ => None,
124             })
125             .next()
126     }
127
128     /// Highlight the given bound region.
129     /// We can only highlight one bound region at a time. See
130     /// the field `highlight_bound_region` for more detailed notes.
131     pub fn highlighting_bound_region(
132         &mut self,
133         br: ty::BoundRegion,
134         number: usize,
135     ) {
136         assert!(self.highlight_bound_region.is_none());
137         self.highlight_bound_region = Some((br, number));
138     }
139 }
140
141 struct LateBoundRegionNameCollector(FxHashSet<InternedString>);
142 impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector {
143     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
144         match *r {
145             ty::ReLateBound(_, ty::BrNamed(_, name)) => {
146                 self.0.insert(name);
147             },
148             _ => {},
149         }
150         r.super_visit_with(self)
151     }
152 }
153
154 pub(crate) struct PrintConfig {
155     pub(crate) is_debug: bool,
156     pub(crate) is_verbose: bool,
157     pub(crate) identify_regions: bool,
158     pub(crate) used_region_names: Option<FxHashSet<InternedString>>,
159     pub(crate) region_index: usize,
160     pub(crate) binder_depth: usize,
161 }
162
163 impl PrintConfig {
164     pub(crate) fn new(tcx: TyCtxt<'_, '_, '_>) -> Self {
165         PrintConfig {
166             is_debug: false,
167             is_verbose: tcx.sess.verbose(),
168             identify_regions: tcx.sess.opts.debugging_opts.identify_regions,
169             used_region_names: None,
170             region_index: 0,
171             binder_depth: 0,
172         }
173     }
174 }
175
176 pub struct PrintCx<'a, 'gcx, 'tcx, P> {
177     pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
178     pub printer: P,
179     pub(crate) config: &'a mut PrintConfig,
180 }
181
182 // HACK(eddyb) this is solely for `self: PrintCx<Self>`, e.g. to
183 // implement traits on the printer and call the methods on the context.
184 impl<P> Deref for PrintCx<'_, '_, '_, P> {
185     type Target = P;
186     fn deref(&self) -> &P {
187         &self.printer
188     }
189 }
190
191 impl<'a, 'gcx, 'tcx, P> PrintCx<'a, 'gcx, 'tcx, P> {
192     pub fn with<R>(
193         tcx: TyCtxt<'a, 'gcx, 'tcx>,
194         printer: P,
195         f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, P>) -> R,
196     ) -> R {
197         f(PrintCx {
198             tcx,
199             printer,
200             config: &mut PrintConfig::new(tcx),
201         })
202     }
203
204     pub(crate) fn with_tls_tcx<R>(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R {
205         ty::tls::with(|tcx| PrintCx::with(tcx, printer, f))
206     }
207     pub(crate) fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<T>)
208     where T: TypeFoldable<'tcx>
209     {
210         let mut collector = LateBoundRegionNameCollector(Default::default());
211         value.visit_with(&mut collector);
212         self.config.used_region_names = Some(collector.0);
213         self.config.region_index = 0;
214     }
215 }
216
217 pub trait Print<'tcx, P> {
218     type Output;
219     type Error;
220
221     fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error>;
222     fn print_display(
223         &self,
224         cx: PrintCx<'_, '_, 'tcx, P>,
225     ) -> Result<Self::Output, Self::Error> {
226         let old_debug = cx.config.is_debug;
227         cx.config.is_debug = false;
228         let result = self.print(PrintCx {
229             tcx: cx.tcx,
230             printer: cx.printer,
231             config: cx.config,
232         });
233         cx.config.is_debug = old_debug;
234         result
235     }
236     fn print_debug(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
237         let old_debug = cx.config.is_debug;
238         cx.config.is_debug = true;
239         let result = self.print(PrintCx {
240             tcx: cx.tcx,
241             printer: cx.printer,
242             config: cx.config,
243         });
244         cx.config.is_debug = old_debug;
245         result
246     }
247 }
248
249 pub trait Printer: Sized {
250     type Error;
251
252     type Path;
253
254     fn print_def_path(
255         self: PrintCx<'_, '_, 'tcx, Self>,
256         def_id: DefId,
257         substs: Option<SubstsRef<'tcx>>,
258         ns: Namespace,
259         projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
260     ) -> Result<Self::Path, Self::Error> {
261         self.default_print_def_path(def_id, substs, ns, projections)
262     }
263     fn print_impl_path(
264         self: PrintCx<'_, '_, 'tcx, Self>,
265         impl_def_id: DefId,
266         substs: Option<SubstsRef<'tcx>>,
267         ns: Namespace,
268         self_ty: Ty<'tcx>,
269         trait_ref: Option<ty::TraitRef<'tcx>>,
270     ) -> Result<Self::Path, Self::Error> {
271         self.default_print_impl_path(impl_def_id, substs, ns, self_ty, trait_ref)
272     }
273
274     fn path_crate(
275         self: PrintCx<'_, '_, '_, Self>,
276         cnum: CrateNum,
277     ) -> Result<Self::Path, Self::Error>;
278     fn path_qualified(
279         self: PrintCx<'_, '_, 'tcx, Self>,
280         self_ty: Ty<'tcx>,
281         trait_ref: Option<ty::TraitRef<'tcx>>,
282         ns: Namespace,
283     ) -> Result<Self::Path, Self::Error>;
284
285     fn path_append_impl<'gcx, 'tcx>(
286         self: PrintCx<'_, 'gcx, 'tcx, Self>,
287         print_prefix: impl FnOnce(
288             PrintCx<'_, 'gcx, 'tcx, Self>,
289         ) -> Result<Self::Path, Self::Error>,
290         self_ty: Ty<'tcx>,
291         trait_ref: Option<ty::TraitRef<'tcx>>,
292     ) -> Result<Self::Path, Self::Error>;
293     fn path_append<'gcx, 'tcx>(
294         self: PrintCx<'_, 'gcx, 'tcx, Self>,
295         print_prefix: impl FnOnce(
296             PrintCx<'_, 'gcx, 'tcx, Self>,
297         ) -> Result<Self::Path, Self::Error>,
298         text: &str,
299     ) -> Result<Self::Path, Self::Error>;
300     fn path_generic_args<'gcx, 'tcx>(
301         self: PrintCx<'_, 'gcx, 'tcx, Self>,
302         print_prefix: impl FnOnce(
303             PrintCx<'_, 'gcx, 'tcx, Self>,
304         ) -> Result<Self::Path, Self::Error>,
305         params: &[ty::GenericParamDef],
306         substs: SubstsRef<'tcx>,
307         ns: Namespace,
308         projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
309     ) -> Result<Self::Path, Self::Error>;
310 }
311
312 /// Trait for printers that pretty-print using `fmt::Write` to the printer.
313 pub trait PrettyPrinter: Printer<Error = fmt::Error, Path = Self> + fmt::Write {
314     /// Enter a nested print context, for pretty-printing
315     /// nested components in some larger context.
316     fn nest<'a, 'gcx, 'tcx, E>(
317         self: PrintCx<'a, 'gcx, 'tcx, Self>,
318         f: impl for<'b> FnOnce(PrintCx<'b, 'gcx, 'tcx, Self>) -> Result<Self, E>,
319     ) -> Result<PrintCx<'a, 'gcx, 'tcx, Self>, E> {
320         let printer = f(PrintCx {
321             tcx: self.tcx,
322             printer: self.printer,
323             config: self.config,
324         })?;
325         Ok(PrintCx {
326             tcx: self.tcx,
327             printer,
328             config: self.config,
329         })
330     }
331
332     fn region_highlight_mode(&self) -> RegionHighlightMode {
333         RegionHighlightMode::default()
334     }
335 }
336
337 macro_rules! nest {
338     ($cx:ident, $closure:expr) => {
339         $cx = $cx.nest($closure)?
340     }
341 }
342
343 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
344     // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
345     // (but also some things just print a `DefId` generally so maybe we need this?)
346     fn guess_def_namespace(self, def_id: DefId) -> Namespace {
347         match self.def_key(def_id).disambiguated_data.data {
348             DefPathData::ValueNs(..) |
349             DefPathData::EnumVariant(..) |
350             DefPathData::Field(..) |
351             DefPathData::AnonConst |
352             DefPathData::ConstParam(..) |
353             DefPathData::ClosureExpr |
354             DefPathData::StructCtor => Namespace::ValueNS,
355
356             DefPathData::MacroDef(..) => Namespace::MacroNS,
357
358             _ => Namespace::TypeNS,
359         }
360     }
361
362     /// Returns a string identifying this `DefId`. This string is
363     /// suitable for user output.
364     pub fn def_path_str(self, def_id: DefId) -> String {
365         let ns = self.guess_def_namespace(def_id);
366         debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
367         let mut s = String::new();
368         let _ = PrintCx::with(self, FmtPrinter::new(&mut s), |cx| {
369             cx.print_def_path(def_id, None, ns, iter::empty())
370         });
371         s
372     }
373 }
374
375 impl<P: Printer> PrintCx<'a, 'gcx, 'tcx, P> {
376     pub fn default_print_def_path(
377         self,
378         def_id: DefId,
379         substs: Option<SubstsRef<'tcx>>,
380         ns: Namespace,
381         projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
382     ) -> Result<P::Path, P::Error> {
383         debug!("default_print_def_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns);
384         let key = self.tcx.def_key(def_id);
385         debug!("default_print_def_path: key={:?}", key);
386
387         match key.disambiguated_data.data {
388             DefPathData::CrateRoot => {
389                 assert!(key.parent.is_none());
390                 self.path_crate(def_id.krate)
391             }
392
393             DefPathData::Impl => {
394                 let mut self_ty = self.tcx.type_of(def_id);
395                 if let Some(substs) = substs {
396                     self_ty = self_ty.subst(self.tcx, substs);
397                 }
398
399                 let mut impl_trait_ref = self.tcx.impl_trait_ref(def_id);
400                 if let Some(substs) = substs {
401                     impl_trait_ref = impl_trait_ref.subst(self.tcx, substs);
402                 }
403                 self.print_impl_path(def_id, substs, ns, self_ty, impl_trait_ref)
404             }
405
406             _ => {
407                 let generics = substs.map(|_| self.tcx.generics_of(def_id));
408                 let generics_parent = generics.as_ref().and_then(|g| g.parent);
409                 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
410                 let print_parent_path = |cx: PrintCx<'_, 'gcx, 'tcx, P>| {
411                     if let Some(generics_parent_def_id) = generics_parent {
412                         assert_eq!(parent_def_id, generics_parent_def_id);
413
414                         // FIXME(eddyb) try to move this into the parent's printing
415                         // logic, instead of doing it when printing the child.
416                         let parent_generics = cx.tcx.generics_of(parent_def_id);
417                         let parent_has_own_self =
418                             parent_generics.has_self && parent_generics.parent_count == 0;
419                         if let (Some(substs), true) = (substs, parent_has_own_self) {
420                             let trait_ref = ty::TraitRef::new(parent_def_id, substs);
421                             cx.path_qualified(trait_ref.self_ty(), Some(trait_ref), ns)
422                         } else {
423                             cx.print_def_path(parent_def_id, substs, ns, iter::empty())
424                         }
425                     } else {
426                         cx.print_def_path(parent_def_id, None, ns, iter::empty())
427                     }
428                 };
429                 let print_path = |cx: PrintCx<'_, 'gcx, 'tcx, P>| {
430                     match key.disambiguated_data.data {
431                         // Skip `::{{constructor}}` on tuple/unit structs.
432                         DefPathData::StructCtor => print_parent_path(cx),
433
434                         _ => {
435                             cx.path_append(
436                                 print_parent_path,
437                                 &key.disambiguated_data.data.as_interned_str().as_str(),
438                             )
439                         }
440                     }
441                 };
442
443                 if let (Some(generics), Some(substs)) = (generics, substs) {
444                     let has_own_self = generics.has_self && generics.parent_count == 0;
445                     let params = &generics.params[has_own_self as usize..];
446                     self.path_generic_args(print_path, params, substs, ns, projections)
447                 } else {
448                     print_path(self)
449                 }
450             }
451         }
452     }
453
454     fn default_print_impl_path(
455         self,
456         impl_def_id: DefId,
457         _substs: Option<SubstsRef<'tcx>>,
458         ns: Namespace,
459         self_ty: Ty<'tcx>,
460         impl_trait_ref: Option<ty::TraitRef<'tcx>>,
461     ) -> Result<P::Path, P::Error> {
462         debug!("default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
463                impl_def_id, self_ty, impl_trait_ref);
464
465         // Decide whether to print the parent path for the impl.
466         // Logically, since impls are global, it's never needed, but
467         // users may find it useful. Currently, we omit the parent if
468         // the impl is either in the same module as the self-type or
469         // as the trait.
470         let parent_def_id = self.tcx.parent(impl_def_id).unwrap();
471         let in_self_mod = match characteristic_def_id_of_type(self_ty) {
472             None => false,
473             Some(ty_def_id) => self.tcx.parent(ty_def_id) == Some(parent_def_id),
474         };
475         let in_trait_mod = match impl_trait_ref {
476             None => false,
477             Some(trait_ref) => self.tcx.parent(trait_ref.def_id) == Some(parent_def_id),
478         };
479
480         if !in_self_mod && !in_trait_mod {
481             // If the impl is not co-located with either self-type or
482             // trait-type, then fallback to a format that identifies
483             // the module more clearly.
484             self.path_append_impl(
485                 |cx| cx.print_def_path(parent_def_id, None, ns, iter::empty()),
486                 self_ty,
487                 impl_trait_ref,
488             )
489         } else {
490             // Otherwise, try to give a good form that would be valid language
491             // syntax. Preferably using associated item notation.
492             self.path_qualified(self_ty, impl_trait_ref, ns)
493         }
494     }
495 }
496
497 /// As a heuristic, when we see an impl, if we see that the
498 /// 'self type' is a type defined in the same module as the impl,
499 /// we can omit including the path to the impl itself. This
500 /// function tries to find a "characteristic `DefId`" for a
501 /// type. It's just a heuristic so it makes some questionable
502 /// decisions and we may want to adjust it later.
503 pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
504     match ty.sty {
505         ty::Adt(adt_def, _) => Some(adt_def.did),
506
507         ty::Dynamic(data, ..) => data.principal_def_id(),
508
509         ty::Array(subty, _) |
510         ty::Slice(subty) => characteristic_def_id_of_type(subty),
511
512         ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
513
514         ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
515
516         ty::Tuple(ref tys) => tys.iter()
517                                    .filter_map(|ty| characteristic_def_id_of_type(ty))
518                                    .next(),
519
520         ty::FnDef(def_id, _) |
521         ty::Closure(def_id, _) |
522         ty::Generator(def_id, _, _) |
523         ty::Foreign(def_id) => Some(def_id),
524
525         ty::Bool |
526         ty::Char |
527         ty::Int(_) |
528         ty::Uint(_) |
529         ty::Str |
530         ty::FnPtr(_) |
531         ty::Projection(_) |
532         ty::Placeholder(..) |
533         ty::UnnormalizedProjection(..) |
534         ty::Param(_) |
535         ty::Opaque(..) |
536         ty::Infer(_) |
537         ty::Bound(..) |
538         ty::Error |
539         ty::GeneratorWitness(..) |
540         ty::Never |
541         ty::Float(_) => None,
542     }
543 }
544
545 pub struct FmtPrinter<F: fmt::Write> {
546     pub(crate) fmt: F,
547     empty: bool,
548     pub region_highlight_mode: RegionHighlightMode,
549 }
550
551 impl<F: fmt::Write> FmtPrinter<F> {
552     pub fn new(fmt: F) -> Self {
553         FmtPrinter {
554             fmt,
555             empty: true,
556             region_highlight_mode: RegionHighlightMode::default(),
557         }
558     }
559 }
560
561 impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> {
562     /// If possible, this returns a global path resolving to `def_id` that is visible
563     /// from at least one local module and returns true. If the crate defining `def_id` is
564     /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
565     fn try_print_visible_def_path(
566         mut self,
567         def_id: DefId,
568     ) -> Result<(P, bool), P::Error> {
569         debug!("try_print_visible_def_path: def_id={:?}", def_id);
570
571         // If `def_id` is a direct or injected extern crate, return the
572         // path to the crate followed by the path to the item within the crate.
573         if def_id.index == CRATE_DEF_INDEX {
574             let cnum = def_id.krate;
575
576             if cnum == LOCAL_CRATE {
577                 return Ok((self.path_crate(cnum)?, true));
578             }
579
580             // In local mode, when we encounter a crate other than
581             // LOCAL_CRATE, execution proceeds in one of two ways:
582             //
583             // 1. for a direct dependency, where user added an
584             //    `extern crate` manually, we put the `extern
585             //    crate` as the parent. So you wind up with
586             //    something relative to the current crate.
587             // 2. for an extern inferred from a path or an indirect crate,
588             //    where there is no explicit `extern crate`, we just prepend
589             //    the crate name.
590             match *self.tcx.extern_crate(def_id) {
591                 Some(ExternCrate {
592                     src: ExternCrateSource::Extern(def_id),
593                     direct: true,
594                     span,
595                     ..
596                 }) => {
597                     debug!("try_print_visible_def_path: def_id={:?}", def_id);
598                     return Ok((if !span.is_dummy() {
599                         self.print_def_path(def_id, None, Namespace::TypeNS, iter::empty())?
600                     } else {
601                         self.path_crate(cnum)?
602                     }, true));
603                 }
604                 None => {
605                     return Ok((self.path_crate(cnum)?, true));
606                 }
607                 _ => {},
608             }
609         }
610
611         if def_id.is_local() {
612             return Ok((self.printer, false));
613         }
614
615         let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE);
616
617         let mut cur_def_key = self.tcx.def_key(def_id);
618         debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
619
620         // For a UnitStruct or TupleStruct we want the name of its parent rather than <unnamed>.
621         if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data {
622             let parent = DefId {
623                 krate: def_id.krate,
624                 index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"),
625             };
626
627             cur_def_key = self.tcx.def_key(parent);
628         }
629
630         let visible_parent = match visible_parent_map.get(&def_id).cloned() {
631             Some(parent) => parent,
632             None => return Ok((self.printer, false)),
633         };
634         // HACK(eddyb) this uses `nest` to avoid knowing ahead of time whether
635         // the entire path will succeed or not. To support printers that do not
636         // implement `PrettyPrinter`, a `Vec` or linked list on the stack would
637         // need to be built, before starting to print anything.
638         let mut prefix_success = false;
639         nest!(self, |cx| {
640             let (printer, success) = cx.try_print_visible_def_path(visible_parent)?;
641             prefix_success = success;
642             Ok(printer)
643         });
644         if !prefix_success {
645             return Ok((self.printer, false));
646         };
647         let actual_parent = self.tcx.parent(def_id);
648
649         let data = cur_def_key.disambiguated_data.data;
650         debug!(
651             "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}",
652             data, visible_parent, actual_parent,
653         );
654
655         let symbol = match data {
656             // In order to output a path that could actually be imported (valid and visible),
657             // we need to handle re-exports correctly.
658             //
659             // For example, take `std::os::unix::process::CommandExt`, this trait is actually
660             // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing).
661             //
662             // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is
663             // private so the "true" path to `CommandExt` isn't accessible.
664             //
665             // In this case, the `visible_parent_map` will look something like this:
666             //
667             // (child) -> (parent)
668             // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process`
669             // `std::sys::unix::ext::process` -> `std::sys::unix::ext`
670             // `std::sys::unix::ext` -> `std::os`
671             //
672             // This is correct, as the visible parent of `std::sys::unix::ext` is in fact
673             // `std::os`.
674             //
675             // When printing the path to `CommandExt` and looking at the `cur_def_key` that
676             // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go
677             // to the parent - resulting in a mangled path like
678             // `std::os::ext::process::CommandExt`.
679             //
680             // Instead, we must detect that there was a re-export and instead print `unix`
681             // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To
682             // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with
683             // the visible parent (`std::os`). If these do not match, then we iterate over
684             // the children of the visible parent (as was done when computing
685             // `visible_parent_map`), looking for the specific child we currently have and then
686             // have access to the re-exported name.
687             DefPathData::Module(actual_name) |
688             DefPathData::TypeNs(actual_name) if Some(visible_parent) != actual_parent => {
689                 self.tcx.item_children(visible_parent)
690                     .iter()
691                     .find(|child| child.def.def_id() == def_id)
692                     .map(|child| child.ident.as_str())
693                     .unwrap_or_else(|| actual_name.as_str())
694             }
695             _ => {
696                 data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| {
697                     // Re-exported `extern crate` (#43189).
698                     if let DefPathData::CrateRoot = data {
699                         self.tcx.original_crate_name(def_id.krate).as_str()
700                     } else {
701                         Symbol::intern("<unnamed>").as_str()
702                     }
703                 })
704             },
705         };
706         debug!("try_print_visible_def_path: symbol={:?}", symbol);
707         Ok((self.path_append(|cx| Ok(cx.printer), &symbol)?, true))
708     }
709
710     pub fn pretty_path_qualified(
711         mut self,
712         self_ty: Ty<'tcx>,
713         trait_ref: Option<ty::TraitRef<'tcx>>,
714         ns: Namespace,
715     ) -> Result<P::Path, P::Error> {
716         if trait_ref.is_none() {
717             // Inherent impls. Try to print `Foo::bar` for an inherent
718             // impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
719             // anything other than a simple path.
720             match self_ty.sty {
721                 ty::Adt(adt_def, substs) => {
722                     return self.print_def_path(adt_def.did, Some(substs), ns, iter::empty());
723                 }
724                 ty::Foreign(did) => {
725                     return self.print_def_path(did, None, ns, iter::empty());
726                 }
727
728                 ty::Bool | ty::Char | ty::Str |
729                 ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
730                     return self_ty.print_display(self);
731                 }
732
733                 _ => {}
734             }
735         }
736
737         write!(self.printer, "<")?;
738         nest!(self, |cx| self_ty.print_display(cx));
739         if let Some(trait_ref) = trait_ref {
740             write!(self.printer, " as ")?;
741             nest!(self, |cx| cx.print_def_path(
742                 trait_ref.def_id,
743                 Some(trait_ref.substs),
744                 Namespace::TypeNS,
745                 iter::empty(),
746             ));
747         }
748         write!(self.printer, ">")?;
749
750         Ok(self.printer)
751     }
752
753     pub fn pretty_path_append_impl(
754         mut self,
755         print_prefix: impl FnOnce(
756             PrintCx<'_, 'gcx, 'tcx, P>,
757         ) -> Result<P::Path, P::Error>,
758         self_ty: Ty<'tcx>,
759         trait_ref: Option<ty::TraitRef<'tcx>>,
760     ) -> Result<P::Path, P::Error> {
761         // HACK(eddyb) going through `path_append` means symbol name
762         // computation gets to handle its equivalent of `::` correctly.
763         nest!(self, |cx| cx.path_append(print_prefix, "<impl "));
764         if let Some(trait_ref) = trait_ref {
765             nest!(self, |cx| trait_ref.print_display(cx));
766             write!(self.printer, " for ")?;
767         }
768         nest!(self, |cx| self_ty.print_display(cx));
769         write!(self.printer, ">")?;
770
771         Ok(self.printer)
772     }
773
774     pub fn pretty_path_generic_args(
775         mut self,
776         print_prefix: impl FnOnce(
777             PrintCx<'_, 'gcx, 'tcx, P>,
778         ) -> Result<P::Path, P::Error>,
779         params: &[ty::GenericParamDef],
780         substs: SubstsRef<'tcx>,
781         ns: Namespace,
782         projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
783     ) -> Result<P::Path, P::Error> {
784         nest!(self, |cx| print_prefix(cx));
785
786         let mut empty = true;
787         let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
788             write!(cx.printer, "{}", if empty {
789                 empty = false;
790                 start
791             } else {
792                 cont
793             })
794         };
795
796         let start = if ns == Namespace::ValueNS { "::<" } else { "<" };
797
798         // Don't print any regions if they're all erased.
799         let print_regions = params.iter().any(|param| {
800             match substs[param.index as usize].unpack() {
801                 UnpackedKind::Lifetime(r) => *r != ty::ReErased,
802                 _ => false,
803             }
804         });
805
806         // Don't print args that are the defaults of their respective parameters.
807         let num_supplied_defaults = if self.config.is_verbose {
808             0
809         } else {
810             params.iter().rev().take_while(|param| {
811                 match param.kind {
812                     ty::GenericParamDefKind::Lifetime => false,
813                     ty::GenericParamDefKind::Type { has_default, .. } => {
814                         has_default && substs[param.index as usize] == Kind::from(
815                             self.tcx.type_of(param.def_id).subst(self.tcx, substs)
816                         )
817                     }
818                     ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
819                 }
820             }).count()
821         };
822
823         for param in &params[..params.len() - num_supplied_defaults] {
824             match substs[param.index as usize].unpack() {
825                 UnpackedKind::Lifetime(region) => {
826                     if !print_regions {
827                         continue;
828                     }
829                     start_or_continue(&mut self, start, ", ")?;
830                     if !region.display_outputs_anything(&self) {
831                         // This happens when the value of the region
832                         // parameter is not easily serialized. This may be
833                         // because the user omitted it in the first place,
834                         // or because it refers to some block in the code,
835                         // etc. I'm not sure how best to serialize this.
836                         write!(self.printer, "'_")?;
837                     } else {
838                         nest!(self, |cx| region.print_display(cx));
839                     }
840                 }
841                 UnpackedKind::Type(ty) => {
842                     start_or_continue(&mut self, start, ", ")?;
843                     nest!(self, |cx| ty.print_display(cx));
844                 }
845                 UnpackedKind::Const(ct) => {
846                     start_or_continue(self, start, ", ")?;
847                     ct.print_display(self)?;
848                 }
849             }
850         }
851
852         for projection in projections {
853             start_or_continue(&mut self, start, ", ")?;
854             write!(self.printer, "{}=",
855                    self.tcx.associated_item(projection.item_def_id).ident)?;
856             nest!(self, |cx| projection.ty.print_display(cx));
857         }
858
859         start_or_continue(&mut self, "", ">")?;
860
861         Ok(self.printer)
862     }
863 }
864
865 impl<F: fmt::Write> fmt::Write for FmtPrinter<F> {
866     fn write_str(&mut self, s: &str) -> fmt::Result {
867         self.empty &= s.is_empty();
868         self.fmt.write_str(s)
869     }
870 }
871
872 impl<F: fmt::Write> Printer for FmtPrinter<F> {
873     type Error = fmt::Error;
874
875     type Path = Self;
876
877     fn print_def_path(
878         mut self: PrintCx<'_, '_, 'tcx, Self>,
879         def_id: DefId,
880         substs: Option<SubstsRef<'tcx>>,
881         ns: Namespace,
882         projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
883     ) -> Result<Self::Path, Self::Error> {
884         // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key`
885         // both here and in `default_print_def_path`.
886         let generics = substs.map(|_| self.tcx.generics_of(def_id));
887         if generics.as_ref().and_then(|g| g.parent).is_none() {
888             let mut visible_path_success = false;
889             nest!(self, |cx| {
890                 let (printer, success) = cx.try_print_visible_def_path(def_id)?;
891                 visible_path_success = success;
892                 Ok(printer)
893             });
894             if visible_path_success {
895                 return if let (Some(generics), Some(substs)) = (generics, substs) {
896                     let has_own_self = generics.has_self && generics.parent_count == 0;
897                     let params = &generics.params[has_own_self as usize..];
898                     self.path_generic_args(|cx| Ok(cx.printer), params, substs, ns, projections)
899                 } else {
900                     Ok(self.printer)
901                 };
902             }
903         }
904
905         let key = self.tcx.def_key(def_id);
906         if let DefPathData::Impl = key.disambiguated_data.data {
907             // Always use types for non-local impls, where types are always
908             // available, and filename/line-number is mostly uninteresting.
909             let use_types =
910                 !def_id.is_local() || {
911                     // Otherwise, use filename/line-number if forced.
912                     let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
913                     !force_no_types
914                 };
915
916             if !use_types {
917                 // If no type info is available, fall back to
918                 // pretty printing some span information. This should
919                 // only occur very early in the compiler pipeline.
920                 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
921                 let span = self.tcx.def_span(def_id);
922                 return self.path_append(
923                     |cx| cx.print_def_path(parent_def_id, None, ns, iter::empty()),
924                     &format!("<impl at {:?}>", span),
925                 );
926             }
927         }
928
929         self.default_print_def_path(def_id, substs, ns, projections)
930     }
931
932     fn path_crate(
933         mut self: PrintCx<'_, '_, '_, Self>,
934         cnum: CrateNum,
935     ) -> Result<Self::Path, Self::Error> {
936         if cnum == LOCAL_CRATE {
937             if self.tcx.sess.rust_2018() {
938                 // We add the `crate::` keyword on Rust 2018, only when desired.
939                 if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
940                     write!(self.printer, "{}", keywords::Crate.name())?;
941                 }
942             }
943             Ok(self.printer)
944         } else {
945             write!(self.printer, "{}", self.tcx.crate_name(cnum))?;
946             Ok(self.printer)
947         }
948     }
949     fn path_qualified(
950         self: PrintCx<'_, '_, 'tcx, Self>,
951         self_ty: Ty<'tcx>,
952         trait_ref: Option<ty::TraitRef<'tcx>>,
953         ns: Namespace,
954     ) -> Result<Self::Path, Self::Error> {
955         self.pretty_path_qualified(self_ty, trait_ref, ns)
956     }
957
958     fn path_append_impl<'gcx, 'tcx>(
959         self: PrintCx<'_, 'gcx, 'tcx, Self>,
960         print_prefix: impl FnOnce(
961             PrintCx<'_, 'gcx, 'tcx, Self>,
962         ) -> Result<Self::Path, Self::Error>,
963         self_ty: Ty<'tcx>,
964         trait_ref: Option<ty::TraitRef<'tcx>>,
965     ) -> Result<Self::Path, Self::Error> {
966         self.pretty_path_append_impl(print_prefix, self_ty, trait_ref)
967     }
968     fn path_append<'gcx, 'tcx>(
969         self: PrintCx<'_, 'gcx, 'tcx, Self>,
970         print_prefix: impl FnOnce(
971             PrintCx<'_, 'gcx, 'tcx, Self>,
972         ) -> Result<Self::Path, Self::Error>,
973         text: &str,
974     ) -> Result<Self::Path, Self::Error> {
975         let mut printer = print_prefix(self)?;
976
977         // FIXME(eddyb) `text` should never be empty, but it
978         // currently is for `extern { ... }` "foreign modules".
979         if !text.is_empty() {
980             if !printer.empty {
981                 write!(printer, "::")?;
982             }
983             write!(printer, "{}", text)?;
984         }
985
986         Ok(printer)
987     }
988     fn path_generic_args<'gcx, 'tcx>(
989         self: PrintCx<'_, 'gcx, 'tcx, Self>,
990         print_prefix: impl FnOnce(
991             PrintCx<'_, 'gcx, 'tcx, Self>,
992         ) -> Result<Self::Path, Self::Error>,
993         params: &[ty::GenericParamDef],
994         substs: SubstsRef<'tcx>,
995         ns: Namespace,
996         projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
997     ) -> Result<Self::Path, Self::Error> {
998         self.pretty_path_generic_args(print_prefix, params, substs, ns, projections)
999     }
1000 }
1001
1002 impl<F: fmt::Write> PrettyPrinter for FmtPrinter<F> {
1003     fn nest<'a, 'gcx, 'tcx, E>(
1004         mut self: PrintCx<'a, 'gcx, 'tcx, Self>,
1005         f: impl for<'b> FnOnce(PrintCx<'b, 'gcx, 'tcx, Self>) -> Result<Self, E>,
1006     ) -> Result<PrintCx<'a, 'gcx, 'tcx, Self>, E> {
1007         let was_empty = std::mem::replace(&mut self.printer.empty, true);
1008         let mut printer = f(PrintCx {
1009             tcx: self.tcx,
1010             printer: self.printer,
1011             config: self.config,
1012         })?;
1013         printer.empty &= was_empty;
1014         Ok(PrintCx {
1015             tcx: self.tcx,
1016             printer,
1017             config: self.config,
1018         })
1019     }
1020
1021     fn region_highlight_mode(&self) -> RegionHighlightMode {
1022         self.region_highlight_mode
1023     }
1024 }