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