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};
8 use syntax::symbol::{keywords, Symbol};
10 use rustc_data_structures::fx::FxHashSet;
11 use syntax::symbol::InternedString;
14 use std::fmt::{self, Write as _};
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);
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();
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();
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| {
63 // FIXME(eddyb) this module uses `pub(crate)` for things used only
64 // from `ppaux` - when that is removed, they can be re-privatized.
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 {
70 ty::ReLateBound(_, ty::BrNamed(_, name)) => {
75 r.super_visit_with(self)
79 pub struct PrintCx<'a, 'gcx, 'tcx, P> {
80 pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
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,
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> {
94 fn deref(&self) -> &P {
99 impl<P> PrintCx<'a, 'gcx, 'tcx, P> {
100 pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, printer: P) -> Self {
105 is_verbose: tcx.sess.verbose(),
106 identify_regions: tcx.sess.opts.debugging_opts.identify_regions,
107 used_region_names: None,
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)))
116 pub(crate) fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<T>)
117 where T: TypeFoldable<'tcx>
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;
126 pub trait Print<'tcx, P> {
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;
133 let result = self.print(cx);
134 cx.is_debug = old_debug;
137 fn print_debug(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output {
138 let old_debug = cx.is_debug;
140 let result = self.print(cx);
141 cx.is_debug = old_debug;
146 pub trait Printer: Sized {
151 self: &mut PrintCx<'_, '_, 'tcx, Self>,
153 substs: Option<SubstsRef<'tcx>>,
155 projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
157 self.default_print_def_path(def_id, substs, ns, projections)
161 self: &mut PrintCx<'_, '_, 'tcx, Self>,
163 substs: Option<SubstsRef<'tcx>>,
166 trait_ref: Option<ty::TraitRef<'tcx>>,
168 self.default_print_impl_path(impl_def_id, substs, ns, self_ty, trait_ref)
172 fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path;
175 self: &mut PrintCx<'_, '_, 'tcx, Self>,
176 impl_prefix: Option<Self::Path>,
178 trait_ref: Option<ty::TraitRef<'tcx>>,
183 self: &mut PrintCx<'_, '_, '_, Self>,
188 fn path_generic_args(
189 self: &mut PrintCx<'_, '_, 'tcx, Self>,
191 params: &[ty::GenericParamDef],
192 substs: SubstsRef<'tcx>,
194 projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
199 pub struct PrettyPath {
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 {}
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,
219 DefPathData::MacroDef(..) => Namespace::MacroNS,
221 _ => Namespace::TypeNS,
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(
231 substs: Option<SubstsRef<'tcx>>,
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());
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());
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))
260 impl<P: Printer> PrintCx<'a, 'gcx, 'tcx, P> {
261 pub fn default_print_def_path(
264 substs: Option<SubstsRef<'tcx>>,
266 projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
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);
272 match key.disambiguated_data.data {
273 DefPathData::CrateRoot => {
274 assert!(key.parent.is_none());
275 self.path_crate(def_id.krate)
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);
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);
288 self.print_impl_path(def_id, substs, ns, self_ty, impl_trait_ref)
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);
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)
307 self.print_def_path(parent_def_id, substs, ns, iter::empty())
310 self.print_def_path(parent_def_id, None, ns, iter::empty())
312 let path = match key.disambiguated_data.data {
313 // Skip `::{{constructor}}` on tuple/unit structs.
314 DefPathData::StructCtor => path,
319 &key.disambiguated_data.data.as_interned_str().as_str(),
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)
335 fn default_print_impl_path(
338 _substs: Option<SubstsRef<'tcx>>,
341 impl_trait_ref: Option<ty::TraitRef<'tcx>>,
343 debug!("default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
344 impl_def_id, self_ty, impl_trait_ref);
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
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) {
354 Some(ty_def_id) => self.tcx.parent(ty_def_id) == Some(parent_def_id),
356 let in_trait_mod = match impl_trait_ref {
358 Some(trait_ref) => self.tcx.parent(trait_ref.def_id) == Some(parent_def_id),
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()))
367 // Otherwise, try to give a good form that would be valid language
368 // syntax. Preferably using associated item notation.
372 self.path_qualified(prefix_path, self_ty, impl_trait_ref, ns)
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> {
384 ty::Adt(adt_def, _) => Some(adt_def.did),
386 ty::Dynamic(data, ..) => data.principal_def_id(),
388 ty::Array(subty, _) |
389 ty::Slice(subty) => characteristic_def_id_of_type(subty),
391 ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
393 ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
395 ty::Tuple(ref tys) => tys.iter()
396 .filter_map(|ty| characteristic_def_id_of_type(ty))
399 ty::FnDef(def_id, _) |
400 ty::Closure(def_id, _) |
401 ty::Generator(def_id, _, _) |
402 ty::Foreign(def_id) => Some(def_id),
411 ty::Placeholder(..) |
412 ty::UnnormalizedProjection(..) |
418 ty::GeneratorWitness(..) |
420 ty::Float(_) => None,
424 pub struct FmtPrinter<F: fmt::Write> {
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);
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;
440 if cnum == LOCAL_CRATE {
441 return Some(self.path_crate(cnum));
444 // In local mode, when we encounter a crate other than
445 // LOCAL_CRATE, execution proceeds in one of two ways:
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
454 match *self.tcx.extern_crate(def_id) {
456 src: ExternCrateSource::Extern(def_id),
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())
465 self.path_crate(cnum)
470 return Some(self.path_crate(cnum));
476 if def_id.is_local() {
480 let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE);
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);
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 {
489 index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"),
492 cur_def_key = self.tcx.def_key(parent);
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);
499 let data = cur_def_key.disambiguated_data.data;
501 "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}",
502 data, visible_parent, actual_parent,
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.
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).
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.
515 // In this case, the `visible_parent_map` will look something like this:
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`
522 // This is correct, as the visible parent of `std::sys::unix::ext` is in fact
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`.
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)
541 .find(|child| child.def.def_id() == def_id)
542 .map(|child| child.ident.as_str())
543 .unwrap_or_else(|| actual_name.as_str())
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()
551 Symbol::intern("<unnamed>").as_str()
556 debug!("try_print_visible_def_path: symbol={:?}", symbol);
557 Some(self.path_append(path, &symbol))
560 pub fn pretty_path_qualified(
562 impl_prefix: Option<P::Path>,
564 trait_ref: Option<ty::TraitRef<'tcx>>,
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 ")?;
575 self_ty.print_display(self)?;
576 write!(self.printer, ">")?;
577 return Ok(PrettyPath { empty: false });
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.
585 ty::Adt(adt_def, substs) => {
586 return self.print_def_path(adt_def.did, Some(substs), ns, iter::empty());
588 ty::Foreign(did) => {
589 return self.print_def_path(did, None, ns, iter::empty());
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 });
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(
608 Some(trait_ref.substs),
613 write!(self.printer, ">")?;
614 Ok(PrettyPath { empty: false })
617 pub fn pretty_path_generic_args(
620 params: &[ty::GenericParamDef],
621 substs: SubstsRef<'tcx>,
623 projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
627 let mut empty = true;
628 let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
631 write!(cx.printer, "{}", start)
633 write!(cx.printer, "{}", cont)
637 let start = if ns == Namespace::ValueNS { "::<" } else { "<" };
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,
647 // Don't print args that are the defaults of their respective parameters.
648 let num_supplied_defaults = if self.is_verbose {
651 params.iter().rev().take_while(|param| {
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)
659 ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
664 for param in ¶ms[..params.len() - num_supplied_defaults] {
665 match substs[param.index as usize].unpack() {
666 UnpackedKind::Lifetime(region) => {
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, "'_")?;
679 region.print_display(self)?;
682 UnpackedKind::Type(ty) => {
683 start_or_continue(self, start, ", ")?;
684 ty.print_display(self)?;
686 UnpackedKind::Const(ct) => {
687 start_or_continue(self, start, ", ")?;
688 ct.print_display(self)?;
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)?;
700 start_or_continue(self, "", ">")?;
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)
712 impl<F: fmt::Write> Printer for FmtPrinter<F> {
713 type Path = Result<PrettyPath, fmt::Error>;
716 self: &mut PrintCx<'_, '_, 'tcx, Self>,
718 substs: Option<SubstsRef<'tcx>>,
720 projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
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)
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.
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());
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));
764 self.default_print_def_path(def_id, substs, ns, projections)
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 });
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 });
781 Ok(PrettyPath { empty: true })
783 write!(self.printer, "{}", self.tcx.crate_name(cnum))?;
784 Ok(PrettyPath { empty: false })
788 self: &mut PrintCx<'_, '_, 'tcx, Self>,
789 impl_prefix: Option<Self::Path>,
791 trait_ref: Option<ty::TraitRef<'tcx>>,
794 self.pretty_path_qualified(impl_prefix, self_ty, trait_ref, ns)
797 self: &mut PrintCx<'_, '_, '_, Self>,
803 // FIXME(eddyb) this shouldn't happen, but is currently
804 // the case for `extern { ... }` "foreign modules".
810 write!(self.printer, "::")?;
812 write!(self.printer, "{}", text)?;
813 Ok(PrettyPath { empty: false })
815 fn path_generic_args(
816 self: &mut PrintCx<'_, '_, 'tcx, Self>,
818 params: &[ty::GenericParamDef],
819 substs: SubstsRef<'tcx>,
821 projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
823 self.pretty_path_generic_args(path, params, substs, ns, projections)
827 impl<F: fmt::Write> PrettyPrinter for FmtPrinter<F> {}