2 use crate::hir
::def
::{Namespace, DefKind}
;
3 use crate::hir
::map
::{DefPathData, DisambiguatedDefPathData}
;
4 use crate::hir
::def_id
::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}
;
5 use crate::middle
::cstore
::{ExternCrate, ExternCrateSource}
;
6 use crate::middle
::region
;
7 use crate::ty
::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable}
;
8 use crate::ty
::subst
::{GenericArg, Subst, GenericArgKind}
;
9 use crate::ty
::layout
::{Integer, IntegerExt, Size}
;
10 use crate::mir
::interpret
::{ConstValue, sign_extend, Scalar, truncate}
;
12 use rustc_apfloat
::ieee
::{Double, Single}
;
13 use rustc_apfloat
::Float
;
14 use rustc_target
::spec
::abi
::Abi
;
16 use syntax
::attr
::{SignedInt, UnsignedInt}
;
17 use syntax
::symbol
::{kw, Symbol}
;
20 use std
::collections
::BTreeMap
;
21 use std
::fmt
::{self, Write as _}
;
22 use std
::ops
::{Deref, DerefMut}
;
24 // `pretty` is a separate module only for organization.
28 (@
write($
($data
:expr
),+)) => {
29 write
!(scoped_cx
!(), $
($data
),+)?
31 (@
print($x
:expr
)) => {
32 scoped_cx
!() = $x
.print(scoped_cx
!())?
34 (@$method
:ident($
($arg
:expr
),*)) => {
35 scoped_cx
!() = scoped_cx
!().$
method($
($arg
),*)?
37 ($
($kind
:ident $data
:tt
),+) => {{
41 macro_rules
! define_scoped_cx
{
43 #[allow(unused_macros)]
44 macro_rules
! scoped_cx
{
51 static FORCE_IMPL_FILENAME_LINE
: Cell
<bool
> = Cell
::new(false);
52 static SHOULD_PREFIX_WITH_CRATE
: Cell
<bool
> = Cell
::new(false);
53 static NO_QUERIES
: Cell
<bool
> = Cell
::new(false);
56 /// Avoids running any queries during any prints that occur
57 /// during the closure. This may alter the appearance of some
58 /// types (e.g. forcing verbose printing for opaque types).
59 /// This method is used during some queries (e.g. `predicates_of`
60 /// for opaque types), to ensure that any debug printing that
61 /// occurs during the query computation does not end up recursively
62 /// calling the same query.
63 pub fn with_no_queries
<F
: FnOnce() -> R
, R
>(f
: F
) -> R
{
64 NO_QUERIES
.with(|no_queries
| {
65 let old
= no_queries
.get();
73 /// Force us to name impls with just the filename/line number. We
74 /// normally try to use types. But at some points, notably while printing
75 /// cycle errors, this can result in extra or suboptimal error output,
76 /// so this variable disables that check.
77 pub fn with_forced_impl_filename_line
<F
: FnOnce() -> R
, R
>(f
: F
) -> R
{
78 FORCE_IMPL_FILENAME_LINE
.with(|force
| {
79 let old
= force
.get();
87 /// Adds the `crate::` prefix to paths where appropriate.
88 pub fn with_crate_prefix
<F
: FnOnce() -> R
, R
>(f
: F
) -> R
{
89 SHOULD_PREFIX_WITH_CRATE
.with(|flag
| {
98 /// The "region highlights" are used to control region printing during
99 /// specific error messages. When a "region highlight" is enabled, it
100 /// gives an alternate way to print specific regions. For now, we
101 /// always print those regions using a number, so something like "`'0`".
103 /// Regions not selected by the region highlight mode are presently
105 #[derive(Copy, Clone, Default)]
106 pub struct RegionHighlightMode
{
107 /// If enabled, when we see the selected region, use "`'N`"
108 /// instead of the ordinary behavior.
109 highlight_regions
: [Option
<(ty
::RegionKind
, usize)>; 3],
111 /// If enabled, when printing a "free region" that originated from
112 /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
113 /// have names print as normal.
115 /// This is used when you have a signature like `fn foo(x: &u32,
116 /// y: &'a u32)` and we want to give a name to the region of the
118 highlight_bound_region
: Option
<(ty
::BoundRegion
, usize)>,
121 impl RegionHighlightMode
{
122 /// If `region` and `number` are both `Some`, invokes
123 /// `highlighting_region`.
124 pub fn maybe_highlighting_region(
126 region
: Option
<ty
::Region
<'_
>>,
127 number
: Option
<usize>,
129 if let Some(k
) = region
{
130 if let Some(n
) = number
{
131 self.highlighting_region(k
, n
);
136 /// Highlights the region inference variable `vid` as `'N`.
137 pub fn highlighting_region(
139 region
: ty
::Region
<'_
>,
142 let num_slots
= self.highlight_regions
.len();
143 let first_avail_slot
= self.highlight_regions
.iter_mut()
144 .filter(|s
| s
.is_none())
148 "can only highlight {} placeholders at a time",
152 *first_avail_slot
= Some((*region
, number
));
155 /// Convenience wrapper for `highlighting_region`.
156 pub fn highlighting_region_vid(
161 self.highlighting_region(&ty
::ReVar(vid
), number
)
164 /// Returns `Some(n)` with the number to use for the given region, if any.
165 fn region_highlighted(&self, region
: ty
::Region
<'_
>) -> Option
<usize> {
169 .filter_map(|h
| match h
{
170 Some((r
, n
)) if r
== region
=> Some(*n
),
176 /// Highlight the given bound region.
177 /// We can only highlight one bound region at a time. See
178 /// the field `highlight_bound_region` for more detailed notes.
179 pub fn highlighting_bound_region(
184 assert
!(self.highlight_bound_region
.is_none());
185 self.highlight_bound_region
= Some((br
, number
));
189 /// Trait for printers that pretty-print using `fmt::Write` to the printer.
190 pub trait PrettyPrinter
<'tcx
>:
197 DynExistential
= Self,
201 /// Like `print_def_path` but for value paths.
205 substs
: &'tcx
[GenericArg
<'tcx
>],
206 ) -> Result
<Self::Path
, Self::Error
> {
207 self.print_def_path(def_id
, substs
)
210 fn in_binder
<T
>(self, value
: &ty
::Binder
<T
>) -> Result
<Self, Self::Error
>
212 T
: Print
<'tcx
, Self, Output
= Self, Error
= Self::Error
> + TypeFoldable
<'tcx
>,
214 value
.skip_binder().print(self)
217 /// Prints comma-separated elements.
218 fn comma_sep
<T
>(mut self, mut elems
: impl Iterator
<Item
= T
>) -> Result
<Self, Self::Error
>
220 T
: Print
<'tcx
, Self, Output
= Self, Error
= Self::Error
>,
222 if let Some(first
) = elems
.next() {
223 self = first
.print(self)?
;
225 self.write_str(", ")?
;
226 self = elem
.print(self)?
;
232 /// Prints `<...>` around what `f` prints.
233 fn generic_delimiters(
235 f
: impl FnOnce(Self) -> Result
<Self, Self::Error
>,
236 ) -> Result
<Self, Self::Error
>;
238 /// Returns `true` if the region should be printed in
239 /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`.
240 /// This is typically the case for all non-`'_` regions.
241 fn region_should_not_be_omitted(
243 region
: ty
::Region
<'_
>,
246 // Defaults (should not be overriden):
248 /// If possible, this returns a global path resolving to `def_id` that is visible
249 /// from at least one local module, and returns `true`. If the crate defining `def_id` is
250 /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
251 fn try_print_visible_def_path(
254 ) -> Result
<(Self, bool
), Self::Error
> {
255 let mut callers
= Vec
::new();
256 self.try_print_visible_def_path_recur(def_id
, &mut callers
)
259 /// Does the work of `try_print_visible_def_path`, building the
260 /// full definition path recursively before attempting to
261 /// post-process it into the valid and visible version that
262 /// accounts for re-exports.
264 /// This method should only be callled by itself or
265 /// `try_print_visible_def_path`.
267 /// `callers` is a chain of visible_parent's leading to `def_id`,
268 /// to support cycle detection during recursion.
269 fn try_print_visible_def_path_recur(
272 callers
: &mut Vec
<DefId
>,
273 ) -> Result
<(Self, bool
), Self::Error
> {
274 define_scoped_cx
!(self);
276 debug
!("try_print_visible_def_path: def_id={:?}", def_id
);
278 // If `def_id` is a direct or injected extern crate, return the
279 // path to the crate followed by the path to the item within the crate.
280 if def_id
.index
== CRATE_DEF_INDEX
{
281 let cnum
= def_id
.krate
;
283 if cnum
== LOCAL_CRATE
{
284 return Ok((self.path_crate(cnum
)?
, true));
287 // In local mode, when we encounter a crate other than
288 // LOCAL_CRATE, execution proceeds in one of two ways:
290 // 1. For a direct dependency, where user added an
291 // `extern crate` manually, we put the `extern
292 // crate` as the parent. So you wind up with
293 // something relative to the current crate.
294 // 2. For an extern inferred from a path or an indirect crate,
295 // where there is no explicit `extern crate`, we just prepend
297 match self.tcx().extern_crate(def_id
) {
299 src
: ExternCrateSource
::Extern(def_id
),
300 dependency_of
: LOCAL_CRATE
,
304 debug
!("try_print_visible_def_path: def_id={:?}", def_id
);
305 return Ok((if !span
.is_dummy() {
306 self.print_def_path(def_id
, &[])?
308 self.path_crate(cnum
)?
312 return Ok((self.path_crate(cnum
)?
, true));
318 if def_id
.is_local() {
319 return Ok((self, false));
322 let visible_parent_map
= self.tcx().visible_parent_map(LOCAL_CRATE
);
324 let mut cur_def_key
= self.tcx().def_key(def_id
);
325 debug
!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key
);
327 // For a constructor, we want the name of its parent rather than <unnamed>.
328 match cur_def_key
.disambiguated_data
.data
{
329 DefPathData
::Ctor
=> {
332 index
: cur_def_key
.parent
333 .expect("`DefPathData::Ctor` / `VariantData` missing a parent"),
336 cur_def_key
= self.tcx().def_key(parent
);
341 let visible_parent
= match visible_parent_map
.get(&def_id
).cloned() {
342 Some(parent
) => parent
,
343 None
=> return Ok((self, false)),
345 if callers
.contains(&visible_parent
) {
346 return Ok((self, false));
348 callers
.push(visible_parent
);
349 // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid
350 // knowing ahead of time whether the entire path will succeed or not.
351 // To support printers that do not implement `PrettyPrinter`, a `Vec` or
352 // linked list on the stack would need to be built, before any printing.
353 match self.try_print_visible_def_path_recur(visible_parent
, callers
)?
{
354 (cx
, false) => return Ok((cx
, false)),
355 (cx
, true) => self = cx
,
358 let actual_parent
= self.tcx().parent(def_id
);
360 "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}",
361 visible_parent
, actual_parent
,
364 let mut data
= cur_def_key
.disambiguated_data
.data
;
366 "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}",
367 data
, visible_parent
, actual_parent
,
371 // In order to output a path that could actually be imported (valid and visible),
372 // we need to handle re-exports correctly.
374 // For example, take `std::os::unix::process::CommandExt`, this trait is actually
375 // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing).
377 // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is
378 // private so the "true" path to `CommandExt` isn't accessible.
380 // In this case, the `visible_parent_map` will look something like this:
382 // (child) -> (parent)
383 // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process`
384 // `std::sys::unix::ext::process` -> `std::sys::unix::ext`
385 // `std::sys::unix::ext` -> `std::os`
387 // This is correct, as the visible parent of `std::sys::unix::ext` is in fact
390 // When printing the path to `CommandExt` and looking at the `cur_def_key` that
391 // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go
392 // to the parent - resulting in a mangled path like
393 // `std::os::ext::process::CommandExt`.
395 // Instead, we must detect that there was a re-export and instead print `unix`
396 // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To
397 // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with
398 // the visible parent (`std::os`). If these do not match, then we iterate over
399 // the children of the visible parent (as was done when computing
400 // `visible_parent_map`), looking for the specific child we currently have and then
401 // have access to the re-exported name.
402 DefPathData
::TypeNs(ref mut name
) if Some(visible_parent
) != actual_parent
=> {
403 let reexport
= self.tcx().item_children(visible_parent
)
405 .find(|child
| child
.res
.def_id() == def_id
)
406 .map(|child
| child
.ident
.name
);
407 if let Some(reexport
) = reexport
{
411 // Re-exported `extern crate` (#43189).
412 DefPathData
::CrateRoot
=> {
413 data
= DefPathData
::TypeNs(
414 self.tcx().original_crate_name(def_id
.krate
),
419 debug
!("try_print_visible_def_path: data={:?}", data
);
421 Ok((self.path_append(Ok
, &DisambiguatedDefPathData
{
427 fn pretty_path_qualified(
430 trait_ref
: Option
<ty
::TraitRef
<'tcx
>>,
431 ) -> Result
<Self::Path
, Self::Error
> {
432 if trait_ref
.is_none() {
433 // Inherent impls. Try to print `Foo::bar` for an inherent
434 // impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
435 // anything other than a simple path.
437 ty
::Adt(..) | ty
::Foreign(_
) |
438 ty
::Bool
| ty
::Char
| ty
::Str
|
439 ty
::Int(_
) | ty
::Uint(_
) | ty
::Float(_
) => {
440 return self_ty
.print(self);
447 self.generic_delimiters(|mut cx
| {
448 define_scoped_cx
!(cx
);
451 if let Some(trait_ref
) = trait_ref
{
452 p
!(write(" as "), print(trait_ref
.print_only_trait_path()));
458 fn pretty_path_append_impl(
460 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
462 trait_ref
: Option
<ty
::TraitRef
<'tcx
>>,
463 ) -> Result
<Self::Path
, Self::Error
> {
464 self = print_prefix(self)?
;
466 self.generic_delimiters(|mut cx
| {
467 define_scoped_cx
!(cx
);
470 if let Some(trait_ref
) = trait_ref
{
471 p
!(print(trait_ref
.print_only_trait_path()), write(" for "));
479 fn pretty_print_type(
482 ) -> Result
<Self::Type
, Self::Error
> {
483 define_scoped_cx
!(self);
486 ty
::Bool
=> p
!(write("bool")),
487 ty
::Char
=> p
!(write("char")),
488 ty
::Int(t
) => p
!(write("{}", t
.name_str())),
489 ty
::Uint(t
) => p
!(write("{}", t
.name_str())),
490 ty
::Float(t
) => p
!(write("{}", t
.name_str())),
491 ty
::RawPtr(ref tm
) => {
492 p
!(write("*{} ", match tm
.mutbl
{
493 hir
::Mutability
::Mutable
=> "mut",
494 hir
::Mutability
::Immutable
=> "const",
498 ty
::Ref(r
, ty
, mutbl
) => {
500 if self.region_should_not_be_omitted(r
) {
501 p
!(print(r
), write(" "));
503 p
!(print(ty
::TypeAndMut { ty, mutbl }
))
505 ty
::Never
=> p
!(write("!")),
506 ty
::Tuple(ref tys
) => {
508 let mut tys
= tys
.iter();
509 if let Some(&ty
) = tys
.next() {
510 p
!(print(ty
), write(","));
511 if let Some(&ty
) = tys
.next() {
512 p
!(write(" "), print(ty
));
514 p
!(write(", "), print(ty
));
520 ty
::FnDef(def_id
, substs
) => {
521 let sig
= self.tcx().fn_sig(def_id
).subst(self.tcx(), substs
);
522 p
!(print(sig
), write(" {{"), print_value_path(def_id, substs), write("}}"));
524 ty
::FnPtr(ref bare_fn
) => {
527 ty
::Infer(infer_ty
) => {
528 if let ty
::TyVar(ty_vid
) = infer_ty
{
529 if let Some(name
) = self.infer_ty_name(ty_vid
) {
530 p
!(write("{}", name
))
532 p
!(write("{}", infer_ty
))
535 p
!(write("{}", infer_ty
))
538 ty
::Error
=> p
!(write("[type error]")),
539 ty
::Param(ref param_ty
) => p
!(write("{}", param_ty
)),
540 ty
::Bound(debruijn
, bound_ty
) => {
541 match bound_ty
.kind
{
542 ty
::BoundTyKind
::Anon
=> {
543 if debruijn
== ty
::INNERMOST
{
544 p
!(write("^{}", bound_ty
.var
.index()))
546 p
!(write("^{}_{}", debruijn
.index(), bound_ty
.var
.index()))
550 ty
::BoundTyKind
::Param(p
) => p
!(write("{}", p
)),
553 ty
::Adt(def
, substs
) => {
554 p
!(print_def_path(def
.did
, substs
));
556 ty
::Dynamic(data
, r
) => {
557 let print_r
= self.region_should_not_be_omitted(r
);
561 p
!(write("dyn "), print(data
));
563 p
!(write(" + "), print(r
), write(")"));
566 ty
::Foreign(def_id
) => {
567 p
!(print_def_path(def_id
, &[]));
569 ty
::Projection(ref data
) => p
!(print(data
)),
570 ty
::UnnormalizedProjection(ref data
) => {
571 p
!(write("Unnormalized("), print(data
), write(")"))
573 ty
::Placeholder(placeholder
) => {
574 p
!(write("Placeholder({:?})", placeholder
))
576 ty
::Opaque(def_id
, substs
) => {
577 // FIXME(eddyb) print this with `print_def_path`.
578 // We use verbose printing in 'NO_QUERIES' mode, to
579 // avoid needing to call `predicates_of`. This should
580 // only affect certain debug messages (e.g. messages printed
581 // from `rustc::ty` during the computation of `tcx.predicates_of`),
582 // and should have no effect on any compiler output.
583 if self.tcx().sess
.verbose() || NO_QUERIES
.with(|q
| q
.get()) {
584 p
!(write("Opaque({:?}, {:?})", def_id
, substs
));
588 return Ok(with_no_queries(|| {
590 let def_key
= self.tcx().def_key(def_id
);
591 if let Some(name
) = def_key
.disambiguated_data
.data
.get_opt_name() {
592 p
!(write("{}", name
));
593 let mut substs
= substs
.iter();
594 // FIXME(eddyb) print this with `print_def_path`.
595 if let Some(first
) = substs
.next() {
598 for subst
in substs
{
599 p
!(write(", "), print(subst
));
605 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
606 // by looking up the projections associated with the def_id.
607 let bounds
= self.tcx().predicates_of(def_id
).instantiate(self.tcx(), substs
);
609 let mut first
= true;
610 let mut is_sized
= false;
612 for predicate
in bounds
.predicates
{
613 if let Some(trait_ref
) = predicate
.to_opt_poly_trait_ref() {
614 // Don't print +Sized, but rather +?Sized if absent.
615 if Some(trait_ref
.def_id()) == self.tcx().lang_items().sized_trait() {
621 write("{}", if first { " " }
else { "+" }
),
622 print(trait_ref
.print_only_trait_path()));
627 p
!(write("{}?Sized", if first { " " }
else { "+" }
));
634 ty
::Str
=> p
!(write("str")),
635 ty
::Generator(did
, substs
, movability
) => {
636 let upvar_tys
= substs
.as_generator().upvar_tys(did
, self.tcx());
637 let witness
= substs
.as_generator().witness(did
, self.tcx());
639 hir
::Movability
::Movable
=> p
!(write("[generator")),
640 hir
::Movability
::Static
=> p
!(write("[static generator")),
643 // FIXME(eddyb) should use `def_span`.
644 if let Some(hir_id
) = self.tcx().hir().as_local_hir_id(did
) {
645 p
!(write("@{:?}", self.tcx().hir().span(hir_id
)));
647 for (&var_id
, upvar_ty
) in self.tcx().upvars(did
)
650 .flat_map(|v
| v
.keys())
656 self.tcx().hir().name(var_id
)),
661 // Cross-crate closure types should only be
662 // visible in codegen bug reports, I imagine.
663 p
!(write("@{:?}", did
));
665 for (index
, upvar_ty
) in upvar_tys
.enumerate() {
667 write("{}{}:", sep
, index
),
673 p
!(write(" "), print(witness
), write("]"))
675 ty
::GeneratorWitness(types
) => {
676 p
!(in_binder(&types
));
678 ty
::Closure(did
, substs
) => {
679 let upvar_tys
= substs
.as_closure().upvar_tys(did
, self.tcx());
680 p
!(write("[closure"));
682 // FIXME(eddyb) should use `def_span`.
683 if let Some(hir_id
) = self.tcx().hir().as_local_hir_id(did
) {
684 if self.tcx().sess
.opts
.debugging_opts
.span_free_formats
{
685 p
!(write("@"), print_def_path(did
, substs
));
687 p
!(write("@{:?}", self.tcx().hir().span(hir_id
)));
690 for (&var_id
, upvar_ty
) in self.tcx().upvars(did
)
693 .flat_map(|v
| v
.keys())
699 self.tcx().hir().name(var_id
)),
704 // Cross-crate closure types should only be
705 // visible in codegen bug reports, I imagine.
706 p
!(write("@{:?}", did
));
708 for (index
, upvar_ty
) in upvar_tys
.enumerate() {
710 write("{}{}:", sep
, index
),
716 if self.tcx().sess
.verbose() {
718 " closure_kind_ty={:?} closure_sig_ty={:?}",
719 substs
.as_closure().kind_ty(did
, self.tcx()),
720 substs
.as_closure().sig_ty(did
, self.tcx())
726 ty
::Array(ty
, sz
) => {
727 p
!(write("["), print(ty
), write("; "));
728 if self.tcx().sess
.verbose() {
729 p
!(write("{:?}", sz
));
730 } else if let ty
::ConstKind
::Unevaluated(..) = sz
.val
{
731 // do not try to evalute unevaluated constants. If we are const evaluating an
732 // array length anon const, rustc will (with debug assertions) print the
733 // constant's path. Which will end up here again.
735 } else if let Some(n
) = sz
.try_eval_usize(self.tcx(), ty
::ParamEnv
::empty()) {
743 p
!(write("["), print(ty
), write("]"))
750 fn infer_ty_name(&self, _
: ty
::TyVid
) -> Option
<String
> {
754 fn pretty_print_dyn_existential(
756 predicates
: &'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>,
757 ) -> Result
<Self::DynExistential
, Self::Error
> {
758 define_scoped_cx
!(self);
760 // Generate the main trait ref, including associated types.
761 let mut first
= true;
763 if let Some(principal
) = predicates
.principal() {
764 p
!(print_def_path(principal
.def_id
, &[]));
766 let mut resugared
= false;
768 // Special-case `Fn(...) -> ...` and resugar it.
769 let fn_trait_kind
= self.tcx().lang_items().fn_trait_kind(principal
.def_id
);
770 if !self.tcx().sess
.verbose() && fn_trait_kind
.is_some() {
771 if let ty
::Tuple(ref args
) = principal
.substs
.type_at(0).kind
{
772 let mut projections
= predicates
.projection_bounds();
773 if let (Some(proj
), None
) = (projections
.next(), projections
.next()) {
774 let tys
: Vec
<_
> = args
.iter().map(|k
| k
.expect_ty()).collect();
775 p
!(pretty_fn_sig(&tys
, false, proj
.ty
));
781 // HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`,
782 // in order to place the projections inside the `<...>`.
784 // Use a type that can't appear in defaults of type parameters.
785 let dummy_self
= self.tcx().mk_ty_infer(ty
::FreshTy(0));
786 let principal
= principal
.with_self_ty(self.tcx(), dummy_self
);
788 let args
= self.generic_args_to_print(
789 self.tcx().generics_of(principal
.def_id
),
793 // Don't print `'_` if there's no unerased regions.
794 let print_regions
= args
.iter().any(|arg
| {
796 GenericArgKind
::Lifetime(r
) => *r
!= ty
::ReErased
,
800 let mut args
= args
.iter().cloned().filter(|arg
| {
802 GenericArgKind
::Lifetime(_
) => print_regions
,
806 let mut projections
= predicates
.projection_bounds();
808 let arg0
= args
.next();
809 let projection0
= projections
.next();
810 if arg0
.is_some() || projection0
.is_some() {
811 let args
= arg0
.into_iter().chain(args
);
812 let projections
= projection0
.into_iter().chain(projections
);
814 p
!(generic_delimiters(|mut cx
| {
815 cx
= cx
.comma_sep(args
)?
;
816 if arg0
.is_some() && projection0
.is_some() {
819 cx
.comma_sep(projections
)
827 // FIXME(eddyb) avoid printing twice (needed to ensure
828 // that the auto traits are sorted *and* printed via cx).
829 let mut auto_traits
: Vec
<_
> = predicates
.auto_traits().map(|did
| {
830 (self.tcx().def_path_str(did
), did
)
833 // The auto traits come ordered by `DefPathHash`. While
834 // `DefPathHash` is *stable* in the sense that it depends on
835 // neither the host nor the phase of the moon, it depends
836 // "pseudorandomly" on the compiler version and the target.
838 // To avoid that causing instabilities in compiletest
839 // output, sort the auto-traits alphabetically.
842 for (_
, def_id
) in auto_traits
{
848 p
!(print_def_path(def_id
, &[]));
859 ) -> Result
<Self, Self::Error
> {
860 define_scoped_cx
!(self);
863 let mut inputs
= inputs
.iter();
864 if let Some(&ty
) = inputs
.next() {
867 p
!(write(", "), print(ty
));
874 if !output
.is_unit() {
875 p
!(write(" -> "), print(output
));
881 fn pretty_print_const(
883 ct
: &'tcx ty
::Const
<'tcx
>,
884 ) -> Result
<Self::Const
, Self::Error
> {
885 define_scoped_cx
!(self);
887 if self.tcx().sess
.verbose() {
888 p
!(write("Const({:?}: {:?})", ct
.val
, ct
.ty
));
892 match (ct
.val
, &ct
.ty
.kind
) {
893 (_
, ty
::FnDef(did
, substs
)) => p
!(print_value_path(*did
, substs
)),
894 (ty
::ConstKind
::Unevaluated(did
, substs
), _
) => {
895 match self.tcx().def_kind(did
) {
896 | Some(DefKind
::Static
)
897 | Some(DefKind
::Const
)
898 | Some(DefKind
::AssocConst
) => p
!(print_value_path(did
, substs
)),
899 _
=> if did
.is_local() {
900 let span
= self.tcx().def_span(did
);
901 if let Ok(snip
) = self.tcx().sess
.source_map().span_to_snippet(span
) {
902 p
!(write("{}", snip
))
904 p
!(write("_: "), print(ct
.ty
))
907 p
!(write("_: "), print(ct
.ty
))
911 (ty
::ConstKind
::Infer(..), _
) => p
!(write("_: "), print(ct
.ty
)),
912 (ty
::ConstKind
::Param(ParamConst { name, .. }
), _
) => p
!(write("{}", name
)),
913 (ty
::ConstKind
::Value(value
), _
) => return self.pretty_print_const_value(value
, ct
.ty
),
917 p
!(write("{:?} : ", ct
.val
), print(ct
.ty
))
923 fn pretty_print_const_value(
925 ct
: ConstValue
<'tcx
>,
927 ) -> Result
<Self::Const
, Self::Error
> {
928 define_scoped_cx
!(self);
930 if self.tcx().sess
.verbose() {
931 p
!(write("ConstValue({:?}: {:?})", ct
, ty
));
935 let u8 = self.tcx().types
.u8;
937 match (ct
, &ty
.kind
) {
938 (ConstValue
::Scalar(Scalar
::Raw { data, .. }
), ty
::Bool
) =>
939 p
!(write("{}", if data
== 0 { "false" }
else { "true" }
)),
940 (ConstValue
::Scalar(Scalar
::Raw { data, .. }
), ty
::Float(ast
::FloatTy
::F32
)) =>
941 p
!(write("{}f32", Single
::from_bits(data
))),
942 (ConstValue
::Scalar(Scalar
::Raw { data, .. }
), ty
::Float(ast
::FloatTy
::F64
)) =>
943 p
!(write("{}f64", Double
::from_bits(data
))),
944 (ConstValue
::Scalar(Scalar
::Raw { data, .. }
), ty
::Uint(ui
)) => {
945 let bit_size
= Integer
::from_attr(&self.tcx(), UnsignedInt(*ui
)).size();
946 let max
= truncate(u128
::max_value(), bit_size
);
948 let ui_str
= ui
.name_str();
950 p
!(write("std::{}::MAX", ui_str
))
952 p
!(write("{}{}", data
, ui_str
))
955 (ConstValue
::Scalar(Scalar
::Raw { data, .. }
), ty
::Int(i
)) => {
956 let bit_size
= Integer
::from_attr(&self.tcx(), SignedInt(*i
))
957 .size().bits() as u128
;
958 let min
= 1u128 << (bit_size
- 1);
961 let ty
= self.tcx().lift(&ty
).unwrap();
962 let size
= self.tcx().layout_of(ty
::ParamEnv
::empty().and(ty
))
965 let i_str
= i
.name_str();
967 d
if d
== min
=> p
!(write("std::{}::MIN", i_str
)),
968 d
if d
== max
=> p
!(write("std::{}::MAX", i_str
)),
969 _
=> p
!(write("{}{}", sign_extend(data
, size
) as i128
, i_str
))
972 (ConstValue
::Scalar(Scalar
::Raw { data, .. }
), ty
::Char
) =>
973 p
!(write("{:?}", ::std
::char::from_u32(data
as u32).unwrap())),
974 (ConstValue
::Scalar(_
), ty
::RawPtr(_
)) => p
!(write("{{pointer}}")),
975 (ConstValue
::Scalar(Scalar
::Ptr(ptr
)), ty
::FnPtr(_
)) => {
977 let alloc_map
= self.tcx().alloc_map
.lock();
978 alloc_map
.unwrap_fn(ptr
.alloc_id
)
980 p
!(print_value_path(instance
.def_id(), instance
.substs
));
983 let printed
= if let ty
::Ref(_
, ref_ty
, _
) = ty
.kind
{
984 let byte_str
= match (ct
, &ref_ty
.kind
) {
985 (ConstValue
::Scalar(Scalar
::Ptr(ptr
)), ty
::Array(t
, n
)) if *t
== u8 => {
986 let n
= n
.eval_usize(self.tcx(), ty
::ParamEnv
::empty());
989 .unwrap_memory(ptr
.alloc_id
)
990 .get_bytes(&self.tcx(), ptr
, Size
::from_bytes(n
)).unwrap())
992 (ConstValue
::Slice { data, start, end }
, ty
::Slice(t
)) if *t
== u8 => {
993 // The `inspect` here is okay since we checked the bounds, and there are
994 // no relocations (we have an active slice reference here). We don't use
995 // this result to affect interpreter execution.
996 Some(data
.inspect_with_undef_and_ptr_outside_interpreter(start
..end
))
1001 if let Some(byte_str
) = byte_str
{
1003 for &c
in byte_str
{
1004 for e
in std
::ascii
::escape_default(c
) {
1005 self.write_char(e
as char)?
;
1010 } else if let (ConstValue
::Slice { data, start, end }
, ty
::Str
) =
1013 // The `inspect` here is okay since we checked the bounds, and there are no
1014 // relocations (we have an active `str` reference here). We don't use this
1015 // result to affect interpreter execution.
1016 let slice
= data
.inspect_with_undef_and_ptr_outside_interpreter(start
..end
);
1017 let s
= ::std
::str::from_utf8(slice
)
1018 .expect("non utf8 str from miri");
1019 p
!(write("{:?}", s
));
1029 p
!(write("{:?} : ", ct
), print(ty
))
1037 // HACK(eddyb) boxed to avoid moving around a large struct by-value.
1038 pub struct FmtPrinter
<'a
, 'tcx
, F
>(Box
<FmtPrinterData
<'a
, 'tcx
, F
>>);
1040 pub struct FmtPrinterData
<'a
, 'tcx
, F
> {
1047 used_region_names
: FxHashSet
<Symbol
>,
1048 region_index
: usize,
1049 binder_depth
: usize,
1051 pub region_highlight_mode
: RegionHighlightMode
,
1053 pub name_resolver
: Option
<Box
<&'a
dyn Fn(ty
::sty
::TyVid
) -> Option
<String
>>>,
1056 impl<F
> Deref
for FmtPrinter
<'a
, 'tcx
, F
> {
1057 type Target
= FmtPrinterData
<'a
, 'tcx
, F
>;
1058 fn deref(&self) -> &Self::Target
{
1063 impl<F
> DerefMut
for FmtPrinter
<'_
, '_
, F
> {
1064 fn deref_mut(&mut self) -> &mut Self::Target
{
1069 impl<F
> FmtPrinter
<'a
, 'tcx
, F
> {
1070 pub fn new(tcx
: TyCtxt
<'tcx
>, fmt
: F
, ns
: Namespace
) -> Self {
1071 FmtPrinter(Box
::new(FmtPrinterData
{
1075 in_value
: ns
== Namespace
::ValueNS
,
1076 used_region_names
: Default
::default(),
1079 region_highlight_mode
: RegionHighlightMode
::default(),
1080 name_resolver
: None
,
1086 // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
1087 // (but also some things just print a `DefId` generally so maybe we need this?)
1088 fn guess_def_namespace(self, def_id
: DefId
) -> Namespace
{
1089 match self.def_key(def_id
).disambiguated_data
.data
{
1090 DefPathData
::TypeNs(..)
1091 | DefPathData
::CrateRoot
1092 | DefPathData
::ImplTrait
=> Namespace
::TypeNS
,
1094 DefPathData
::ValueNs(..)
1095 | DefPathData
::AnonConst
1096 | DefPathData
::ClosureExpr
1097 | DefPathData
::Ctor
=> Namespace
::ValueNS
,
1099 DefPathData
::MacroNs(..) => Namespace
::MacroNS
,
1101 _
=> Namespace
::TypeNS
,
1105 /// Returns a string identifying this `DefId`. This string is
1106 /// suitable for user output.
1107 pub fn def_path_str(self, def_id
: DefId
) -> String
{
1108 self.def_path_str_with_substs(def_id
, &[])
1111 pub fn def_path_str_with_substs(self, def_id
: DefId
, substs
: &'t
[GenericArg
<'t
>]) -> String
{
1112 let ns
= self.guess_def_namespace(def_id
);
1113 debug
!("def_path_str: def_id={:?}, ns={:?}", def_id
, ns
);
1114 let mut s
= String
::new();
1115 let _
= FmtPrinter
::new(self, &mut s
, ns
).print_def_path(def_id
, substs
);
1120 impl<F
: fmt
::Write
> fmt
::Write
for FmtPrinter
<'_
, '_
, F
> {
1121 fn write_str(&mut self, s
: &str) -> fmt
::Result
{
1122 self.fmt
.write_str(s
)
1126 impl<F
: fmt
::Write
> Printer
<'tcx
> for FmtPrinter
<'_
, 'tcx
, F
> {
1127 type Error
= fmt
::Error
;
1132 type DynExistential
= Self;
1135 fn tcx(&'a
self) -> TyCtxt
<'tcx
> {
1142 substs
: &'tcx
[GenericArg
<'tcx
>],
1143 ) -> Result
<Self::Path
, Self::Error
> {
1144 define_scoped_cx
!(self);
1146 if substs
.is_empty() {
1147 match self.try_print_visible_def_path(def_id
)?
{
1148 (cx
, true) => return Ok(cx
),
1149 (cx
, false) => self = cx
,
1153 let key
= self.tcx
.def_key(def_id
);
1154 if let DefPathData
::Impl
= key
.disambiguated_data
.data
{
1155 // Always use types for non-local impls, where types are always
1156 // available, and filename/line-number is mostly uninteresting.
1158 !def_id
.is_local() || {
1159 // Otherwise, use filename/line-number if forced.
1160 let force_no_types
= FORCE_IMPL_FILENAME_LINE
.with(|f
| f
.get());
1165 // If no type info is available, fall back to
1166 // pretty printing some span information. This should
1167 // only occur very early in the compiler pipeline.
1168 let parent_def_id
= DefId { index: key.parent.unwrap(), ..def_id }
;
1169 let span
= self.tcx
.def_span(def_id
);
1171 self = self.print_def_path(parent_def_id
, &[])?
;
1173 // HACK(eddyb) copy of `path_append` to avoid
1174 // constructing a `DisambiguatedDefPathData`.
1175 if !self.empty_path
{
1176 write
!(self, "::")?
;
1178 write
!(self, "<impl at {:?}>", span
)?
;
1179 self.empty_path
= false;
1185 self.default_print_def_path(def_id
, substs
)
1190 region
: ty
::Region
<'_
>,
1191 ) -> Result
<Self::Region
, Self::Error
> {
1192 self.pretty_print_region(region
)
1198 ) -> Result
<Self::Type
, Self::Error
> {
1199 self.pretty_print_type(ty
)
1202 fn print_dyn_existential(
1204 predicates
: &'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>,
1205 ) -> Result
<Self::DynExistential
, Self::Error
> {
1206 self.pretty_print_dyn_existential(predicates
)
1211 ct
: &'tcx ty
::Const
<'tcx
>,
1212 ) -> Result
<Self::Const
, Self::Error
> {
1213 self.pretty_print_const(ct
)
1219 ) -> Result
<Self::Path
, Self::Error
> {
1220 self.empty_path
= true;
1221 if cnum
== LOCAL_CRATE
{
1222 if self.tcx
.sess
.rust_2018() {
1223 // We add the `crate::` keyword on Rust 2018, only when desired.
1224 if SHOULD_PREFIX_WITH_CRATE
.with(|flag
| flag
.get()) {
1225 write
!(self, "{}", kw
::Crate
)?
;
1226 self.empty_path
= false;
1230 write
!(self, "{}", self.tcx
.crate_name(cnum
))?
;
1231 self.empty_path
= false;
1239 trait_ref
: Option
<ty
::TraitRef
<'tcx
>>,
1240 ) -> Result
<Self::Path
, Self::Error
> {
1241 self = self.pretty_path_qualified(self_ty
, trait_ref
)?
;
1242 self.empty_path
= false;
1246 fn path_append_impl(
1248 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
1249 _disambiguated_data
: &DisambiguatedDefPathData
,
1251 trait_ref
: Option
<ty
::TraitRef
<'tcx
>>,
1252 ) -> Result
<Self::Path
, Self::Error
> {
1253 self = self.pretty_path_append_impl(|mut cx
| {
1254 cx
= print_prefix(cx
)?
;
1260 }, self_ty
, trait_ref
)?
;
1261 self.empty_path
= false;
1267 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
1268 disambiguated_data
: &DisambiguatedDefPathData
,
1269 ) -> Result
<Self::Path
, Self::Error
> {
1270 self = print_prefix(self)?
;
1272 // Skip `::{{constructor}}` on tuple/unit structs.
1273 match disambiguated_data
.data
{
1274 DefPathData
::Ctor
=> return Ok(self),
1278 // FIXME(eddyb) `name` should never be empty, but it
1279 // currently is for `extern { ... }` "foreign modules".
1280 let name
= disambiguated_data
.data
.as_symbol().as_str();
1281 if !name
.is_empty() {
1282 if !self.empty_path
{
1283 write
!(self, "::")?
;
1285 if ast
::Ident
::from_str(&name
).is_raw_guess() {
1286 write
!(self, "r#")?
;
1288 write
!(self, "{}", name
)?
;
1290 // FIXME(eddyb) this will print e.g. `{{closure}}#3`, but it
1291 // might be nicer to use something else, e.g. `{closure#3}`.
1292 let dis
= disambiguated_data
.disambiguator
;
1294 disambiguated_data
.data
.get_opt_name().is_none() ||
1295 dis
!= 0 && self.tcx
.sess
.verbose();
1297 write
!(self, "#{}", dis
)?
;
1300 self.empty_path
= false;
1306 fn path_generic_args(
1308 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
1309 args
: &[GenericArg
<'tcx
>],
1310 ) -> Result
<Self::Path
, Self::Error
> {
1311 self = print_prefix(self)?
;
1313 // Don't print `'_` if there's no unerased regions.
1314 let print_regions
= args
.iter().any(|arg
| {
1315 match arg
.unpack() {
1316 GenericArgKind
::Lifetime(r
) => *r
!= ty
::ReErased
,
1320 let args
= args
.iter().cloned().filter(|arg
| {
1321 match arg
.unpack() {
1322 GenericArgKind
::Lifetime(_
) => print_regions
,
1327 if args
.clone().next().is_some() {
1329 write
!(self, "::")?
;
1331 self.generic_delimiters(|cx
| cx
.comma_sep(args
))
1338 impl<F
: fmt
::Write
> PrettyPrinter
<'tcx
> for FmtPrinter
<'_
, 'tcx
, F
> {
1339 fn infer_ty_name(&self, id
: ty
::TyVid
) -> Option
<String
> {
1340 self.0.name_resolver
.as_ref().and_then(|func
| func(id
))
1343 fn print_value_path(
1346 substs
: &'tcx
[GenericArg
<'tcx
>],
1347 ) -> Result
<Self::Path
, Self::Error
> {
1348 let was_in_value
= std
::mem
::replace(&mut self.in_value
, true);
1349 self = self.print_def_path(def_id
, substs
)?
;
1350 self.in_value
= was_in_value
;
1355 fn in_binder
<T
>(self, value
: &ty
::Binder
<T
>) -> Result
<Self, Self::Error
>
1357 T
: Print
<'tcx
, Self, Output
= Self, Error
= Self::Error
> + TypeFoldable
<'tcx
>,
1359 self.pretty_in_binder(value
)
1362 fn generic_delimiters(
1364 f
: impl FnOnce(Self) -> Result
<Self, Self::Error
>,
1365 ) -> Result
<Self, Self::Error
> {
1368 let was_in_value
= std
::mem
::replace(&mut self.in_value
, false);
1369 let mut inner
= f(self)?
;
1370 inner
.in_value
= was_in_value
;
1372 write
!(inner
, ">")?
;
1376 fn region_should_not_be_omitted(
1378 region
: ty
::Region
<'_
>,
1380 let highlight
= self.region_highlight_mode
;
1381 if highlight
.region_highlighted(region
).is_some() {
1385 if self.tcx
.sess
.verbose() {
1389 let identify_regions
= self.tcx
.sess
.opts
.debugging_opts
.identify_regions
;
1392 ty
::ReEarlyBound(ref data
) => {
1393 data
.name
!= kw
::Invalid
&&
1394 data
.name
!= kw
::UnderscoreLifetime
1397 ty
::ReLateBound(_
, br
) |
1398 ty
::ReFree(ty
::FreeRegion { bound_region: br, .. }
) |
1399 ty
::RePlaceholder(ty
::Placeholder { name: br, .. }
) => {
1400 if let ty
::BrNamed(_
, name
) = br
{
1401 if name
!= kw
::Invalid
&&
1402 name
!= kw
::UnderscoreLifetime
{
1407 if let Some((region
, _
)) = highlight
.highlight_bound_region
{
1417 ty
::ReVar(_
) if identify_regions
=> true,
1421 ty
::ReErased
=> false,
1425 ty
::ReClosureBound(_
) => true,
1430 // HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
1431 impl<F
: fmt
::Write
> FmtPrinter
<'_
, '_
, F
> {
1432 pub fn pretty_print_region(
1434 region
: ty
::Region
<'_
>,
1435 ) -> Result
<Self, fmt
::Error
> {
1436 define_scoped_cx
!(self);
1438 // Watch out for region highlights.
1439 let highlight
= self.region_highlight_mode
;
1440 if let Some(n
) = highlight
.region_highlighted(region
) {
1441 p
!(write("'{}", n
));
1445 if self.tcx
.sess
.verbose() {
1446 p
!(write("{:?}", region
));
1450 let identify_regions
= self.tcx
.sess
.opts
.debugging_opts
.identify_regions
;
1452 // These printouts are concise. They do not contain all the information
1453 // the user might want to diagnose an error, but there is basically no way
1454 // to fit that into a short string. Hence the recommendation to use
1455 // `explain_region()` or `note_and_explain_region()`.
1457 ty
::ReEarlyBound(ref data
) => {
1458 if data
.name
!= kw
::Invalid
{
1459 p
!(write("{}", data
.name
));
1463 ty
::ReLateBound(_
, br
) |
1464 ty
::ReFree(ty
::FreeRegion { bound_region: br, .. }
) |
1465 ty
::RePlaceholder(ty
::Placeholder { name: br, .. }
) => {
1466 if let ty
::BrNamed(_
, name
) = br
{
1467 if name
!= kw
::Invalid
&&
1468 name
!= kw
::UnderscoreLifetime
{
1469 p
!(write("{}", name
));
1474 if let Some((region
, counter
)) = highlight
.highlight_bound_region
{
1476 p
!(write("'{}", counter
));
1481 ty
::ReScope(scope
) if identify_regions
=> {
1483 region
::ScopeData
::Node
=>
1484 p
!(write("'{}s", scope
.item_local_id().as_usize())),
1485 region
::ScopeData
::CallSite
=>
1486 p
!(write("'{}cs", scope
.item_local_id().as_usize())),
1487 region
::ScopeData
::Arguments
=>
1488 p
!(write("'{}as", scope
.item_local_id().as_usize())),
1489 region
::ScopeData
::Destruction
=>
1490 p
!(write("'{}ds", scope
.item_local_id().as_usize())),
1491 region
::ScopeData
::Remainder(first_statement_index
) => p
!(write(
1493 scope
.item_local_id().as_usize(),
1494 first_statement_index
.index()
1499 ty
::ReVar(region_vid
) if identify_regions
=> {
1500 p
!(write("{:?}", region_vid
));
1507 p
!(write("'static"));
1511 p
!(write("'<empty>"));
1515 // The user should never encounter these in unsubstituted form.
1516 ty
::ReClosureBound(vid
) => {
1517 p
!(write("{:?}", vid
));
1528 // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`,
1529 // `region_index` and `used_region_names`.
1530 impl<F
: fmt
::Write
> FmtPrinter
<'_
, 'tcx
, F
> {
1531 pub fn name_all_regions
<T
>(
1533 value
: &ty
::Binder
<T
>,
1534 ) -> Result
<(Self, (T
, BTreeMap
<ty
::BoundRegion
, ty
::Region
<'tcx
>>)), fmt
::Error
>
1536 T
: Print
<'tcx
, Self, Output
= Self, Error
= fmt
::Error
> + TypeFoldable
<'tcx
>,
1538 fn name_by_region_index(index
: usize) -> Symbol
{
1540 0 => Symbol
::intern("'r"),
1541 1 => Symbol
::intern("'s"),
1542 i
=> Symbol
::intern(&format
!("'t{}", i
-2)),
1546 // Replace any anonymous late-bound regions with named
1547 // variants, using new unique identifiers, so that we can
1548 // clearly differentiate between named and unnamed regions in
1549 // the output. We'll probably want to tweak this over time to
1550 // decide just how much information to give.
1551 if self.binder_depth
== 0 {
1552 self.prepare_late_bound_region_info(value
);
1555 let mut empty
= true;
1556 let mut start_or_continue
= |cx
: &mut Self, start
: &str, cont
: &str| {
1557 write
!(cx
, "{}", if empty
{
1565 define_scoped_cx
!(self);
1567 let mut region_index
= self.region_index
;
1568 let new_value
= self.tcx
.replace_late_bound_regions(value
, |br
| {
1569 let _
= start_or_continue(&mut self, "for<", ", ");
1571 ty
::BrNamed(_
, name
) => {
1572 let _
= write
!(self, "{}", name
);
1578 let name
= name_by_region_index(region_index
);
1580 if !self.used_region_names
.contains(&name
) {
1584 let _
= write
!(self, "{}", name
);
1585 ty
::BrNamed(DefId
::local(CRATE_DEF_INDEX
), name
)
1588 self.tcx
.mk_region(ty
::ReLateBound(ty
::INNERMOST
, br
))
1590 start_or_continue(&mut self, "", "> ")?
;
1592 self.binder_depth
+= 1;
1593 self.region_index
= region_index
;
1594 Ok((self, new_value
))
1597 pub fn pretty_in_binder
<T
>(self, value
: &ty
::Binder
<T
>) -> Result
<Self, fmt
::Error
>
1599 T
: Print
<'tcx
, Self, Output
= Self, Error
= fmt
::Error
> + TypeFoldable
<'tcx
>,
1601 let old_region_index
= self.region_index
;
1602 let (new
, new_value
) = self.name_all_regions(value
)?
;
1603 let mut inner
= new_value
.0.print(new
)?
;
1604 inner
.region_index
= old_region_index
;
1605 inner
.binder_depth
-= 1;
1609 fn prepare_late_bound_region_info
<T
>(&mut self, value
: &ty
::Binder
<T
>)
1610 where T
: TypeFoldable
<'tcx
>
1613 struct LateBoundRegionNameCollector
<'a
>(&'a
mut FxHashSet
<Symbol
>);
1614 impl<'tcx
> ty
::fold
::TypeVisitor
<'tcx
> for LateBoundRegionNameCollector
<'_
> {
1615 fn visit_region(&mut self, r
: ty
::Region
<'tcx
>) -> bool
{
1617 ty
::ReLateBound(_
, ty
::BrNamed(_
, name
)) => {
1618 self.0.insert
(name
);
1622 r
.super_visit_with(self)
1626 self.used_region_names
.clear();
1627 let mut collector
= LateBoundRegionNameCollector(&mut self.used_region_names
);
1628 value
.visit_with(&mut collector
);
1629 self.region_index
= 0;
1633 impl<'tcx
, T
, P
: PrettyPrinter
<'tcx
>> Print
<'tcx
, P
> for ty
::Binder
<T
>
1635 T
: Print
<'tcx
, P
, Output
= P
, Error
= P
::Error
> + TypeFoldable
<'tcx
>,
1638 type Error
= P
::Error
;
1639 fn print(&self, cx
: P
) -> Result
<Self::Output
, Self::Error
> {
1644 impl<'tcx
, T
, U
, P
: PrettyPrinter
<'tcx
>> Print
<'tcx
, P
> for ty
::OutlivesPredicate
<T
, U
>
1646 T
: Print
<'tcx
, P
, Output
= P
, Error
= P
::Error
>,
1647 U
: Print
<'tcx
, P
, Output
= P
, Error
= P
::Error
>,
1650 type Error
= P
::Error
;
1651 fn print(&self, mut cx
: P
) -> Result
<Self::Output
, Self::Error
> {
1652 define_scoped_cx
!(cx
);
1653 p
!(print(self.0), write(" : "), print(self.1));
1658 macro_rules
! forward_display_to_print
{
1660 $
(impl fmt
::Display
for $ty
{
1661 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1662 ty
::tls
::with(|tcx
| {
1664 .expect("could not lift for printing")
1665 .print(FmtPrinter
::new(tcx
, f
, Namespace
::TypeNS
))?
;
1673 macro_rules
! define_print_and_forward_display
{
1674 (($
self:ident
, $cx
:ident
): $
($ty
:ty $print
:block
)+) => {
1675 $
(impl<'tcx
, P
: PrettyPrinter
<'tcx
>> Print
<'tcx
, P
> for $ty
{
1677 type Error
= fmt
::Error
;
1678 fn print(&$
self, $cx
: P
) -> Result
<Self::Output
, Self::Error
> {
1679 #[allow(unused_mut)]
1681 define_scoped_cx
!($cx
);
1683 #[allow(unreachable_code)]
1688 forward_display_to_print
!($
($ty
),+);
1692 // HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting.
1693 impl fmt
::Display
for ty
::RegionKind
{
1694 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1695 ty
::tls
::with(|tcx
| {
1696 self.print(FmtPrinter
::new(tcx
, f
, Namespace
::TypeNS
))?
;
1702 /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
1703 /// the trait path. That is, it will print `Trait<U>` instead of
1704 /// `<T as Trait<U>>`.
1705 #[derive(Copy, Clone, TypeFoldable, Lift)]
1706 pub struct TraitRefPrintOnlyTraitPath
<'tcx
>(ty
::TraitRef
<'tcx
>);
1708 impl fmt
::Debug
for TraitRefPrintOnlyTraitPath
<'tcx
> {
1709 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1710 fmt
::Display
::fmt(self, f
)
1714 impl ty
::TraitRef
<'tcx
> {
1715 pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath
<'tcx
> {
1716 TraitRefPrintOnlyTraitPath(self)
1720 impl ty
::Binder
<ty
::TraitRef
<'tcx
>> {
1721 pub fn print_only_trait_path(self) -> ty
::Binder
<TraitRefPrintOnlyTraitPath
<'tcx
>> {
1722 self.map_bound(|tr
| tr
.print_only_trait_path())
1726 forward_display_to_print
! {
1728 &'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>,
1729 &'tcx ty
::Const
<'tcx
>,
1731 // HACK(eddyb) these are exhaustive instead of generic,
1732 // because `for<'tcx>` isn't possible yet.
1733 ty
::Binder
<&'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>>,
1734 ty
::Binder
<ty
::TraitRef
<'tcx
>>,
1735 ty
::Binder
<TraitRefPrintOnlyTraitPath
<'tcx
>>,
1736 ty
::Binder
<ty
::FnSig
<'tcx
>>,
1737 ty
::Binder
<ty
::TraitPredicate
<'tcx
>>,
1738 ty
::Binder
<ty
::SubtypePredicate
<'tcx
>>,
1739 ty
::Binder
<ty
::ProjectionPredicate
<'tcx
>>,
1740 ty
::Binder
<ty
::OutlivesPredicate
<Ty
<'tcx
>, ty
::Region
<'tcx
>>>,
1741 ty
::Binder
<ty
::OutlivesPredicate
<ty
::Region
<'tcx
>, ty
::Region
<'tcx
>>>,
1743 ty
::OutlivesPredicate
<Ty
<'tcx
>, ty
::Region
<'tcx
>>,
1744 ty
::OutlivesPredicate
<ty
::Region
<'tcx
>, ty
::Region
<'tcx
>>
1747 define_print_and_forward_display
! {
1750 &'tcx ty
::List
<Ty
<'tcx
>> {
1752 let mut tys
= self.iter();
1753 if let Some(&ty
) = tys
.next() {
1756 p
!(write(", "), print(ty
));
1762 ty
::TypeAndMut
<'tcx
> {
1763 p
!(write("{}", self.mutbl
.prefix_str()), print(self.ty
))
1766 ty
::ExistentialTraitRef
<'tcx
> {
1767 // Use a type that can't appear in defaults of type parameters.
1768 let dummy_self
= cx
.tcx().mk_ty_infer(ty
::FreshTy(0));
1769 let trait_ref
= self.with_self_ty(cx
.tcx(), dummy_self
);
1770 p
!(print(trait_ref
.print_only_trait_path()))
1773 ty
::ExistentialProjection
<'tcx
> {
1774 let name
= cx
.tcx().associated_item(self.item_def_id
).ident
;
1775 p
!(write("{} = ", name
), print(self.ty
))
1778 ty
::ExistentialPredicate
<'tcx
> {
1780 ty
::ExistentialPredicate
::Trait(x
) => p
!(print(x
)),
1781 ty
::ExistentialPredicate
::Projection(x
) => p
!(print(x
)),
1782 ty
::ExistentialPredicate
::AutoTrait(def_id
) => {
1783 p
!(print_def_path(def_id
, &[]));
1789 p
!(write("{}", self.unsafety
.prefix_str()));
1791 if self.abi
!= Abi
::Rust
{
1792 p
!(write("extern {} ", self.abi
));
1795 p
!(write("fn"), pretty_fn_sig(self.inputs(), self.c_variadic
, self.output()));
1799 if cx
.tcx().sess
.verbose() {
1800 p
!(write("{:?}", self));
1804 ty
::TyVar(_
) => p
!(write("_")),
1805 ty
::IntVar(_
) => p
!(write("{}", "{integer}")),
1806 ty
::FloatVar(_
) => p
!(write("{}", "{float}")),
1807 ty
::FreshTy(v
) => p
!(write("FreshTy({})", v
)),
1808 ty
::FreshIntTy(v
) => p
!(write("FreshIntTy({})", v
)),
1809 ty
::FreshFloatTy(v
) => p
!(write("FreshFloatTy({})", v
))
1813 ty
::TraitRef
<'tcx
> {
1814 p
!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
1817 TraitRefPrintOnlyTraitPath
<'tcx
> {
1818 p
!(print_def_path(self.0.def_id
, self.0.substs
));
1822 p
!(write("{}", self.name
))
1826 p
!(write("{}", self.name
))
1829 ty
::SubtypePredicate
<'tcx
> {
1830 p
!(print(self.a
), write(" <: "), print(self.b
))
1833 ty
::TraitPredicate
<'tcx
> {
1834 p
!(print(self.trait_ref
.self_ty()), write(": "),
1835 print(self.trait_ref
.print_only_trait_path()))
1838 ty
::ProjectionPredicate
<'tcx
> {
1839 p
!(print(self.projection_ty
), write(" == "), print(self.ty
))
1842 ty
::ProjectionTy
<'tcx
> {
1843 p
!(print_def_path(self.item_def_id
, self.substs
));
1848 ty
::ClosureKind
::Fn
=> p
!(write("Fn")),
1849 ty
::ClosureKind
::FnMut
=> p
!(write("FnMut")),
1850 ty
::ClosureKind
::FnOnce
=> p
!(write("FnOnce")),
1854 ty
::Predicate
<'tcx
> {
1856 ty
::Predicate
::Trait(ref data
) => p
!(print(data
)),
1857 ty
::Predicate
::Subtype(ref predicate
) => p
!(print(predicate
)),
1858 ty
::Predicate
::RegionOutlives(ref predicate
) => p
!(print(predicate
)),
1859 ty
::Predicate
::TypeOutlives(ref predicate
) => p
!(print(predicate
)),
1860 ty
::Predicate
::Projection(ref predicate
) => p
!(print(predicate
)),
1861 ty
::Predicate
::WellFormed(ty
) => p
!(print(ty
), write(" well-formed")),
1862 ty
::Predicate
::ObjectSafe(trait_def_id
) => {
1863 p
!(write("the trait `"),
1864 print_def_path(trait_def_id
, &[]),
1865 write("` is object-safe"))
1867 ty
::Predicate
::ClosureKind(closure_def_id
, _closure_substs
, kind
) => {
1868 p
!(write("the closure `"),
1869 print_value_path(closure_def_id
, &[]),
1870 write("` implements the trait `{}`", kind
))
1872 ty
::Predicate
::ConstEvaluatable(def_id
, substs
) => {
1873 p
!(write("the constant `"),
1874 print_value_path(def_id
, substs
),
1875 write("` can be evaluated"))
1881 match self.unpack() {
1882 GenericArgKind
::Lifetime(lt
) => p
!(print(lt
)),
1883 GenericArgKind
::Type(ty
) => p
!(print(ty
)),
1884 GenericArgKind
::Const(ct
) => p
!(print(ct
)),