1 use crate::middle
::cstore
::{ExternCrate, ExternCrateSource}
;
2 use crate::mir
::interpret
::{AllocId, ConstValue, GlobalAlloc, Pointer, Scalar}
;
3 use crate::ty
::subst
::{GenericArg, GenericArgKind, Subst}
;
4 use crate::ty
::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable}
;
5 use rustc_apfloat
::ieee
::{Double, Single}
;
7 use rustc_data_structures
::fx
::FxHashMap
;
9 use rustc_hir
::def
::{self, CtorKind, DefKind, Namespace}
;
10 use rustc_hir
::def_id
::{CrateNum, DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE}
;
11 use rustc_hir
::definitions
::{DefPathData, DefPathDataName, DisambiguatedDefPathData}
;
12 use rustc_hir
::ItemKind
;
13 use rustc_session
::config
::TrimmedDefPaths
;
14 use rustc_span
::symbol
::{kw, Ident, Symbol}
;
15 use rustc_target
::abi
::Size
;
16 use rustc_target
::spec
::abi
::Abi
;
20 use std
::collections
::BTreeMap
;
21 use std
::convert
::TryFrom
;
22 use std
::fmt
::{self, Write as _}
;
23 use std
::ops
::{ControlFlow, Deref, DerefMut}
;
25 // `pretty` is a separate module only for organization.
30 write
!(scoped_cx
!(), $lit
)?
32 (@
write($
($data
:expr
),+)) => {
33 write
!(scoped_cx
!(), $
($data
),+)?
35 (@
print($x
:expr
)) => {
36 scoped_cx
!() = $x
.print(scoped_cx
!())?
38 (@$method
:ident($
($arg
:expr
),*)) => {
39 scoped_cx
!() = scoped_cx
!().$
method($
($arg
),*)?
41 ($
($elem
:tt $
(($
($args
:tt
)*))?
),+) => {{
42 $
(p
!(@ $elem $
(($
($args
)*))?
);)+
45 macro_rules
! define_scoped_cx
{
47 #[allow(unused_macros)]
48 macro_rules
! scoped_cx
{
57 static FORCE_IMPL_FILENAME_LINE
: Cell
<bool
> = Cell
::new(false);
58 static SHOULD_PREFIX_WITH_CRATE
: Cell
<bool
> = Cell
::new(false);
59 static NO_TRIMMED_PATH
: Cell
<bool
> = Cell
::new(false);
60 static NO_QUERIES
: Cell
<bool
> = Cell
::new(false);
63 /// Avoids running any queries during any prints that occur
64 /// during the closure. This may alter the appearance of some
65 /// types (e.g. forcing verbose printing for opaque types).
66 /// This method is used during some queries (e.g. `explicit_item_bounds`
67 /// for opaque types), to ensure that any debug printing that
68 /// occurs during the query computation does not end up recursively
69 /// calling the same query.
70 pub fn with_no_queries
<F
: FnOnce() -> R
, R
>(f
: F
) -> R
{
71 NO_QUERIES
.with(|no_queries
| {
72 let old
= no_queries
.replace(true);
79 /// Force us to name impls with just the filename/line number. We
80 /// normally try to use types. But at some points, notably while printing
81 /// cycle errors, this can result in extra or suboptimal error output,
82 /// so this variable disables that check.
83 pub fn with_forced_impl_filename_line
<F
: FnOnce() -> R
, R
>(f
: F
) -> R
{
84 FORCE_IMPL_FILENAME_LINE
.with(|force
| {
85 let old
= force
.replace(true);
92 /// Adds the `crate::` prefix to paths where appropriate.
93 pub fn with_crate_prefix
<F
: FnOnce() -> R
, R
>(f
: F
) -> R
{
94 SHOULD_PREFIX_WITH_CRATE
.with(|flag
| {
95 let old
= flag
.replace(true);
102 /// Prevent path trimming if it is turned on. Path trimming affects `Display` impl
103 /// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`,
104 /// if no other `Vec` is found.
105 pub fn with_no_trimmed_paths
<F
: FnOnce() -> R
, R
>(f
: F
) -> R
{
106 NO_TRIMMED_PATH
.with(|flag
| {
107 let old
= flag
.replace(true);
114 /// The "region highlights" are used to control region printing during
115 /// specific error messages. When a "region highlight" is enabled, it
116 /// gives an alternate way to print specific regions. For now, we
117 /// always print those regions using a number, so something like "`'0`".
119 /// Regions not selected by the region highlight mode are presently
121 #[derive(Copy, Clone, Default)]
122 pub struct RegionHighlightMode
{
123 /// If enabled, when we see the selected region, use "`'N`"
124 /// instead of the ordinary behavior.
125 highlight_regions
: [Option
<(ty
::RegionKind
, usize)>; 3],
127 /// If enabled, when printing a "free region" that originated from
128 /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
129 /// have names print as normal.
131 /// This is used when you have a signature like `fn foo(x: &u32,
132 /// y: &'a u32)` and we want to give a name to the region of the
134 highlight_bound_region
: Option
<(ty
::BoundRegion
, usize)>,
137 impl RegionHighlightMode
{
138 /// If `region` and `number` are both `Some`, invokes
139 /// `highlighting_region`.
140 pub fn maybe_highlighting_region(
142 region
: Option
<ty
::Region
<'_
>>,
143 number
: Option
<usize>,
145 if let Some(k
) = region
{
146 if let Some(n
) = number
{
147 self.highlighting_region(k
, n
);
152 /// Highlights the region inference variable `vid` as `'N`.
153 pub fn highlighting_region(&mut self, region
: ty
::Region
<'_
>, number
: usize) {
154 let num_slots
= self.highlight_regions
.len();
155 let first_avail_slot
=
156 self.highlight_regions
.iter_mut().find(|s
| s
.is_none()).unwrap_or_else(|| {
157 bug
!("can only highlight {} placeholders at a time", num_slots
,)
159 *first_avail_slot
= Some((*region
, number
));
162 /// Convenience wrapper for `highlighting_region`.
163 pub fn highlighting_region_vid(&mut self, vid
: ty
::RegionVid
, number
: usize) {
164 self.highlighting_region(&ty
::ReVar(vid
), number
)
167 /// Returns `Some(n)` with the number to use for the given region, if any.
168 fn region_highlighted(&self, region
: ty
::Region
<'_
>) -> Option
<usize> {
169 self.highlight_regions
.iter().find_map(|h
| match h
{
170 Some((r
, n
)) if r
== region
=> Some(*n
),
175 /// Highlight the given bound region.
176 /// We can only highlight one bound region at a time. See
177 /// the field `highlight_bound_region` for more detailed notes.
178 pub fn highlighting_bound_region(&mut self, br
: ty
::BoundRegion
, number
: usize) {
179 assert
!(self.highlight_bound_region
.is_none());
180 self.highlight_bound_region
= Some((br
, number
));
184 /// Trait for printers that pretty-print using `fmt::Write` to the printer.
185 pub trait PrettyPrinter
<'tcx
>:
192 DynExistential
= Self,
196 /// Like `print_def_path` but for value paths.
200 substs
: &'tcx
[GenericArg
<'tcx
>],
201 ) -> Result
<Self::Path
, Self::Error
> {
202 self.print_def_path(def_id
, substs
)
205 fn in_binder
<T
>(self, value
: &ty
::Binder
<T
>) -> Result
<Self, Self::Error
>
207 T
: Print
<'tcx
, Self, Output
= Self, Error
= Self::Error
> + TypeFoldable
<'tcx
>,
209 value
.as_ref().skip_binder().print(self)
212 /// Prints comma-separated elements.
213 fn comma_sep
<T
>(mut self, mut elems
: impl Iterator
<Item
= T
>) -> Result
<Self, Self::Error
>
215 T
: Print
<'tcx
, Self, Output
= Self, Error
= Self::Error
>,
217 if let Some(first
) = elems
.next() {
218 self = first
.print(self)?
;
220 self.write_str(", ")?
;
221 self = elem
.print(self)?
;
227 /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument
230 f
: impl FnOnce(Self) -> Result
<Self, Self::Error
>,
231 t
: impl FnOnce(Self) -> Result
<Self, Self::Error
>,
233 ) -> Result
<Self::Const
, Self::Error
> {
234 self.write_str("{")?
;
236 self.write_str(conversion
)?
;
238 self.write_str("}")?
;
242 /// Prints `<...>` around what `f` prints.
243 fn generic_delimiters(
245 f
: impl FnOnce(Self) -> Result
<Self, Self::Error
>,
246 ) -> Result
<Self, Self::Error
>;
248 /// Returns `true` if the region should be printed in
249 /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`.
250 /// This is typically the case for all non-`'_` regions.
251 fn region_should_not_be_omitted(&self, region
: ty
::Region
<'_
>) -> bool
;
253 // Defaults (should not be overridden):
255 /// If possible, this returns a global path resolving to `def_id` that is visible
256 /// from at least one local module, and returns `true`. If the crate defining `def_id` is
257 /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
258 fn try_print_visible_def_path(self, def_id
: DefId
) -> Result
<(Self, bool
), Self::Error
> {
259 let mut callers
= Vec
::new();
260 self.try_print_visible_def_path_recur(def_id
, &mut callers
)
263 /// Try to see if this path can be trimmed to a unique symbol name.
264 fn try_print_trimmed_def_path(
267 ) -> Result
<(Self::Path
, bool
), Self::Error
> {
268 if !self.tcx().sess
.opts
.debugging_opts
.trim_diagnostic_paths
269 || matches
!(self.tcx().sess
.opts
.trimmed_def_paths
, TrimmedDefPaths
::Never
)
270 || NO_TRIMMED_PATH
.with(|flag
| flag
.get())
271 || SHOULD_PREFIX_WITH_CRATE
.with(|flag
| flag
.get())
273 return Ok((self, false));
276 match self.tcx().trimmed_def_paths(LOCAL_CRATE
).get(&def_id
) {
277 None
=> Ok((self, false)),
279 self.write_str(&symbol
.as_str())?
;
285 /// Does the work of `try_print_visible_def_path`, building the
286 /// full definition path recursively before attempting to
287 /// post-process it into the valid and visible version that
288 /// accounts for re-exports.
290 /// This method should only be called by itself or
291 /// `try_print_visible_def_path`.
293 /// `callers` is a chain of visible_parent's leading to `def_id`,
294 /// to support cycle detection during recursion.
295 fn try_print_visible_def_path_recur(
298 callers
: &mut Vec
<DefId
>,
299 ) -> Result
<(Self, bool
), Self::Error
> {
300 define_scoped_cx
!(self);
302 debug
!("try_print_visible_def_path: def_id={:?}", def_id
);
304 // If `def_id` is a direct or injected extern crate, return the
305 // path to the crate followed by the path to the item within the crate.
306 if def_id
.index
== CRATE_DEF_INDEX
{
307 let cnum
= def_id
.krate
;
309 if cnum
== LOCAL_CRATE
{
310 return Ok((self.path_crate(cnum
)?
, true));
313 // In local mode, when we encounter a crate other than
314 // LOCAL_CRATE, execution proceeds in one of two ways:
316 // 1. For a direct dependency, where user added an
317 // `extern crate` manually, we put the `extern
318 // crate` as the parent. So you wind up with
319 // something relative to the current crate.
320 // 2. For an extern inferred from a path or an indirect crate,
321 // where there is no explicit `extern crate`, we just prepend
323 match self.tcx().extern_crate(def_id
) {
324 Some(&ExternCrate { src, dependency_of, span, .. }
) => match (src
, dependency_of
) {
325 (ExternCrateSource
::Extern(def_id
), LOCAL_CRATE
) => {
326 debug
!("try_print_visible_def_path: def_id={:?}", def_id
);
328 if !span
.is_dummy() {
329 self.print_def_path(def_id
, &[])?
331 self.path_crate(cnum
)?
336 (ExternCrateSource
::Path
, LOCAL_CRATE
) => {
337 debug
!("try_print_visible_def_path: def_id={:?}", def_id
);
338 return Ok((self.path_crate(cnum
)?
, true));
343 return Ok((self.path_crate(cnum
)?
, true));
348 if def_id
.is_local() {
349 return Ok((self, false));
352 let visible_parent_map
= self.tcx().visible_parent_map(LOCAL_CRATE
);
354 let mut cur_def_key
= self.tcx().def_key(def_id
);
355 debug
!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key
);
357 // For a constructor, we want the name of its parent rather than <unnamed>.
358 if let DefPathData
::Ctor
= cur_def_key
.disambiguated_data
.data
{
363 .expect("`DefPathData::Ctor` / `VariantData` missing a parent"),
366 cur_def_key
= self.tcx().def_key(parent
);
369 let visible_parent
= match visible_parent_map
.get(&def_id
).cloned() {
370 Some(parent
) => parent
,
371 None
=> return Ok((self, false)),
373 if callers
.contains(&visible_parent
) {
374 return Ok((self, false));
376 callers
.push(visible_parent
);
377 // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid
378 // knowing ahead of time whether the entire path will succeed or not.
379 // To support printers that do not implement `PrettyPrinter`, a `Vec` or
380 // linked list on the stack would need to be built, before any printing.
381 match self.try_print_visible_def_path_recur(visible_parent
, callers
)?
{
382 (cx
, false) => return Ok((cx
, false)),
383 (cx
, true) => self = cx
,
386 let actual_parent
= self.tcx().parent(def_id
);
388 "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}",
389 visible_parent
, actual_parent
,
392 let mut data
= cur_def_key
.disambiguated_data
.data
;
394 "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}",
395 data
, visible_parent
, actual_parent
,
399 // In order to output a path that could actually be imported (valid and visible),
400 // we need to handle re-exports correctly.
402 // For example, take `std::os::unix::process::CommandExt`, this trait is actually
403 // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing).
405 // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is
406 // private so the "true" path to `CommandExt` isn't accessible.
408 // In this case, the `visible_parent_map` will look something like this:
410 // (child) -> (parent)
411 // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process`
412 // `std::sys::unix::ext::process` -> `std::sys::unix::ext`
413 // `std::sys::unix::ext` -> `std::os`
415 // This is correct, as the visible parent of `std::sys::unix::ext` is in fact
418 // When printing the path to `CommandExt` and looking at the `cur_def_key` that
419 // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go
420 // to the parent - resulting in a mangled path like
421 // `std::os::ext::process::CommandExt`.
423 // Instead, we must detect that there was a re-export and instead print `unix`
424 // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To
425 // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with
426 // the visible parent (`std::os`). If these do not match, then we iterate over
427 // the children of the visible parent (as was done when computing
428 // `visible_parent_map`), looking for the specific child we currently have and then
429 // have access to the re-exported name.
430 DefPathData
::TypeNs(ref mut name
) if Some(visible_parent
) != actual_parent
=> {
433 .item_children(visible_parent
)
435 .find(|child
| child
.res
.opt_def_id() == Some(def_id
))
436 .map(|child
| child
.ident
.name
);
437 if let Some(reexport
) = reexport
{
441 // Re-exported `extern crate` (#43189).
442 DefPathData
::CrateRoot
=> {
443 data
= DefPathData
::TypeNs(self.tcx().original_crate_name(def_id
.krate
));
447 debug
!("try_print_visible_def_path: data={:?}", data
);
449 Ok((self.path_append(Ok
, &DisambiguatedDefPathData { data, disambiguator: 0 }
)?
, true))
452 fn pretty_path_qualified(
455 trait_ref
: Option
<ty
::TraitRef
<'tcx
>>,
456 ) -> Result
<Self::Path
, Self::Error
> {
457 if trait_ref
.is_none() {
458 // Inherent impls. Try to print `Foo::bar` for an inherent
459 // impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
460 // anything other than a simple path.
461 match self_ty
.kind() {
470 return self_ty
.print(self);
477 self.generic_delimiters(|mut cx
| {
478 define_scoped_cx
!(cx
);
481 if let Some(trait_ref
) = trait_ref
{
482 p
!(" as ", print(trait_ref
.print_only_trait_path()));
488 fn pretty_path_append_impl(
490 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
492 trait_ref
: Option
<ty
::TraitRef
<'tcx
>>,
493 ) -> Result
<Self::Path
, Self::Error
> {
494 self = print_prefix(self)?
;
496 self.generic_delimiters(|mut cx
| {
497 define_scoped_cx
!(cx
);
500 if let Some(trait_ref
) = trait_ref
{
501 p
!(print(trait_ref
.print_only_trait_path()), " for ");
509 fn pretty_print_type(mut self, ty
: Ty
<'tcx
>) -> Result
<Self::Type
, Self::Error
> {
510 define_scoped_cx
!(self);
513 ty
::Bool
=> p
!("bool"),
514 ty
::Char
=> p
!("char"),
515 ty
::Int(t
) => p
!(write("{}", t
.name_str())),
516 ty
::Uint(t
) => p
!(write("{}", t
.name_str())),
517 ty
::Float(t
) => p
!(write("{}", t
.name_str())),
518 ty
::RawPtr(ref tm
) => {
522 hir
::Mutability
::Mut
=> "mut",
523 hir
::Mutability
::Not
=> "const",
528 ty
::Ref(r
, ty
, mutbl
) => {
530 if self.region_should_not_be_omitted(r
) {
533 p
!(print(ty
::TypeAndMut { ty, mutbl }
))
535 ty
::Never
=> p
!("!"),
536 ty
::Tuple(ref tys
) => {
537 p
!("(", comma_sep(tys
.iter()));
543 ty
::FnDef(def_id
, substs
) => {
544 let sig
= self.tcx().fn_sig(def_id
).subst(self.tcx(), substs
);
545 p
!(print(sig
), " {{", print_value_path(def_id, substs), "}}");
547 ty
::FnPtr(ref bare_fn
) => p
!(print(bare_fn
)),
548 ty
::Infer(infer_ty
) => {
549 if let ty
::TyVar(ty_vid
) = infer_ty
{
550 if let Some(name
) = self.infer_ty_name(ty_vid
) {
551 p
!(write("{}", name
))
553 p
!(write("{}", infer_ty
))
556 p
!(write("{}", infer_ty
))
559 ty
::Error(_
) => p
!("[type error]"),
560 ty
::Param(ref param_ty
) => p
!(write("{}", param_ty
)),
561 ty
::Bound(debruijn
, bound_ty
) => match bound_ty
.kind
{
562 ty
::BoundTyKind
::Anon
=> self.pretty_print_bound_var(debruijn
, bound_ty
.var
)?
,
563 ty
::BoundTyKind
::Param(p
) => p
!(write("{}", p
)),
565 ty
::Adt(def
, substs
) => {
566 p
!(print_def_path(def
.did
, substs
));
568 ty
::Dynamic(data
, r
) => {
569 let print_r
= self.region_should_not_be_omitted(r
);
573 p
!("dyn ", print(data
));
575 p
!(" + ", print(r
), ")");
578 ty
::Foreign(def_id
) => {
579 p
!(print_def_path(def_id
, &[]));
581 ty
::Projection(ref data
) => p
!(print(data
)),
582 ty
::Placeholder(placeholder
) => p
!(write("Placeholder({:?})", placeholder
)),
583 ty
::Opaque(def_id
, substs
) => {
584 // FIXME(eddyb) print this with `print_def_path`.
585 // We use verbose printing in 'NO_QUERIES' mode, to
586 // avoid needing to call `predicates_of`. This should
587 // only affect certain debug messages (e.g. messages printed
588 // from `rustc_middle::ty` during the computation of `tcx.predicates_of`),
589 // and should have no effect on any compiler output.
590 if self.tcx().sess
.verbose() || NO_QUERIES
.with(|q
| q
.get()) {
591 p
!(write("Opaque({:?}, {:?})", def_id
, substs
));
595 return Ok(with_no_queries(|| {
596 let def_key
= self.tcx().def_key(def_id
);
597 if let Some(name
) = def_key
.disambiguated_data
.data
.get_opt_name() {
598 p
!(write("{}", name
));
599 // FIXME(eddyb) print this with `print_def_path`.
600 if !substs
.is_empty() {
602 p
!(generic_delimiters(|cx
| cx
.comma_sep(substs
.iter())));
606 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
607 // by looking up the projections associated with the def_id.
608 let bounds
= self.tcx().explicit_item_bounds(def_id
);
610 let mut first
= true;
611 let mut is_sized
= false;
613 for (predicate
, _
) in bounds
{
614 let predicate
= predicate
.subst(self.tcx(), substs
);
615 // Note: We can't use `to_opt_poly_trait_ref` here as `predicate`
616 // may contain unbound variables. We therefore do this manually.
618 // FIXME(lcnr): Find out why exactly this is the case :)
619 let bound_predicate
= predicate
.bound_atom_with_opt_escaping(self.tcx());
620 if let ty
::PredicateAtom
::Trait(pred
, _
) = bound_predicate
.skip_binder() {
621 let trait_ref
= bound_predicate
.rebind(pred
.trait_ref
);
622 // Don't print +Sized, but rather +?Sized if absent.
623 if Some(trait_ref
.def_id()) == self.tcx().lang_items().sized_trait() {
629 write("{}", if first { " " }
else { "+" }
),
630 print(trait_ref
.print_only_trait_path())
636 p
!(write("{}?Sized", if first { " " }
else { "+" }
));
643 ty
::Str
=> p
!("str"),
644 ty
::Generator(did
, substs
, movability
) => {
647 hir
::Movability
::Movable
=> {}
648 hir
::Movability
::Static
=> p
!("static "),
651 if !self.tcx().sess
.verbose() {
653 // FIXME(eddyb) should use `def_span`.
654 if let Some(did
) = did
.as_local() {
655 let hir_id
= self.tcx().hir().local_def_id_to_hir_id(did
);
656 let span
= self.tcx().hir().span(hir_id
);
657 p
!(write("@{}", self.tcx().sess
.source_map().span_to_string(span
)));
659 p
!(write("@"), print_def_path(did
, substs
));
662 p
!(print_def_path(did
, substs
));
664 if !substs
.as_generator().is_valid() {
667 self = self.comma_sep(substs
.as_generator().upvar_tys())?
;
672 if substs
.as_generator().is_valid() {
673 p
!(" ", print(substs
.as_generator().witness()));
678 ty
::GeneratorWitness(types
) => {
679 p
!(in_binder(&types
));
681 ty
::Closure(did
, substs
) => {
683 if !self.tcx().sess
.verbose() {
684 p
!(write("closure"));
685 // FIXME(eddyb) should use `def_span`.
686 if let Some(did
) = did
.as_local() {
687 let hir_id
= self.tcx().hir().local_def_id_to_hir_id(did
);
688 if self.tcx().sess
.opts
.debugging_opts
.span_free_formats
{
689 p
!("@", print_def_path(did
.to_def_id(), substs
));
691 let span
= self.tcx().hir().span(hir_id
);
692 p
!(write("@{}", self.tcx().sess
.source_map().span_to_string(span
)));
695 p
!(write("@"), print_def_path(did
, substs
));
698 p
!(print_def_path(did
, substs
));
699 if !substs
.as_closure().is_valid() {
700 p
!(" closure_substs=(unavailable)");
702 p
!(" closure_kind_ty=", print(substs
.as_closure().kind_ty()));
704 " closure_sig_as_fn_ptr_ty=",
705 print(substs
.as_closure().sig_as_fn_ptr_ty())
708 self = self.comma_sep(substs
.as_closure().upvar_tys())?
;
714 ty
::Array(ty
, sz
) => {
715 p
!("[", print(ty
), "; ");
716 if self.tcx().sess
.verbose() {
717 p
!(write("{:?}", sz
));
718 } else if let ty
::ConstKind
::Unevaluated(..) = sz
.val
{
719 // Do not try to evaluate unevaluated constants. If we are const evaluating an
720 // array length anon const, rustc will (with debug assertions) print the
721 // constant's path. Which will end up here again.
723 } else if let Some(n
) = sz
.val
.try_to_bits(self.tcx().data_layout
.pointer_size
) {
725 } else if let ty
::ConstKind
::Param(param
) = sz
.val
{
726 p
!(write("{}", param
));
732 ty
::Slice(ty
) => p
!("[", print(ty
), "]"),
738 fn pretty_print_bound_var(
740 debruijn
: ty
::DebruijnIndex
,
742 ) -> Result
<(), Self::Error
> {
743 if debruijn
== ty
::INNERMOST
{
744 write
!(self, "^{}", var
.index())
746 write
!(self, "^{}_{}", debruijn
.index(), var
.index())
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().fn_trait_kind_from_lang_item(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
| match arg
.unpack() {
795 GenericArgKind
::Lifetime(r
) => *r
!= ty
::ReErased
,
798 let mut args
= args
.iter().cloned().filter(|arg
| match arg
.unpack() {
799 GenericArgKind
::Lifetime(_
) => print_regions
,
802 let mut projections
= predicates
.projection_bounds();
804 let arg0
= args
.next();
805 let projection0
= projections
.next();
806 if arg0
.is_some() || projection0
.is_some() {
807 let args
= arg0
.into_iter().chain(args
);
808 let projections
= projection0
.into_iter().chain(projections
);
810 p
!(generic_delimiters(|mut cx
| {
811 cx
= cx
.comma_sep(args
)?
;
812 if arg0
.is_some() && projection0
.is_some() {
815 cx
.comma_sep(projections
)
823 // FIXME(eddyb) avoid printing twice (needed to ensure
824 // that the auto traits are sorted *and* printed via cx).
825 let mut auto_traits
: Vec
<_
> =
826 predicates
.auto_traits().map(|did
| (self.tcx().def_path_str(did
), did
)).collect();
828 // The auto traits come ordered by `DefPathHash`. While
829 // `DefPathHash` is *stable* in the sense that it depends on
830 // neither the host nor the phase of the moon, it depends
831 // "pseudorandomly" on the compiler version and the target.
833 // To avoid that causing instabilities in compiletest
834 // output, sort the auto-traits alphabetically.
837 for (_
, def_id
) in auto_traits
{
843 p
!(print_def_path(def_id
, &[]));
854 ) -> Result
<Self, Self::Error
> {
855 define_scoped_cx
!(self);
857 p
!("(", comma_sep(inputs
.iter().copied()));
859 if !inputs
.is_empty() {
865 if !output
.is_unit() {
866 p
!(" -> ", print(output
));
872 fn pretty_print_const(
874 ct
: &'tcx ty
::Const
<'tcx
>,
876 ) -> Result
<Self::Const
, Self::Error
> {
877 define_scoped_cx
!(self);
879 if self.tcx().sess
.verbose() {
880 p
!(write("Const({:?}: {:?})", ct
.val
, ct
.ty
));
884 macro_rules
! print_underscore
{
887 self = self.typed_value(
892 |this
| this
.print_type(ct
.ty
),
902 ty
::ConstKind
::Unevaluated(def
, substs
, promoted
) => {
903 if let Some(promoted
) = promoted
{
904 p
!(print_value_path(def
.did
, substs
));
905 p
!(write("::{:?}", promoted
));
907 match self.tcx().def_kind(def
.did
) {
908 DefKind
::Static
| DefKind
::Const
| DefKind
::AssocConst
=> {
909 p
!(print_value_path(def
.did
, substs
))
913 let span
= self.tcx().def_span(def
.did
);
914 if let Ok(snip
) = self.tcx().sess
.source_map().span_to_snippet(span
)
916 p
!(write("{}", snip
))
927 ty
::ConstKind
::Infer(..) => print_underscore
!(),
928 ty
::ConstKind
::Param(ParamConst { name, .. }
) => p
!(write("{}", name
)),
929 ty
::ConstKind
::Value(value
) => {
930 return self.pretty_print_const_value(value
, ct
.ty
, print_ty
);
933 ty
::ConstKind
::Bound(debruijn
, bound_var
) => {
934 self.pretty_print_bound_var(debruijn
, bound_var
)?
936 ty
::ConstKind
::Placeholder(placeholder
) => p
!(write("Placeholder({:?})", placeholder
)),
937 ty
::ConstKind
::Error(_
) => p
!("[const error]"),
942 fn pretty_print_const_scalar(
947 ) -> Result
<Self::Const
, Self::Error
> {
948 define_scoped_cx
!(self);
950 match (scalar
, &ty
.kind()) {
951 // Byte strings (&[u8; N])
959 ty
::TyS { kind: ty::Uint(ast::UintTy::U8), .. }
,
961 val
: ty
::ConstKind
::Value(ConstValue
::Scalar(int
)),
969 ) => match self.tcx().get_global_alloc(ptr
.alloc_id
) {
970 Some(GlobalAlloc
::Memory(alloc
)) => {
971 let bytes
= int
.assert_bits(self.tcx().data_layout
.pointer_size
);
972 let size
= Size
::from_bytes(bytes
);
973 if let Ok(byte_str
) = alloc
.get_bytes(&self.tcx(), ptr
, size
) {
974 p
!(pretty_print_byte_str(byte_str
))
976 p
!("<too short allocation>")
979 // FIXME: for statics and functions, we could in principle print more detail.
980 Some(GlobalAlloc
::Static(def_id
)) => p
!(write("<static({:?})>", def_id
)),
981 Some(GlobalAlloc
::Function(_
)) => p
!("<function>"),
982 None
=> p
!("<dangling pointer>"),
985 (Scalar
::Int(int
), ty
::Bool
) if int
== ScalarInt
::FALSE
=> p
!("false"),
986 (Scalar
::Int(int
), ty
::Bool
) if int
== ScalarInt
::TRUE
=> p
!("true"),
988 (Scalar
::Int(int
), ty
::Float(ast
::FloatTy
::F32
)) => {
989 p
!(write("{}f32", Single
::try_from(int
).unwrap()))
991 (Scalar
::Int(int
), ty
::Float(ast
::FloatTy
::F64
)) => {
992 p
!(write("{}f64", Double
::try_from(int
).unwrap()))
995 (Scalar
::Int(int
), ty
::Uint(_
) | ty
::Int(_
)) => {
997 ConstInt
::new(int
, matches
!(ty
.kind(), ty
::Int(_
)), ty
.is_ptr_sized_integral());
998 if print_ty { p!(write("{:#?}
", int)) } else { p!(write("{:?}", int
)) }
1001 (Scalar
::Int(int
), ty
::Char
) if char::try_from(int
).is_ok() => {
1002 p
!(write("{:?}", char::try_from(int
).unwrap()))
1005 (Scalar
::Int(int
), ty
::RawPtr(_
)) => {
1006 let data
= int
.assert_bits(self.tcx().data_layout
.pointer_size
);
1007 self = self.typed_value(
1009 write
!(this
, "0x{:x}", data
)?
;
1012 |this
| this
.print_type(ty
),
1016 (Scalar
::Ptr(ptr
), ty
::FnPtr(_
)) => {
1017 // FIXME: this can ICE when the ptr is dangling or points to a non-function.
1018 // We should probably have a helper method to share code with the "Byte strings"
1019 // printing above (which also has to handle pointers to all sorts of things).
1020 let instance
= self.tcx().global_alloc(ptr
.alloc_id
).unwrap_fn();
1021 self = self.typed_value(
1022 |this
| this
.print_value_path(instance
.def_id(), instance
.substs
),
1023 |this
| this
.print_type(ty
),
1027 // For function type zsts just printing the path is enough
1028 (Scalar
::Int(int
), ty
::FnDef(d
, s
)) if int
== ScalarInt
::ZST
=> {
1029 p
!(print_value_path(*d
, s
))
1031 // Nontrivial types with scalar bit representation
1032 (Scalar
::Int(int
), _
) => {
1033 let print
= |mut this
: Self| {
1034 if int
.size() == Size
::ZERO
{
1035 write
!(this
, "transmute(())")?
;
1037 write
!(this
, "transmute(0x{:x})", int
)?
;
1041 self = if print_ty
{
1042 self.typed_value(print
, |this
| this
.print_type(ty
), ": ")?
1047 // Any pointer values not covered by a branch above
1048 (Scalar
::Ptr(p
), _
) => {
1049 self = self.pretty_print_const_pointer(p
, ty
, print_ty
)?
;
1055 /// This is overridden for MIR printing because we only want to hide alloc ids from users, not
1056 /// from MIR where it is actually useful.
1057 fn pretty_print_const_pointer(
1062 ) -> Result
<Self::Const
, Self::Error
> {
1066 this
.write_str("&_")?
;
1069 |this
| this
.print_type(ty
),
1073 self.write_str("&_")?
;
1078 fn pretty_print_byte_str(mut self, byte_str
: &'tcx
[u8]) -> Result
<Self::Const
, Self::Error
> {
1079 define_scoped_cx
!(self);
1081 for &c
in byte_str
{
1082 for e
in std
::ascii
::escape_default(c
) {
1083 self.write_char(e
as char)?
;
1090 fn pretty_print_const_value(
1092 ct
: ConstValue
<'tcx
>,
1095 ) -> Result
<Self::Const
, Self::Error
> {
1096 define_scoped_cx
!(self);
1098 if self.tcx().sess
.verbose() {
1099 p
!(write("ConstValue({:?}: ", ct
), print(ty
), ")");
1103 let u8_type
= self.tcx().types
.u8;
1105 match (ct
, ty
.kind()) {
1106 // Byte/string slices, printed as (byte) string literals.
1108 ConstValue
::Slice { data, start, end }
,
1109 ty
::Ref(_
, ty
::TyS { kind: ty::Slice(t), .. }
, _
),
1110 ) if *t
== u8_type
=> {
1111 // The `inspect` here is okay since we checked the bounds, and there are
1112 // no relocations (we have an active slice reference here). We don't use
1113 // this result to affect interpreter execution.
1114 let byte_str
= data
.inspect_with_uninit_and_ptr_outside_interpreter(start
..end
);
1115 self.pretty_print_byte_str(byte_str
)
1118 ConstValue
::Slice { data, start, end }
,
1119 ty
::Ref(_
, ty
::TyS { kind: ty::Str, .. }
, _
),
1121 // The `inspect` here is okay since we checked the bounds, and there are no
1122 // relocations (we have an active `str` reference here). We don't use this
1123 // result to affect interpreter execution.
1124 let slice
= data
.inspect_with_uninit_and_ptr_outside_interpreter(start
..end
);
1125 let s
= std
::str::from_utf8(slice
).expect("non utf8 str from miri");
1126 p
!(write("{:?}", s
));
1129 (ConstValue
::ByRef { alloc, offset }
, ty
::Array(t
, n
)) if *t
== u8_type
=> {
1130 let n
= n
.val
.try_to_bits(self.tcx().data_layout
.pointer_size
).unwrap();
1131 // cast is ok because we already checked for pointer size (32 or 64 bit) above
1132 let n
= Size
::from_bytes(n
);
1133 let ptr
= Pointer
::new(AllocId(0), offset
);
1135 let byte_str
= alloc
.get_bytes(&self.tcx(), ptr
, n
).unwrap();
1137 p
!(pretty_print_byte_str(byte_str
));
1141 // Aggregates, printed as array/tuple/struct/variant construction syntax.
1143 // NB: the `has_param_types_or_consts` check ensures that we can use
1144 // the `destructure_const` query with an empty `ty::ParamEnv` without
1145 // introducing ICEs (e.g. via `layout_of`) from missing bounds.
1146 // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
1147 // to be able to destructure the tuple into `(0u8, *mut T)
1149 // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
1150 // correct `ty::ParamEnv` to allow printing *all* constant values.
1151 (_
, ty
::Array(..) | ty
::Tuple(..) | ty
::Adt(..)) if !ty
.has_param_types_or_consts() => {
1152 let contents
= self.tcx().destructure_const(
1153 ty
::ParamEnv
::reveal_all()
1154 .and(self.tcx().mk_const(ty
::Const { val: ty::ConstKind::Value(ct), ty }
)),
1156 let fields
= contents
.fields
.iter().copied();
1160 p
!("[", comma_sep(fields
), "]");
1163 p
!("(", comma_sep(fields
));
1164 if contents
.fields
.len() == 1 {
1169 ty
::Adt(def
, substs
) if def
.variants
.is_empty() => {
1170 p
!(print_value_path(def
.did
, substs
));
1172 ty
::Adt(def
, substs
) => {
1174 contents
.variant
.expect("destructed const of adt without variant id");
1175 let variant_def
= &def
.variants
[variant_id
];
1176 p
!(print_value_path(variant_def
.def_id
, substs
));
1178 match variant_def
.ctor_kind
{
1179 CtorKind
::Const
=> {}
1181 p
!("(", comma_sep(fields
), ")");
1183 CtorKind
::Fictive
=> {
1185 let mut first
= true;
1186 for (field_def
, field
) in variant_def
.fields
.iter().zip(fields
) {
1190 p
!(write("{}: ", field_def
.ident
), print(field
));
1197 _
=> unreachable
!(),
1203 (ConstValue
::Scalar(scalar
), _
) => self.pretty_print_const_scalar(scalar
, ty
, print_ty
),
1205 // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
1206 // their fields instead of just dumping the memory.
1209 p
!(write("{:?}", ct
));
1211 p
!(": ", print(ty
));
1219 // HACK(eddyb) boxed to avoid moving around a large struct by-value.
1220 pub struct FmtPrinter
<'a
, 'tcx
, F
>(Box
<FmtPrinterData
<'a
, 'tcx
, F
>>);
1222 pub struct FmtPrinterData
<'a
, 'tcx
, F
> {
1228 pub print_alloc_ids
: bool
,
1230 used_region_names
: FxHashSet
<Symbol
>,
1231 region_index
: usize,
1232 binder_depth
: usize,
1233 printed_type_count
: usize,
1235 pub region_highlight_mode
: RegionHighlightMode
,
1237 pub name_resolver
: Option
<Box
<&'a
dyn Fn(ty
::sty
::TyVid
) -> Option
<String
>>>,
1240 impl<F
> Deref
for FmtPrinter
<'a
, 'tcx
, F
> {
1241 type Target
= FmtPrinterData
<'a
, 'tcx
, F
>;
1242 fn deref(&self) -> &Self::Target
{
1247 impl<F
> DerefMut
for FmtPrinter
<'_
, '_
, F
> {
1248 fn deref_mut(&mut self) -> &mut Self::Target
{
1253 impl<F
> FmtPrinter
<'a
, 'tcx
, F
> {
1254 pub fn new(tcx
: TyCtxt
<'tcx
>, fmt
: F
, ns
: Namespace
) -> Self {
1255 FmtPrinter(Box
::new(FmtPrinterData
{
1259 in_value
: ns
== Namespace
::ValueNS
,
1260 print_alloc_ids
: false,
1261 used_region_names
: Default
::default(),
1264 printed_type_count
: 0,
1265 region_highlight_mode
: RegionHighlightMode
::default(),
1266 name_resolver
: None
,
1271 // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
1272 // (but also some things just print a `DefId` generally so maybe we need this?)
1273 fn guess_def_namespace(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> Namespace
{
1274 match tcx
.def_key(def_id
).disambiguated_data
.data
{
1275 DefPathData
::TypeNs(..) | DefPathData
::CrateRoot
| DefPathData
::ImplTrait
=> {
1279 DefPathData
::ValueNs(..)
1280 | DefPathData
::AnonConst
1281 | DefPathData
::ClosureExpr
1282 | DefPathData
::Ctor
=> Namespace
::ValueNS
,
1284 DefPathData
::MacroNs(..) => Namespace
::MacroNS
,
1286 _
=> Namespace
::TypeNS
,
1291 /// Returns a string identifying this `DefId`. This string is
1292 /// suitable for user output.
1293 pub fn def_path_str(self, def_id
: DefId
) -> String
{
1294 self.def_path_str_with_substs(def_id
, &[])
1297 pub fn def_path_str_with_substs(self, def_id
: DefId
, substs
: &'t
[GenericArg
<'t
>]) -> String
{
1298 let ns
= guess_def_namespace(self, def_id
);
1299 debug
!("def_path_str: def_id={:?}, ns={:?}", def_id
, ns
);
1300 let mut s
= String
::new();
1301 let _
= FmtPrinter
::new(self, &mut s
, ns
).print_def_path(def_id
, substs
);
1306 impl<F
: fmt
::Write
> fmt
::Write
for FmtPrinter
<'_
, '_
, F
> {
1307 fn write_str(&mut self, s
: &str) -> fmt
::Result
{
1308 self.fmt
.write_str(s
)
1312 impl<F
: fmt
::Write
> Printer
<'tcx
> for FmtPrinter
<'_
, 'tcx
, F
> {
1313 type Error
= fmt
::Error
;
1318 type DynExistential
= Self;
1321 fn tcx(&'a
self) -> TyCtxt
<'tcx
> {
1328 substs
: &'tcx
[GenericArg
<'tcx
>],
1329 ) -> Result
<Self::Path
, Self::Error
> {
1330 define_scoped_cx
!(self);
1332 if substs
.is_empty() {
1333 match self.try_print_trimmed_def_path(def_id
)?
{
1334 (cx
, true) => return Ok(cx
),
1335 (cx
, false) => self = cx
,
1338 match self.try_print_visible_def_path(def_id
)?
{
1339 (cx
, true) => return Ok(cx
),
1340 (cx
, false) => self = cx
,
1344 let key
= self.tcx
.def_key(def_id
);
1345 if let DefPathData
::Impl
= key
.disambiguated_data
.data
{
1346 // Always use types for non-local impls, where types are always
1347 // available, and filename/line-number is mostly uninteresting.
1348 let use_types
= !def_id
.is_local() || {
1349 // Otherwise, use filename/line-number if forced.
1350 let force_no_types
= FORCE_IMPL_FILENAME_LINE
.with(|f
| f
.get());
1355 // If no type info is available, fall back to
1356 // pretty printing some span information. This should
1357 // only occur very early in the compiler pipeline.
1358 let parent_def_id
= DefId { index: key.parent.unwrap(), ..def_id }
;
1359 let span
= self.tcx
.def_span(def_id
);
1361 self = self.print_def_path(parent_def_id
, &[])?
;
1363 // HACK(eddyb) copy of `path_append` to avoid
1364 // constructing a `DisambiguatedDefPathData`.
1365 if !self.empty_path
{
1366 write
!(self, "::")?
;
1368 write
!(self, "<impl at {}>", self.tcx
.sess
.source_map().span_to_string(span
))?
;
1369 self.empty_path
= false;
1375 self.default_print_def_path(def_id
, substs
)
1378 fn print_region(self, region
: ty
::Region
<'_
>) -> Result
<Self::Region
, Self::Error
> {
1379 self.pretty_print_region(region
)
1382 fn print_type(mut self, ty
: Ty
<'tcx
>) -> Result
<Self::Type
, Self::Error
> {
1383 if self.tcx
.sess
.type_length_limit().value_within_limit(self.printed_type_count
) {
1384 self.printed_type_count
+= 1;
1385 self.pretty_print_type(ty
)
1387 write
!(self, "...")?
;
1392 fn print_dyn_existential(
1394 predicates
: &'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>,
1395 ) -> Result
<Self::DynExistential
, Self::Error
> {
1396 self.pretty_print_dyn_existential(predicates
)
1399 fn print_const(self, ct
: &'tcx ty
::Const
<'tcx
>) -> Result
<Self::Const
, Self::Error
> {
1400 self.pretty_print_const(ct
, true)
1403 fn path_crate(mut self, cnum
: CrateNum
) -> Result
<Self::Path
, Self::Error
> {
1404 self.empty_path
= true;
1405 if cnum
== LOCAL_CRATE
{
1406 if self.tcx
.sess
.rust_2018() {
1407 // We add the `crate::` keyword on Rust 2018, only when desired.
1408 if SHOULD_PREFIX_WITH_CRATE
.with(|flag
| flag
.get()) {
1409 write
!(self, "{}", kw
::Crate
)?
;
1410 self.empty_path
= false;
1414 write
!(self, "{}", self.tcx
.crate_name(cnum
))?
;
1415 self.empty_path
= false;
1423 trait_ref
: Option
<ty
::TraitRef
<'tcx
>>,
1424 ) -> Result
<Self::Path
, Self::Error
> {
1425 self = self.pretty_path_qualified(self_ty
, trait_ref
)?
;
1426 self.empty_path
= false;
1430 fn path_append_impl(
1432 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
1433 _disambiguated_data
: &DisambiguatedDefPathData
,
1435 trait_ref
: Option
<ty
::TraitRef
<'tcx
>>,
1436 ) -> Result
<Self::Path
, Self::Error
> {
1437 self = self.pretty_path_append_impl(
1439 cx
= print_prefix(cx
)?
;
1449 self.empty_path
= false;
1455 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
1456 disambiguated_data
: &DisambiguatedDefPathData
,
1457 ) -> Result
<Self::Path
, Self::Error
> {
1458 self = print_prefix(self)?
;
1460 // Skip `::{{constructor}}` on tuple/unit structs.
1461 if let DefPathData
::Ctor
= disambiguated_data
.data
{
1465 // FIXME(eddyb) `name` should never be empty, but it
1466 // currently is for `extern { ... }` "foreign modules".
1467 let name
= disambiguated_data
.data
.name();
1468 if name
!= DefPathDataName
::Named(kw
::Invalid
) {
1469 if !self.empty_path
{
1470 write
!(self, "::")?
;
1473 if let DefPathDataName
::Named(name
) = name
{
1474 if Ident
::with_dummy_span(name
).is_raw_guess() {
1475 write
!(self, "r#")?
;
1479 let verbose
= self.tcx
.sess
.verbose();
1480 disambiguated_data
.fmt_maybe_verbose(&mut self, verbose
)?
;
1482 self.empty_path
= false;
1488 fn path_generic_args(
1490 print_prefix
: impl FnOnce(Self) -> Result
<Self::Path
, Self::Error
>,
1491 args
: &[GenericArg
<'tcx
>],
1492 ) -> Result
<Self::Path
, Self::Error
> {
1493 self = print_prefix(self)?
;
1495 // Don't print `'_` if there's no unerased regions.
1496 let print_regions
= args
.iter().any(|arg
| match arg
.unpack() {
1497 GenericArgKind
::Lifetime(r
) => *r
!= ty
::ReErased
,
1500 let args
= args
.iter().cloned().filter(|arg
| match arg
.unpack() {
1501 GenericArgKind
::Lifetime(_
) => print_regions
,
1505 if args
.clone().next().is_some() {
1507 write
!(self, "::")?
;
1509 self.generic_delimiters(|cx
| cx
.comma_sep(args
))
1516 impl<F
: fmt
::Write
> PrettyPrinter
<'tcx
> for FmtPrinter
<'_
, 'tcx
, F
> {
1517 fn infer_ty_name(&self, id
: ty
::TyVid
) -> Option
<String
> {
1518 self.0.name_resolver
.as_ref().and_then(|func
| func(id
))
1521 fn print_value_path(
1524 substs
: &'tcx
[GenericArg
<'tcx
>],
1525 ) -> Result
<Self::Path
, Self::Error
> {
1526 let was_in_value
= std
::mem
::replace(&mut self.in_value
, true);
1527 self = self.print_def_path(def_id
, substs
)?
;
1528 self.in_value
= was_in_value
;
1533 fn in_binder
<T
>(self, value
: &ty
::Binder
<T
>) -> Result
<Self, Self::Error
>
1535 T
: Print
<'tcx
, Self, Output
= Self, Error
= Self::Error
> + TypeFoldable
<'tcx
>,
1537 self.pretty_in_binder(value
)
1542 f
: impl FnOnce(Self) -> Result
<Self, Self::Error
>,
1543 t
: impl FnOnce(Self) -> Result
<Self, Self::Error
>,
1545 ) -> Result
<Self::Const
, Self::Error
> {
1546 self.write_str("{")?
;
1548 self.write_str(conversion
)?
;
1549 let was_in_value
= std
::mem
::replace(&mut self.in_value
, false);
1551 self.in_value
= was_in_value
;
1552 self.write_str("}")?
;
1556 fn generic_delimiters(
1558 f
: impl FnOnce(Self) -> Result
<Self, Self::Error
>,
1559 ) -> Result
<Self, Self::Error
> {
1562 let was_in_value
= std
::mem
::replace(&mut self.in_value
, false);
1563 let mut inner
= f(self)?
;
1564 inner
.in_value
= was_in_value
;
1566 write
!(inner
, ">")?
;
1570 fn region_should_not_be_omitted(&self, region
: ty
::Region
<'_
>) -> bool
{
1571 let highlight
= self.region_highlight_mode
;
1572 if highlight
.region_highlighted(region
).is_some() {
1576 if self.tcx
.sess
.verbose() {
1580 let identify_regions
= self.tcx
.sess
.opts
.debugging_opts
.identify_regions
;
1583 ty
::ReEarlyBound(ref data
) => {
1584 data
.name
!= kw
::Invalid
&& data
.name
!= kw
::UnderscoreLifetime
1587 ty
::ReLateBound(_
, br
)
1588 | ty
::ReFree(ty
::FreeRegion { bound_region: br, .. }
)
1589 | ty
::RePlaceholder(ty
::Placeholder { name: br, .. }
) => {
1590 if let ty
::BrNamed(_
, name
) = br
{
1591 if name
!= kw
::Invalid
&& name
!= kw
::UnderscoreLifetime
{
1596 if let Some((region
, _
)) = highlight
.highlight_bound_region
{
1605 ty
::ReVar(_
) if identify_regions
=> true,
1607 ty
::ReVar(_
) | ty
::ReErased
=> false,
1609 ty
::ReStatic
| ty
::ReEmpty(_
) => true,
1613 fn pretty_print_const_pointer(
1618 ) -> Result
<Self::Const
, Self::Error
> {
1619 let print
= |mut this
: Self| {
1620 define_scoped_cx
!(this
);
1621 if this
.print_alloc_ids
{
1622 p
!(write("{:?}", p
));
1629 self.typed_value(print
, |this
| this
.print_type(ty
), ": ")
1636 // HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
1637 impl<F
: fmt
::Write
> FmtPrinter
<'_
, '_
, F
> {
1638 pub fn pretty_print_region(mut self, region
: ty
::Region
<'_
>) -> Result
<Self, fmt
::Error
> {
1639 define_scoped_cx
!(self);
1641 // Watch out for region highlights.
1642 let highlight
= self.region_highlight_mode
;
1643 if let Some(n
) = highlight
.region_highlighted(region
) {
1644 p
!(write("'{}", n
));
1648 if self.tcx
.sess
.verbose() {
1649 p
!(write("{:?}", region
));
1653 let identify_regions
= self.tcx
.sess
.opts
.debugging_opts
.identify_regions
;
1655 // These printouts are concise. They do not contain all the information
1656 // the user might want to diagnose an error, but there is basically no way
1657 // to fit that into a short string. Hence the recommendation to use
1658 // `explain_region()` or `note_and_explain_region()`.
1660 ty
::ReEarlyBound(ref data
) => {
1661 if data
.name
!= kw
::Invalid
{
1662 p
!(write("{}", data
.name
));
1666 ty
::ReLateBound(_
, br
)
1667 | ty
::ReFree(ty
::FreeRegion { bound_region: br, .. }
)
1668 | ty
::RePlaceholder(ty
::Placeholder { name: br, .. }
) => {
1669 if let ty
::BrNamed(_
, name
) = br
{
1670 if name
!= kw
::Invalid
&& name
!= kw
::UnderscoreLifetime
{
1671 p
!(write("{}", name
));
1676 if let Some((region
, counter
)) = highlight
.highlight_bound_region
{
1678 p
!(write("'{}", counter
));
1683 ty
::ReVar(region_vid
) if identify_regions
=> {
1684 p
!(write("{:?}", region_vid
));
1693 ty
::ReEmpty(ty
::UniverseIndex
::ROOT
) => {
1697 ty
::ReEmpty(ui
) => {
1698 p
!(write("'<empty:{:?}>", ui
));
1709 // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`,
1710 // `region_index` and `used_region_names`.
1711 impl<F
: fmt
::Write
> FmtPrinter
<'_
, 'tcx
, F
> {
1712 pub fn name_all_regions
<T
>(
1714 value
: &ty
::Binder
<T
>,
1715 ) -> Result
<(Self, (T
, BTreeMap
<ty
::BoundRegion
, ty
::Region
<'tcx
>>)), fmt
::Error
>
1717 T
: Print
<'tcx
, Self, Output
= Self, Error
= fmt
::Error
> + TypeFoldable
<'tcx
>,
1719 fn name_by_region_index(index
: usize) -> Symbol
{
1721 0 => Symbol
::intern("'r"),
1722 1 => Symbol
::intern("'s"),
1723 i
=> Symbol
::intern(&format
!("'t{}", i
- 2)),
1727 // Replace any anonymous late-bound regions with named
1728 // variants, using new unique identifiers, so that we can
1729 // clearly differentiate between named and unnamed regions in
1730 // the output. We'll probably want to tweak this over time to
1731 // decide just how much information to give.
1732 if self.binder_depth
== 0 {
1733 self.prepare_late_bound_region_info(value
);
1736 let mut empty
= true;
1737 let mut start_or_continue
= |cx
: &mut Self, start
: &str, cont
: &str| {
1750 define_scoped_cx
!(self);
1752 let mut region_index
= self.region_index
;
1753 let new_value
= self.tcx
.replace_late_bound_regions(value
, |br
| {
1754 let _
= start_or_continue(&mut self, "for<", ", ");
1756 ty
::BrNamed(_
, name
) => {
1757 let _
= write
!(self, "{}", name
);
1760 ty
::BrAnon(_
) | ty
::BrEnv
=> {
1762 let name
= name_by_region_index(region_index
);
1764 if !self.used_region_names
.contains(&name
) {
1768 let _
= write
!(self, "{}", name
);
1769 ty
::BrNamed(DefId
::local(CRATE_DEF_INDEX
), name
)
1772 self.tcx
.mk_region(ty
::ReLateBound(ty
::INNERMOST
, br
))
1774 start_or_continue(&mut self, "", "> ")?
;
1776 self.binder_depth
+= 1;
1777 self.region_index
= region_index
;
1778 Ok((self, new_value
))
1781 pub fn pretty_in_binder
<T
>(self, value
: &ty
::Binder
<T
>) -> Result
<Self, fmt
::Error
>
1783 T
: Print
<'tcx
, Self, Output
= Self, Error
= fmt
::Error
> + TypeFoldable
<'tcx
>,
1785 let old_region_index
= self.region_index
;
1786 let (new
, new_value
) = self.name_all_regions(value
)?
;
1787 let mut inner
= new_value
.0.print(new
)?
;
1788 inner
.region_index
= old_region_index
;
1789 inner
.binder_depth
-= 1;
1793 fn prepare_late_bound_region_info
<T
>(&mut self, value
: &ty
::Binder
<T
>)
1795 T
: TypeFoldable
<'tcx
>,
1797 struct LateBoundRegionNameCollector
<'a
>(&'a
mut FxHashSet
<Symbol
>);
1798 impl<'tcx
> ty
::fold
::TypeVisitor
<'tcx
> for LateBoundRegionNameCollector
<'_
> {
1799 fn visit_region(&mut self, r
: ty
::Region
<'tcx
>) -> ControlFlow
<()> {
1800 if let ty
::ReLateBound(_
, ty
::BrNamed(_
, name
)) = *r
{
1801 self.0.insert
(name
);
1803 r
.super_visit_with(self)
1807 self.used_region_names
.clear();
1808 let mut collector
= LateBoundRegionNameCollector(&mut self.used_region_names
);
1809 value
.visit_with(&mut collector
);
1810 self.region_index
= 0;
1814 impl<'tcx
, T
, P
: PrettyPrinter
<'tcx
>> Print
<'tcx
, P
> for ty
::Binder
<T
>
1816 T
: Print
<'tcx
, P
, Output
= P
, Error
= P
::Error
> + TypeFoldable
<'tcx
>,
1819 type Error
= P
::Error
;
1820 fn print(&self, cx
: P
) -> Result
<Self::Output
, Self::Error
> {
1825 impl<'tcx
, T
, U
, P
: PrettyPrinter
<'tcx
>> Print
<'tcx
, P
> for ty
::OutlivesPredicate
<T
, U
>
1827 T
: Print
<'tcx
, P
, Output
= P
, Error
= P
::Error
>,
1828 U
: Print
<'tcx
, P
, Output
= P
, Error
= P
::Error
>,
1831 type Error
= P
::Error
;
1832 fn print(&self, mut cx
: P
) -> Result
<Self::Output
, Self::Error
> {
1833 define_scoped_cx
!(cx
);
1834 p
!(print(self.0), ": ", print(self.1));
1839 macro_rules
! forward_display_to_print
{
1841 $
(impl fmt
::Display
for $ty
{
1842 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1843 ty
::tls
::with(|tcx
| {
1845 .expect("could not lift for printing")
1846 .print(FmtPrinter
::new(tcx
, f
, Namespace
::TypeNS
))?
;
1854 macro_rules
! define_print_and_forward_display
{
1855 (($
self:ident
, $cx
:ident
): $
($ty
:ty $print
:block
)+) => {
1856 $
(impl<'tcx
, P
: PrettyPrinter
<'tcx
>> Print
<'tcx
, P
> for $ty
{
1858 type Error
= fmt
::Error
;
1859 fn print(&$
self, $cx
: P
) -> Result
<Self::Output
, Self::Error
> {
1860 #[allow(unused_mut)]
1862 define_scoped_cx
!($cx
);
1864 #[allow(unreachable_code)]
1869 forward_display_to_print
!($
($ty
),+);
1873 // HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting.
1874 impl fmt
::Display
for ty
::RegionKind
{
1875 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1876 ty
::tls
::with(|tcx
| {
1877 self.print(FmtPrinter
::new(tcx
, f
, Namespace
::TypeNS
))?
;
1883 /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
1884 /// the trait path. That is, it will print `Trait<U>` instead of
1885 /// `<T as Trait<U>>`.
1886 #[derive(Copy, Clone, TypeFoldable, Lift)]
1887 pub struct TraitRefPrintOnlyTraitPath
<'tcx
>(ty
::TraitRef
<'tcx
>);
1889 impl fmt
::Debug
for TraitRefPrintOnlyTraitPath
<'tcx
> {
1890 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1891 fmt
::Display
::fmt(self, f
)
1895 impl ty
::TraitRef
<'tcx
> {
1896 pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath
<'tcx
> {
1897 TraitRefPrintOnlyTraitPath(self)
1901 impl ty
::Binder
<ty
::TraitRef
<'tcx
>> {
1902 pub fn print_only_trait_path(self) -> ty
::Binder
<TraitRefPrintOnlyTraitPath
<'tcx
>> {
1903 self.map_bound(|tr
| tr
.print_only_trait_path())
1907 forward_display_to_print
! {
1909 &'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>,
1910 &'tcx ty
::Const
<'tcx
>,
1912 // HACK(eddyb) these are exhaustive instead of generic,
1913 // because `for<'tcx>` isn't possible yet.
1914 ty
::Binder
<&'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>>>,
1915 ty
::Binder
<ty
::TraitRef
<'tcx
>>,
1916 ty
::Binder
<TraitRefPrintOnlyTraitPath
<'tcx
>>,
1917 ty
::Binder
<ty
::FnSig
<'tcx
>>,
1918 ty
::Binder
<ty
::TraitPredicate
<'tcx
>>,
1919 ty
::Binder
<ty
::SubtypePredicate
<'tcx
>>,
1920 ty
::Binder
<ty
::ProjectionPredicate
<'tcx
>>,
1921 ty
::Binder
<ty
::OutlivesPredicate
<Ty
<'tcx
>, ty
::Region
<'tcx
>>>,
1922 ty
::Binder
<ty
::OutlivesPredicate
<ty
::Region
<'tcx
>, ty
::Region
<'tcx
>>>,
1924 ty
::OutlivesPredicate
<Ty
<'tcx
>, ty
::Region
<'tcx
>>,
1925 ty
::OutlivesPredicate
<ty
::Region
<'tcx
>, ty
::Region
<'tcx
>>
1928 define_print_and_forward_display
! {
1931 &'tcx ty
::List
<Ty
<'tcx
>> {
1932 p
!("{{", comma_sep(self.iter()), "}}")
1935 ty
::TypeAndMut
<'tcx
> {
1936 p
!(write("{}", self.mutbl
.prefix_str()), print(self.ty
))
1939 ty
::ExistentialTraitRef
<'tcx
> {
1940 // Use a type that can't appear in defaults of type parameters.
1941 let dummy_self
= cx
.tcx().mk_ty_infer(ty
::FreshTy(0));
1942 let trait_ref
= self.with_self_ty(cx
.tcx(), dummy_self
);
1943 p
!(print(trait_ref
.print_only_trait_path()))
1946 ty
::ExistentialProjection
<'tcx
> {
1947 let name
= cx
.tcx().associated_item(self.item_def_id
).ident
;
1948 p
!(write("{} = ", name
), print(self.ty
))
1951 ty
::ExistentialPredicate
<'tcx
> {
1953 ty
::ExistentialPredicate
::Trait(x
) => p
!(print(x
)),
1954 ty
::ExistentialPredicate
::Projection(x
) => p
!(print(x
)),
1955 ty
::ExistentialPredicate
::AutoTrait(def_id
) => {
1956 p
!(print_def_path(def_id
, &[]));
1962 p
!(write("{}", self.unsafety
.prefix_str()));
1964 if self.abi
!= Abi
::Rust
{
1965 p
!(write("extern {} ", self.abi
));
1968 p
!("fn", pretty_fn_sig(self.inputs(), self.c_variadic
, self.output()));
1972 if cx
.tcx().sess
.verbose() {
1973 p
!(write("{:?}", self));
1977 ty
::TyVar(_
) => p
!("_"),
1978 ty
::IntVar(_
) => p
!(write("{}", "{integer}")),
1979 ty
::FloatVar(_
) => p
!(write("{}", "{float}")),
1980 ty
::FreshTy(v
) => p
!(write("FreshTy({})", v
)),
1981 ty
::FreshIntTy(v
) => p
!(write("FreshIntTy({})", v
)),
1982 ty
::FreshFloatTy(v
) => p
!(write("FreshFloatTy({})", v
))
1986 ty
::TraitRef
<'tcx
> {
1987 p
!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
1990 TraitRefPrintOnlyTraitPath
<'tcx
> {
1991 p
!(print_def_path(self.0.def_id
, self.0.substs
));
1995 p
!(write("{}", self.name
))
1999 p
!(write("{}", self.name
))
2002 ty
::SubtypePredicate
<'tcx
> {
2003 p
!(print(self.a
), " <: ", print(self.b
))
2006 ty
::TraitPredicate
<'tcx
> {
2007 p
!(print(self.trait_ref
.self_ty()), ": ",
2008 print(self.trait_ref
.print_only_trait_path()))
2011 ty
::ProjectionPredicate
<'tcx
> {
2012 p
!(print(self.projection_ty
), " == ", print(self.ty
))
2015 ty
::ProjectionTy
<'tcx
> {
2016 p
!(print_def_path(self.item_def_id
, self.substs
));
2021 ty
::ClosureKind
::Fn
=> p
!("Fn"),
2022 ty
::ClosureKind
::FnMut
=> p
!("FnMut"),
2023 ty
::ClosureKind
::FnOnce
=> p
!("FnOnce"),
2027 ty
::Predicate
<'tcx
> {
2029 &ty
::PredicateKind
::Atom(atom
) => p
!(print(atom
)),
2030 ty
::PredicateKind
::ForAll(binder
) => p
!(print(binder
)),
2034 ty
::PredicateAtom
<'tcx
> {
2036 ty
::PredicateAtom
::Trait(ref data
, constness
) => {
2037 if let hir
::Constness
::Const
= constness
{
2042 ty
::PredicateAtom
::Subtype(predicate
) => p
!(print(predicate
)),
2043 ty
::PredicateAtom
::RegionOutlives(predicate
) => p
!(print(predicate
)),
2044 ty
::PredicateAtom
::TypeOutlives(predicate
) => p
!(print(predicate
)),
2045 ty
::PredicateAtom
::Projection(predicate
) => p
!(print(predicate
)),
2046 ty
::PredicateAtom
::WellFormed(arg
) => p
!(print(arg
), " well-formed"),
2047 ty
::PredicateAtom
::ObjectSafe(trait_def_id
) => {
2048 p
!("the trait `", print_def_path(trait_def_id
, &[]), "` is object-safe")
2050 ty
::PredicateAtom
::ClosureKind(closure_def_id
, _closure_substs
, kind
) => {
2052 print_value_path(closure_def_id
, &[]),
2053 write("` implements the trait `{}`", kind
))
2055 ty
::PredicateAtom
::ConstEvaluatable(def
, substs
) => {
2056 p
!("the constant `", print_value_path(def
.did
, substs
), "` can be evaluated")
2058 ty
::PredicateAtom
::ConstEquate(c1
, c2
) => {
2059 p
!("the constant `", print(c1
), "` equals `", print(c2
), "`")
2061 ty
::PredicateAtom
::TypeWellFormedFromEnv(ty
) => {
2062 p
!("the type `", print(ty
), "` is found in the environment")
2068 match self.unpack() {
2069 GenericArgKind
::Lifetime(lt
) => p
!(print(lt
)),
2070 GenericArgKind
::Type(ty
) => p
!(print(ty
)),
2071 GenericArgKind
::Const(ct
) => p
!(print(ct
)),
2076 fn for_each_def(tcx
: TyCtxt
<'_
>, mut collect_fn
: impl for<'b
> FnMut(&'b Ident
, Namespace
, DefId
)) {
2077 // Iterate all local crate items no matter where they are defined.
2078 let hir
= tcx
.hir();
2079 for item
in hir
.krate().items
.values() {
2080 if item
.ident
.name
.as_str().is_empty() || matches
!(item
.kind
, ItemKind
::Use(_
, _
)) {
2084 if let Some(local_def_id
) = hir
.definitions().opt_hir_id_to_local_def_id(item
.hir_id
) {
2085 let def_id
= local_def_id
.to_def_id();
2086 let ns
= tcx
.def_kind(def_id
).ns().unwrap_or(Namespace
::TypeNS
);
2087 collect_fn(&item
.ident
, ns
, def_id
);
2091 // Now take care of extern crate items.
2092 let queue
= &mut Vec
::new();
2093 let mut seen_defs
: DefIdSet
= Default
::default();
2095 for &cnum
in tcx
.crates().iter() {
2096 let def_id
= DefId { krate: cnum, index: CRATE_DEF_INDEX }
;
2098 // Ignore crates that are not direct dependencies.
2099 match tcx
.extern_crate(def_id
) {
2101 Some(extern_crate
) => {
2102 if !extern_crate
.is_direct() {
2111 // Iterate external crate defs but be mindful about visibility
2112 while let Some(def
) = queue
.pop() {
2113 for child
in tcx
.item_children(def
).iter() {
2114 if child
.vis
!= ty
::Visibility
::Public
{
2119 def
::Res
::Def(DefKind
::AssocTy
, _
) => {}
2120 def
::Res
::Def(defkind
, def_id
) => {
2121 if let Some(ns
) = defkind
.ns() {
2122 collect_fn(&child
.ident
, ns
, def_id
);
2125 if seen_defs
.insert(def_id
) {
2135 /// The purpose of this function is to collect public symbols names that are unique across all
2136 /// crates in the build. Later, when printing about types we can use those names instead of the
2137 /// full exported path to them.
2139 /// So essentially, if a symbol name can only be imported from one place for a type, and as
2140 /// long as it was not glob-imported anywhere in the current crate, we can trim its printed
2141 /// path and print only the name.
2143 /// This has wide implications on error messages with types, for example, shortening
2144 /// `std::vec::Vec` to just `Vec`, as long as there is no other `Vec` importable anywhere.
2146 /// The implementation uses similar import discovery logic to that of 'use' suggestions.
2147 fn trimmed_def_paths(tcx
: TyCtxt
<'_
>, crate_num
: CrateNum
) -> FxHashMap
<DefId
, Symbol
> {
2148 assert_eq
!(crate_num
, LOCAL_CRATE
);
2150 let mut map
= FxHashMap
::default();
2152 if let TrimmedDefPaths
::GoodPath
= tcx
.sess
.opts
.trimmed_def_paths
{
2153 // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
2154 // wrapper can be used to suppress this query, in exchange for full paths being formatted.
2155 tcx
.sess
.delay_good_path_bug("trimmed_def_paths constructed");
2158 let unique_symbols_rev
: &mut FxHashMap
<(Namespace
, Symbol
), Option
<DefId
>> =
2159 &mut FxHashMap
::default();
2161 for symbol_set
in tcx
.glob_map
.values() {
2162 for symbol
in symbol_set
{
2163 unique_symbols_rev
.insert((Namespace
::TypeNS
, *symbol
), None
);
2164 unique_symbols_rev
.insert((Namespace
::ValueNS
, *symbol
), None
);
2165 unique_symbols_rev
.insert((Namespace
::MacroNS
, *symbol
), None
);
2169 for_each_def(tcx
, |ident
, ns
, def_id
| {
2170 use std
::collections
::hash_map
::Entry
::{Occupied, Vacant}
;
2172 match unique_symbols_rev
.entry((ns
, ident
.name
)) {
2173 Occupied(mut v
) => match v
.get() {
2176 if *existing
!= def_id
{
2182 v
.insert(Some(def_id
));
2187 for ((_
, symbol
), opt_def_id
) in unique_symbols_rev
.drain() {
2188 if let Some(def_id
) = opt_def_id
{
2189 map
.insert(def_id
, symbol
);
2196 pub fn provide(providers
: &mut ty
::query
::Providers
) {
2197 *providers
= ty
::query
::Providers { trimmed_def_paths, ..*providers }
;