]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/print/pretty.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / print / pretty.rs
CommitLineData
136023e0 1use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar};
dfeec247 2use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
5099ac24 3use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable};
dc9dc135 4use rustc_apfloat::ieee::{Double, Single};
1b1a35ee 5use rustc_data_structures::fx::FxHashMap;
5099ac24 6use rustc_data_structures::intern::Interned;
cdc7bbd5 7use rustc_data_structures::sso::SsoHashSet;
ba9703b0 8use rustc_hir as hir;
1b1a35ee 9use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
17df50a5 10use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
1b1a35ee
XL
11use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
12use rustc_hir::ItemKind;
13use rustc_session::config::TrimmedDefPaths;
c295e0f8 14use rustc_session::cstore::{ExternCrate, ExternCrateSource};
f9f354fc 15use rustc_span::symbol::{kw, Ident, Symbol};
29967ef6 16use rustc_target::abi::Size;
532ac7d7 17use rustc_target::spec::abi::Abi;
532ac7d7
XL
18
19use std::cell::Cell;
ba9703b0 20use std::char;
60c5eb7d 21use std::collections::BTreeMap;
29967ef6 22use std::convert::TryFrom;
532ac7d7 23use std::fmt::{self, Write as _};
cdc7bbd5 24use std::iter;
29967ef6 25use std::ops::{ControlFlow, Deref, DerefMut};
532ac7d7
XL
26
27// `pretty` is a separate module only for organization.
28use super::*;
29
30macro_rules! p {
29967ef6
XL
31 (@$lit:literal) => {
32 write!(scoped_cx!(), $lit)?
33 };
532ac7d7
XL
34 (@write($($data:expr),+)) => {
35 write!(scoped_cx!(), $($data),+)?
36 };
37 (@print($x:expr)) => {
38 scoped_cx!() = $x.print(scoped_cx!())?
39 };
40 (@$method:ident($($arg:expr),*)) => {
41 scoped_cx!() = scoped_cx!().$method($($arg),*)?
42 };
29967ef6
XL
43 ($($elem:tt $(($($args:tt)*))?),+) => {{
44 $(p!(@ $elem $(($($args)*))?);)+
532ac7d7
XL
45 }};
46}
47macro_rules! define_scoped_cx {
48 ($cx:ident) => {
49 #[allow(unused_macros)]
50 macro_rules! scoped_cx {
dfeec247
XL
51 () => {
52 $cx
53 };
532ac7d7
XL
54 }
55 };
56}
57
58thread_local! {
17df50a5
XL
59 static FORCE_IMPL_FILENAME_LINE: Cell<bool> = const { Cell::new(false) };
60 static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
61 static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
62 static NO_QUERIES: Cell<bool> = const { Cell::new(false) };
c295e0f8 63 static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
60c5eb7d
XL
64}
65
5e7ed085
FG
66macro_rules! define_helper {
67 ($($(#[$a:meta])* fn $name:ident($helper:ident, $tl:ident);)+) => {
68 $(
69 #[must_use]
70 pub struct $helper(bool);
71
72 impl $helper {
73 pub fn new() -> $helper {
74 $helper($tl.with(|c| c.replace(true)))
75 }
76 }
532ac7d7 77
5e7ed085
FG
78 $(#[$a])*
79 pub macro $name($e:expr) {
80 {
81 let _guard = $helper::new();
82 $e
83 }
84 }
532ac7d7 85
5e7ed085
FG
86 impl Drop for $helper {
87 fn drop(&mut self) {
88 $tl.with(|c| c.set(self.0))
89 }
90 }
91 )+
92 }
1b1a35ee
XL
93}
94
5e7ed085
FG
95define_helper!(
96 /// Avoids running any queries during any prints that occur
97 /// during the closure. This may alter the appearance of some
98 /// types (e.g. forcing verbose printing for opaque types).
99 /// This method is used during some queries (e.g. `explicit_item_bounds`
100 /// for opaque types), to ensure that any debug printing that
101 /// occurs during the query computation does not end up recursively
102 /// calling the same query.
103 fn with_no_queries(NoQueriesGuard, NO_QUERIES);
104 /// Force us to name impls with just the filename/line number. We
105 /// normally try to use types. But at some points, notably while printing
106 /// cycle errors, this can result in extra or suboptimal error output,
107 /// so this variable disables that check.
108 fn with_forced_impl_filename_line(ForcedImplGuard, FORCE_IMPL_FILENAME_LINE);
109 /// Adds the `crate::` prefix to paths where appropriate.
110 fn with_crate_prefix(CratePrefixGuard, SHOULD_PREFIX_WITH_CRATE);
111 /// Prevent path trimming if it is turned on. Path trimming affects `Display` impl
112 /// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`,
113 /// if no other `Vec` is found.
114 fn with_no_trimmed_paths(NoTrimmedGuard, NO_TRIMMED_PATH);
115 /// Prevent selection of visible paths. `Display` impl of DefId will prefer
116 /// visible (public) reexports of types as paths.
117 fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
118);
c295e0f8 119
532ac7d7
XL
120/// The "region highlights" are used to control region printing during
121/// specific error messages. When a "region highlight" is enabled, it
122/// gives an alternate way to print specific regions. For now, we
123/// always print those regions using a number, so something like "`'0`".
124///
125/// Regions not selected by the region highlight mode are presently
126/// unaffected.
5099ac24
FG
127#[derive(Copy, Clone)]
128pub struct RegionHighlightMode<'tcx> {
129 tcx: TyCtxt<'tcx>,
130
532ac7d7
XL
131 /// If enabled, when we see the selected region, use "`'N`"
132 /// instead of the ordinary behavior.
5099ac24 133 highlight_regions: [Option<(ty::Region<'tcx>, usize)>; 3],
532ac7d7
XL
134
135 /// If enabled, when printing a "free region" that originated from
fc512014 136 /// the given `ty::BoundRegionKind`, print it as "`'1`". Free regions that would ordinarily
532ac7d7
XL
137 /// have names print as normal.
138 ///
139 /// This is used when you have a signature like `fn foo(x: &u32,
140 /// y: &'a u32)` and we want to give a name to the region of the
141 /// reference `x`.
fc512014 142 highlight_bound_region: Option<(ty::BoundRegionKind, usize)>,
532ac7d7
XL
143}
144
5099ac24
FG
145impl<'tcx> RegionHighlightMode<'tcx> {
146 pub fn new(tcx: TyCtxt<'tcx>) -> Self {
147 Self {
148 tcx,
149 highlight_regions: Default::default(),
150 highlight_bound_region: Default::default(),
151 }
152 }
153
532ac7d7
XL
154 /// If `region` and `number` are both `Some`, invokes
155 /// `highlighting_region`.
156 pub fn maybe_highlighting_region(
157 &mut self,
5099ac24 158 region: Option<ty::Region<'tcx>>,
532ac7d7
XL
159 number: Option<usize>,
160 ) {
161 if let Some(k) = region {
162 if let Some(n) = number {
163 self.highlighting_region(k, n);
164 }
165 }
166 }
167
168 /// Highlights the region inference variable `vid` as `'N`.
5099ac24 169 pub fn highlighting_region(&mut self, region: ty::Region<'tcx>, number: usize) {
532ac7d7 170 let num_slots = self.highlight_regions.len();
dfeec247 171 let first_avail_slot =
74b04a01 172 self.highlight_regions.iter_mut().find(|s| s.is_none()).unwrap_or_else(|| {
dfeec247 173 bug!("can only highlight {} placeholders at a time", num_slots,)
532ac7d7 174 });
5099ac24 175 *first_avail_slot = Some((region, number));
532ac7d7
XL
176 }
177
178 /// Convenience wrapper for `highlighting_region`.
dfeec247 179 pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) {
5099ac24 180 self.highlighting_region(self.tcx.mk_region(ty::ReVar(vid)), number)
532ac7d7
XL
181 }
182
183 /// Returns `Some(n)` with the number to use for the given region, if any.
184 fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
f9f354fc 185 self.highlight_regions.iter().find_map(|h| match h {
5099ac24 186 Some((r, n)) if *r == region => Some(*n),
f9f354fc
XL
187 _ => None,
188 })
532ac7d7
XL
189 }
190
191 /// Highlight the given bound region.
192 /// We can only highlight one bound region at a time. See
193 /// the field `highlight_bound_region` for more detailed notes.
fc512014 194 pub fn highlighting_bound_region(&mut self, br: ty::BoundRegionKind, number: usize) {
532ac7d7
XL
195 assert!(self.highlight_bound_region.is_none());
196 self.highlight_bound_region = Some((br, number));
197 }
198}
199
200/// Trait for printers that pretty-print using `fmt::Write` to the printer.
dc9dc135
XL
201pub trait PrettyPrinter<'tcx>:
202 Printer<
203 'tcx,
532ac7d7
XL
204 Error = fmt::Error,
205 Path = Self,
206 Region = Self,
207 Type = Self,
208 DynExistential = Self,
dc9dc135
XL
209 Const = Self,
210 > + fmt::Write
532ac7d7
XL
211{
212 /// Like `print_def_path` but for value paths.
213 fn print_value_path(
214 self,
215 def_id: DefId,
e74abb32 216 substs: &'tcx [GenericArg<'tcx>],
532ac7d7
XL
217 ) -> Result<Self::Path, Self::Error> {
218 self.print_def_path(def_id, substs)
219 }
220
cdc7bbd5 221 fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error>
dc9dc135
XL
222 where
223 T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
532ac7d7 224 {
f035d41b 225 value.as_ref().skip_binder().print(self)
532ac7d7
XL
226 }
227
fc512014
XL
228 fn wrap_binder<T, F: Fn(&T, Self) -> Result<Self, fmt::Error>>(
229 self,
cdc7bbd5 230 value: &ty::Binder<'tcx, T>,
fc512014
XL
231 f: F,
232 ) -> Result<Self, Self::Error>
233 where
234 T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
235 {
236 f(value.as_ref().skip_binder(), self)
237 }
238
e1599b0c 239 /// Prints comma-separated elements.
dc9dc135
XL
240 fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
241 where
242 T: Print<'tcx, Self, Output = Self, Error = Self::Error>,
532ac7d7
XL
243 {
244 if let Some(first) = elems.next() {
245 self = first.print(self)?;
246 for elem in elems {
247 self.write_str(", ")?;
248 self = elem.print(self)?;
249 }
250 }
251 Ok(self)
252 }
253
ba9703b0
XL
254 /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument
255 fn typed_value(
256 mut self,
257 f: impl FnOnce(Self) -> Result<Self, Self::Error>,
258 t: impl FnOnce(Self) -> Result<Self, Self::Error>,
259 conversion: &str,
260 ) -> Result<Self::Const, Self::Error> {
261 self.write_str("{")?;
262 self = f(self)?;
263 self.write_str(conversion)?;
264 self = t(self)?;
265 self.write_str("}")?;
266 Ok(self)
267 }
268
e1599b0c 269 /// Prints `<...>` around what `f` prints.
532ac7d7
XL
270 fn generic_delimiters(
271 self,
272 f: impl FnOnce(Self) -> Result<Self, Self::Error>,
273 ) -> Result<Self, Self::Error>;
274
e1599b0c
XL
275 /// Returns `true` if the region should be printed in
276 /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`.
532ac7d7 277 /// This is typically the case for all non-`'_` regions.
5e7ed085 278 fn should_print_region(&self, region: ty::Region<'_>) -> bool;
532ac7d7 279
74b04a01 280 // Defaults (should not be overridden):
532ac7d7
XL
281
282 /// If possible, this returns a global path resolving to `def_id` that is visible
e1599b0c 283 /// from at least one local module, and returns `true`. If the crate defining `def_id` is
532ac7d7 284 /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
dfeec247 285 fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), Self::Error> {
c295e0f8
XL
286 if NO_VISIBLE_PATH.with(|flag| flag.get()) {
287 return Ok((self, false));
288 }
289
416331ca
XL
290 let mut callers = Vec::new();
291 self.try_print_visible_def_path_recur(def_id, &mut callers)
292 }
293
1b1a35ee
XL
294 /// Try to see if this path can be trimmed to a unique symbol name.
295 fn try_print_trimmed_def_path(
296 mut self,
297 def_id: DefId,
298 ) -> Result<(Self::Path, bool), Self::Error> {
299 if !self.tcx().sess.opts.debugging_opts.trim_diagnostic_paths
300 || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never)
301 || NO_TRIMMED_PATH.with(|flag| flag.get())
302 || SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get())
303 {
304 return Ok((self, false));
305 }
306
17df50a5 307 match self.tcx().trimmed_def_paths(()).get(&def_id) {
1b1a35ee
XL
308 None => Ok((self, false)),
309 Some(symbol) => {
a2a8927a 310 self.write_str(symbol.as_str())?;
1b1a35ee
XL
311 Ok((self, true))
312 }
313 }
314 }
315
416331ca
XL
316 /// Does the work of `try_print_visible_def_path`, building the
317 /// full definition path recursively before attempting to
318 /// post-process it into the valid and visible version that
319 /// accounts for re-exports.
320 ///
74b04a01 321 /// This method should only be called by itself or
416331ca
XL
322 /// `try_print_visible_def_path`.
323 ///
324 /// `callers` is a chain of visible_parent's leading to `def_id`,
325 /// to support cycle detection during recursion.
a2a8927a
XL
326 ///
327 /// This method returns false if we can't print the visible path, so
328 /// `print_def_path` can fall back on the item's real definition path.
416331ca 329 fn try_print_visible_def_path_recur(
532ac7d7
XL
330 mut self,
331 def_id: DefId,
416331ca 332 callers: &mut Vec<DefId>,
532ac7d7
XL
333 ) -> Result<(Self, bool), Self::Error> {
334 define_scoped_cx!(self);
335
336 debug!("try_print_visible_def_path: def_id={:?}", def_id);
337
338 // If `def_id` is a direct or injected extern crate, return the
339 // path to the crate followed by the path to the item within the crate.
340 if def_id.index == CRATE_DEF_INDEX {
341 let cnum = def_id.krate;
342
343 if cnum == LOCAL_CRATE {
344 return Ok((self.path_crate(cnum)?, true));
345 }
346
347 // In local mode, when we encounter a crate other than
348 // LOCAL_CRATE, execution proceeds in one of two ways:
349 //
e1599b0c 350 // 1. For a direct dependency, where user added an
532ac7d7
XL
351 // `extern crate` manually, we put the `extern
352 // crate` as the parent. So you wind up with
353 // something relative to the current crate.
e1599b0c 354 // 2. For an extern inferred from a path or an indirect crate,
532ac7d7
XL
355 // where there is no explicit `extern crate`, we just prepend
356 // the crate name.
dc9dc135 357 match self.tcx().extern_crate(def_id) {
f035d41b
XL
358 Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) {
359 (ExternCrateSource::Extern(def_id), LOCAL_CRATE) => {
3c0e092e
XL
360 // NOTE(eddyb) the only reason `span` might be dummy,
361 // that we're aware of, is that it's the `std`/`core`
362 // `extern crate` injected by default.
363 // FIXME(eddyb) find something better to key this on,
364 // or avoid ending up with `ExternCrateSource::Extern`,
365 // for the injected `std`/`core`.
366 if span.is_dummy() {
367 return Ok((self.path_crate(cnum)?, true));
368 }
369
370 // Disable `try_print_trimmed_def_path` behavior within
371 // the `print_def_path` call, to avoid infinite recursion
372 // in cases where the `extern crate foo` has non-trivial
373 // parents, e.g. it's nested in `impl foo::Trait for Bar`
374 // (see also issues #55779 and #87932).
5e7ed085 375 self = with_no_visible_paths!(self.print_def_path(def_id, &[])?);
3c0e092e
XL
376
377 return Ok((self, true));
f035d41b
XL
378 }
379 (ExternCrateSource::Path, LOCAL_CRATE) => {
f035d41b
XL
380 return Ok((self.path_crate(cnum)?, true));
381 }
382 _ => {}
383 },
532ac7d7
XL
384 None => {
385 return Ok((self.path_crate(cnum)?, true));
386 }
532ac7d7
XL
387 }
388 }
389
390 if def_id.is_local() {
391 return Ok((self, false));
392 }
393
17df50a5 394 let visible_parent_map = self.tcx().visible_parent_map(());
532ac7d7
XL
395
396 let mut cur_def_key = self.tcx().def_key(def_id);
397 debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
398
e1599b0c 399 // For a constructor, we want the name of its parent rather than <unnamed>.
ba9703b0
XL
400 if let DefPathData::Ctor = cur_def_key.disambiguated_data.data {
401 let parent = DefId {
402 krate: def_id.krate,
403 index: cur_def_key
404 .parent
405 .expect("`DefPathData::Ctor` / `VariantData` missing a parent"),
406 };
532ac7d7 407
ba9703b0 408 cur_def_key = self.tcx().def_key(parent);
532ac7d7
XL
409 }
410
5e7ed085
FG
411 let Some(visible_parent) = visible_parent_map.get(&def_id).cloned() else {
412 return Ok((self, false));
532ac7d7 413 };
a2a8927a 414
532ac7d7
XL
415 let actual_parent = self.tcx().parent(def_id);
416 debug!(
417 "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}",
418 visible_parent, actual_parent,
419 );
420
421 let mut data = cur_def_key.disambiguated_data.data;
422 debug!(
423 "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}",
424 data, visible_parent, actual_parent,
425 );
426
427 match data {
428 // In order to output a path that could actually be imported (valid and visible),
429 // we need to handle re-exports correctly.
430 //
431 // For example, take `std::os::unix::process::CommandExt`, this trait is actually
432 // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing).
433 //
5e7ed085 434 // `std::os::unix` reexports the contents of `std::sys::unix::ext`. `std::sys` is
532ac7d7
XL
435 // private so the "true" path to `CommandExt` isn't accessible.
436 //
437 // In this case, the `visible_parent_map` will look something like this:
438 //
439 // (child) -> (parent)
440 // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process`
441 // `std::sys::unix::ext::process` -> `std::sys::unix::ext`
442 // `std::sys::unix::ext` -> `std::os`
443 //
444 // This is correct, as the visible parent of `std::sys::unix::ext` is in fact
445 // `std::os`.
446 //
447 // When printing the path to `CommandExt` and looking at the `cur_def_key` that
448 // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go
449 // to the parent - resulting in a mangled path like
450 // `std::os::ext::process::CommandExt`.
451 //
452 // Instead, we must detect that there was a re-export and instead print `unix`
453 // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To
454 // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with
455 // the visible parent (`std::os`). If these do not match, then we iterate over
456 // the children of the visible parent (as was done when computing
457 // `visible_parent_map`), looking for the specific child we currently have and then
458 // have access to the re-exported name.
532ac7d7 459 DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => {
a2a8927a
XL
460 // Item might be re-exported several times, but filter for the one
461 // that's public and whose identifier isn't `_`.
dfeec247
XL
462 let reexport = self
463 .tcx()
5099ac24 464 .module_children(visible_parent)
532ac7d7 465 .iter()
a2a8927a
XL
466 .filter(|child| child.res.opt_def_id() == Some(def_id))
467 .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore)
e74abb32 468 .map(|child| child.ident.name);
a2a8927a
XL
469
470 if let Some(new_name) = reexport {
471 *name = new_name;
472 } else {
473 // There is no name that is public and isn't `_`, so bail.
474 return Ok((self, false));
532ac7d7
XL
475 }
476 }
477 // Re-exported `extern crate` (#43189).
478 DefPathData::CrateRoot => {
17df50a5 479 data = DefPathData::TypeNs(self.tcx().crate_name(def_id.krate));
532ac7d7
XL
480 }
481 _ => {}
482 }
483 debug!("try_print_visible_def_path: data={:?}", data);
484
a2a8927a
XL
485 if callers.contains(&visible_parent) {
486 return Ok((self, false));
487 }
488 callers.push(visible_parent);
489 // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid
490 // knowing ahead of time whether the entire path will succeed or not.
491 // To support printers that do not implement `PrettyPrinter`, a `Vec` or
492 // linked list on the stack would need to be built, before any printing.
493 match self.try_print_visible_def_path_recur(visible_parent, callers)? {
494 (cx, false) => return Ok((cx, false)),
495 (cx, true) => self = cx,
496 }
497 callers.pop();
498
dfeec247 499 Ok((self.path_append(Ok, &DisambiguatedDefPathData { data, disambiguator: 0 })?, true))
532ac7d7
XL
500 }
501
502 fn pretty_path_qualified(
503 self,
504 self_ty: Ty<'tcx>,
505 trait_ref: Option<ty::TraitRef<'tcx>>,
506 ) -> Result<Self::Path, Self::Error> {
507 if trait_ref.is_none() {
508 // Inherent impls. Try to print `Foo::bar` for an inherent
509 // impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
510 // anything other than a simple path.
1b1a35ee 511 match self_ty.kind() {
dfeec247
XL
512 ty::Adt(..)
513 | ty::Foreign(_)
514 | ty::Bool
515 | ty::Char
516 | ty::Str
517 | ty::Int(_)
518 | ty::Uint(_)
519 | ty::Float(_) => {
532ac7d7
XL
520 return self_ty.print(self);
521 }
522
523 _ => {}
524 }
525 }
526
527 self.generic_delimiters(|mut cx| {
528 define_scoped_cx!(cx);
529
530 p!(print(self_ty));
531 if let Some(trait_ref) = trait_ref {
29967ef6 532 p!(" as ", print(trait_ref.print_only_trait_path()));
532ac7d7
XL
533 }
534 Ok(cx)
535 })
536 }
537
538 fn pretty_path_append_impl(
539 mut self,
540 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
541 self_ty: Ty<'tcx>,
542 trait_ref: Option<ty::TraitRef<'tcx>>,
543 ) -> Result<Self::Path, Self::Error> {
544 self = print_prefix(self)?;
545
546 self.generic_delimiters(|mut cx| {
547 define_scoped_cx!(cx);
548
29967ef6 549 p!("impl ");
532ac7d7 550 if let Some(trait_ref) = trait_ref {
29967ef6 551 p!(print(trait_ref.print_only_trait_path()), " for ");
532ac7d7
XL
552 }
553 p!(print(self_ty));
554
555 Ok(cx)
556 })
557 }
558
dfeec247 559 fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
532ac7d7
XL
560 define_scoped_cx!(self);
561
1b1a35ee 562 match *ty.kind() {
29967ef6
XL
563 ty::Bool => p!("bool"),
564 ty::Char => p!("char"),
60c5eb7d
XL
565 ty::Int(t) => p!(write("{}", t.name_str())),
566 ty::Uint(t) => p!(write("{}", t.name_str())),
567 ty::Float(t) => p!(write("{}", t.name_str())),
532ac7d7 568 ty::RawPtr(ref tm) => {
dfeec247
XL
569 p!(write(
570 "*{} ",
571 match tm.mutbl {
572 hir::Mutability::Mut => "mut",
573 hir::Mutability::Not => "const",
574 }
575 ));
532ac7d7
XL
576 p!(print(tm.ty))
577 }
578 ty::Ref(r, ty, mutbl) => {
29967ef6 579 p!("&");
5e7ed085 580 if self.should_print_region(r) {
29967ef6 581 p!(print(r), " ");
532ac7d7
XL
582 }
583 p!(print(ty::TypeAndMut { ty, mutbl }))
584 }
29967ef6 585 ty::Never => p!("!"),
532ac7d7 586 ty::Tuple(ref tys) => {
29967ef6 587 p!("(", comma_sep(tys.iter()));
ba9703b0 588 if tys.len() == 1 {
29967ef6 589 p!(",");
532ac7d7 590 }
29967ef6 591 p!(")")
532ac7d7
XL
592 }
593 ty::FnDef(def_id, substs) => {
594 let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
29967ef6 595 p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
532ac7d7 596 }
dfeec247 597 ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
dc9dc135 598 ty::Infer(infer_ty) => {
5869c6ff 599 let verbose = self.tcx().sess.verbose();
dc9dc135 600 if let ty::TyVar(ty_vid) = infer_ty {
5099ac24 601 if let Some(name) = self.ty_infer_name(ty_vid) {
dc9dc135
XL
602 p!(write("{}", name))
603 } else {
5869c6ff
XL
604 if verbose {
605 p!(write("{:?}", infer_ty))
606 } else {
607 p!(write("{}", infer_ty))
608 }
dc9dc135
XL
609 }
610 } else {
5869c6ff 611 if verbose { p!(write("{:?}", infer_ty)) } else { p!(write("{}", infer_ty)) }
dc9dc135 612 }
dfeec247 613 }
29967ef6 614 ty::Error(_) => p!("[type error]"),
5e7ed085 615 ty::Param(ref param_ty) => p!(print(param_ty)),
dfeec247 616 ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
ba9703b0 617 ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
dfeec247
XL
618 ty::BoundTyKind::Param(p) => p!(write("{}", p)),
619 },
532ac7d7 620 ty::Adt(def, substs) => {
5e7ed085 621 p!(print_def_path(def.did(), substs));
532ac7d7
XL
622 }
623 ty::Dynamic(data, r) => {
5e7ed085 624 let print_r = self.should_print_region(r);
532ac7d7 625 if print_r {
29967ef6 626 p!("(");
532ac7d7 627 }
29967ef6 628 p!("dyn ", print(data));
532ac7d7 629 if print_r {
29967ef6 630 p!(" + ", print(r), ")");
532ac7d7
XL
631 }
632 }
633 ty::Foreign(def_id) => {
634 p!(print_def_path(def_id, &[]));
635 }
636 ty::Projection(ref data) => p!(print(data)),
dfeec247 637 ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
532ac7d7
XL
638 ty::Opaque(def_id, substs) => {
639 // FIXME(eddyb) print this with `print_def_path`.
60c5eb7d
XL
640 // We use verbose printing in 'NO_QUERIES' mode, to
641 // avoid needing to call `predicates_of`. This should
642 // only affect certain debug messages (e.g. messages printed
ba9703b0 643 // from `rustc_middle::ty` during the computation of `tcx.predicates_of`),
60c5eb7d 644 // and should have no effect on any compiler output.
dfeec247 645 if self.tcx().sess.verbose() || NO_QUERIES.with(|q| q.get()) {
532ac7d7
XL
646 p!(write("Opaque({:?}, {:?})", def_id, substs));
647 return Ok(self);
648 }
649
5e7ed085
FG
650 let parent = self.tcx().parent(def_id).expect("opaque types always have a parent");
651 match self.tcx().def_kind(parent) {
652 DefKind::TyAlias | DefKind::AssocTy => {
653 if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() {
654 if d == def_id {
655 // If the type alias directly starts with the `impl` of the
656 // opaque type we're printing, then skip the `::{opaque#1}`.
657 p!(print_def_path(parent, substs));
658 return Ok(self);
659 }
532ac7d7 660 }
5e7ed085
FG
661 // Complex opaque type, e.g. `type Foo = (i32, impl Debug);`
662 p!(print_def_path(def_id, substs));
60c5eb7d 663 return Ok(self);
532ac7d7 664 }
5e7ed085
FG
665 _ => return self.pretty_print_opaque_impl_type(def_id, substs),
666 }
532ac7d7 667 }
29967ef6 668 ty::Str => p!("str"),
532ac7d7 669 ty::Generator(did, substs, movability) => {
1b1a35ee 670 p!(write("["));
60c5eb7d 671 match movability {
1b1a35ee 672 hir::Movability::Movable => {}
29967ef6 673 hir::Movability::Static => p!("static "),
532ac7d7
XL
674 }
675
1b1a35ee 676 if !self.tcx().sess.verbose() {
29967ef6 677 p!("generator");
1b1a35ee
XL
678 // FIXME(eddyb) should use `def_span`.
679 if let Some(did) = did.as_local() {
5099ac24 680 let span = self.tcx().def_span(did);
17df50a5
XL
681 p!(write(
682 "@{}",
683 // This may end up in stderr diagnostics but it may also be emitted
684 // into MIR. Hence we use the remapped path if available
685 self.tcx().sess.source_map().span_to_embeddable_string(span)
686 ));
1b1a35ee 687 } else {
29967ef6 688 p!(write("@"), print_def_path(did, substs));
532ac7d7
XL
689 }
690 } else {
1b1a35ee 691 p!(print_def_path(did, substs));
29967ef6
XL
692 p!(" upvar_tys=(");
693 if !substs.as_generator().is_valid() {
694 p!("unavailable");
695 } else {
696 self = self.comma_sep(substs.as_generator().upvar_tys())?;
532ac7d7 697 }
29967ef6 698 p!(")");
532ac7d7 699
136023e0
XL
700 if substs.as_generator().is_valid() {
701 p!(" ", print(substs.as_generator().witness()));
702 }
ba9703b0
XL
703 }
704
29967ef6 705 p!("]")
dfeec247 706 }
532ac7d7
XL
707 ty::GeneratorWitness(types) => {
708 p!(in_binder(&types));
709 }
710 ty::Closure(did, substs) => {
1b1a35ee
XL
711 p!(write("["));
712 if !self.tcx().sess.verbose() {
713 p!(write("closure"));
714 // FIXME(eddyb) should use `def_span`.
715 if let Some(did) = did.as_local() {
1b1a35ee 716 if self.tcx().sess.opts.debugging_opts.span_free_formats {
29967ef6 717 p!("@", print_def_path(did.to_def_id(), substs));
1b1a35ee 718 } else {
5099ac24 719 let span = self.tcx().def_span(did);
17df50a5
XL
720 p!(write(
721 "@{}",
722 // This may end up in stderr diagnostics but it may also be emitted
723 // into MIR. Hence we use the remapped path if available
724 self.tcx().sess.source_map().span_to_embeddable_string(span)
725 ));
ba9703b0 726 }
1b1a35ee 727 } else {
29967ef6 728 p!(write("@"), print_def_path(did, substs));
532ac7d7
XL
729 }
730 } else {
1b1a35ee 731 p!(print_def_path(did, substs));
29967ef6
XL
732 if !substs.as_closure().is_valid() {
733 p!(" closure_substs=(unavailable)");
3c0e092e 734 p!(write(" substs={:?}", substs));
29967ef6
XL
735 } else {
736 p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
737 p!(
738 " closure_sig_as_fn_ptr_ty=",
739 print(substs.as_closure().sig_as_fn_ptr_ty())
740 );
741 p!(" upvar_tys=(");
742 self = self.comma_sep(substs.as_closure().upvar_tys())?;
743 p!(")");
532ac7d7
XL
744 }
745 }
29967ef6 746 p!("]");
dfeec247 747 }
532ac7d7 748 ty::Array(ty, sz) => {
29967ef6 749 p!("[", print(ty), "; ");
e74abb32
XL
750 if self.tcx().sess.verbose() {
751 p!(write("{:?}", sz));
5099ac24 752 } else if let ty::ConstKind::Unevaluated(..) = sz.val() {
f9f354fc 753 // Do not try to evaluate unevaluated constants. If we are const evaluating an
416331ca
XL
754 // array length anon const, rustc will (with debug assertions) print the
755 // constant's path. Which will end up here again.
29967ef6 756 p!("_");
5099ac24 757 } else if let Some(n) = sz.val().try_to_bits(self.tcx().data_layout.pointer_size) {
dc9dc135 758 p!(write("{}", n));
5099ac24 759 } else if let ty::ConstKind::Param(param) = sz.val() {
5e7ed085 760 p!(print(param));
dc9dc135 761 } else {
29967ef6 762 p!("_");
532ac7d7 763 }
29967ef6 764 p!("]")
532ac7d7 765 }
29967ef6 766 ty::Slice(ty) => p!("[", print(ty), "]"),
532ac7d7
XL
767 }
768
769 Ok(self)
770 }
771
3c0e092e
XL
772 fn pretty_print_opaque_impl_type(
773 mut self,
774 def_id: DefId,
775 substs: &'tcx ty::List<ty::GenericArg<'tcx>>,
776 ) -> Result<Self::Type, Self::Error> {
777 define_scoped_cx!(self);
778
779 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
780 // by looking up the projections associated with the def_id.
781 let bounds = self.tcx().explicit_item_bounds(def_id);
782
783 let mut traits = BTreeMap::new();
784 let mut fn_traits = BTreeMap::new();
785 let mut is_sized = false;
786
787 for (predicate, _) in bounds {
788 let predicate = predicate.subst(self.tcx(), substs);
789 let bound_predicate = predicate.kind();
790
791 match bound_predicate.skip_binder() {
792 ty::PredicateKind::Trait(pred) => {
793 let trait_ref = bound_predicate.rebind(pred.trait_ref);
794
795 // Don't print + Sized, but rather + ?Sized if absent.
796 if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
797 is_sized = true;
798 continue;
799 }
800
801 self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits);
802 }
803 ty::PredicateKind::Projection(pred) => {
804 let proj_ref = bound_predicate.rebind(pred);
805 let trait_ref = proj_ref.required_poly_trait_ref(self.tcx());
806
807 // Projection type entry -- the def-id for naming, and the ty.
5099ac24 808 let proj_ty = (proj_ref.projection_def_id(), proj_ref.term());
3c0e092e
XL
809
810 self.insert_trait_and_projection(
811 trait_ref,
812 Some(proj_ty),
813 &mut traits,
814 &mut fn_traits,
815 );
816 }
817 _ => {}
818 }
819 }
820
821 let mut first = true;
822 // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait
823 let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !is_sized;
824
825 p!("impl");
826
827 for (fn_once_trait_ref, entry) in fn_traits {
828 // Get the (single) generic ty (the args) of this FnOnce trait ref.
829 let generics = self.generic_args_to_print(
830 self.tcx().generics_of(fn_once_trait_ref.def_id()),
831 fn_once_trait_ref.skip_binder().substs,
832 );
833
834 match (entry.return_ty, generics[0].expect_ty()) {
835 // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
836 // a return type.
837 (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => {
838 let name = if entry.fn_trait_ref.is_some() {
839 "Fn"
840 } else if entry.fn_mut_trait_ref.is_some() {
841 "FnMut"
842 } else {
843 "FnOnce"
844 };
845
846 p!(
847 write("{}", if first { " " } else { " + " }),
848 write("{}{}(", if paren_needed { "(" } else { "" }, name)
849 );
850
5e7ed085 851 for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() {
3c0e092e
XL
852 if idx > 0 {
853 p!(", ");
854 }
855 p!(print(ty));
856 }
857
858 p!(")");
5099ac24
FG
859 if let Term::Ty(ty) = return_ty.skip_binder() {
860 if !ty.is_unit() {
861 p!("-> ", print(return_ty));
862 }
3c0e092e
XL
863 }
864 p!(write("{}", if paren_needed { ")" } else { "" }));
865
866 first = false;
867 }
868 // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the
869 // trait_refs we collected in the OpaqueFnEntry as normal trait refs.
870 _ => {
871 if entry.has_fn_once {
872 traits.entry(fn_once_trait_ref).or_default().extend(
873 // Group the return ty with its def id, if we had one.
874 entry
875 .return_ty
876 .map(|ty| (self.tcx().lang_items().fn_once_output().unwrap(), ty)),
877 );
878 }
879 if let Some(trait_ref) = entry.fn_mut_trait_ref {
880 traits.entry(trait_ref).or_default();
881 }
882 if let Some(trait_ref) = entry.fn_trait_ref {
883 traits.entry(trait_ref).or_default();
884 }
885 }
886 }
887 }
888
889 // Print the rest of the trait types (that aren't Fn* family of traits)
890 for (trait_ref, assoc_items) in traits {
891 p!(
892 write("{}", if first { " " } else { " + " }),
893 print(trait_ref.skip_binder().print_only_trait_name())
894 );
895
896 let generics = self.generic_args_to_print(
897 self.tcx().generics_of(trait_ref.def_id()),
898 trait_ref.skip_binder().substs,
899 );
900
901 if !generics.is_empty() || !assoc_items.is_empty() {
3c0e092e
XL
902 let mut first = true;
903
904 for ty in generics {
5e7ed085
FG
905 if first {
906 p!("<");
907 first = false;
908 } else {
3c0e092e
XL
909 p!(", ");
910 }
911 p!(print(trait_ref.rebind(*ty)));
3c0e092e
XL
912 }
913
5099ac24 914 for (assoc_item_def_id, term) in assoc_items {
5e7ed085
FG
915 // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
916 // unless we can find out what generator return type it comes from.
917 let term = if let Some(ty) = term.skip_binder().ty()
918 && let ty::Projection(ty::ProjectionTy { item_def_id, substs }) = ty.kind()
919 && Some(*item_def_id) == self.tcx().lang_items().generator_return()
920 {
921 if let ty::Generator(_, substs, _) = substs.type_at(0).kind() {
922 let return_ty = substs.as_generator().return_ty();
923 if !return_ty.is_ty_infer() {
924 return_ty.into()
925 } else {
926 continue;
927 }
928 } else {
929 continue;
930 }
931 } else {
932 term.skip_binder()
933 };
934
935 if first {
936 p!("<");
937 first = false;
938 } else {
3c0e092e
XL
939 p!(", ");
940 }
5e7ed085 941
5099ac24
FG
942 p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).name));
943
5e7ed085 944 match term {
5099ac24 945 Term::Ty(ty) => {
5e7ed085 946 p!(print(ty))
3c0e092e 947 }
5099ac24
FG
948 Term::Const(c) => {
949 p!(print(c));
3c0e092e 950 }
5099ac24 951 };
3c0e092e
XL
952 }
953
5e7ed085
FG
954 if !first {
955 p!(">");
956 }
3c0e092e
XL
957 }
958
959 first = false;
960 }
961
962 if !is_sized {
963 p!(write("{}?Sized", if first { " " } else { " + " }));
964 } else if first {
965 p!(" Sized");
966 }
967
968 Ok(self)
969 }
970
971 /// Insert the trait ref and optionally a projection type associated with it into either the
972 /// traits map or fn_traits map, depending on if the trait is in the Fn* family of traits.
973 fn insert_trait_and_projection(
974 &mut self,
975 trait_ref: ty::PolyTraitRef<'tcx>,
5099ac24
FG
976 proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>,
977 traits: &mut BTreeMap<
978 ty::PolyTraitRef<'tcx>,
979 BTreeMap<DefId, ty::Binder<'tcx, Term<'tcx>>>,
980 >,
3c0e092e
XL
981 fn_traits: &mut BTreeMap<ty::PolyTraitRef<'tcx>, OpaqueFnEntry<'tcx>>,
982 ) {
983 let trait_def_id = trait_ref.def_id();
984
985 // If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce
986 // super-trait ref and record it there.
987 if let Some(fn_once_trait) = self.tcx().lang_items().fn_once_trait() {
988 // If we have a FnOnce, then insert it into
989 if trait_def_id == fn_once_trait {
990 let entry = fn_traits.entry(trait_ref).or_default();
991 // Optionally insert the return_ty as well.
992 if let Some((_, ty)) = proj_ty {
993 entry.return_ty = Some(ty);
994 }
995 entry.has_fn_once = true;
996 return;
997 } else if Some(trait_def_id) == self.tcx().lang_items().fn_mut_trait() {
998 let super_trait_ref = crate::traits::util::supertraits(self.tcx(), trait_ref)
999 .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait)
1000 .unwrap();
1001
1002 fn_traits.entry(super_trait_ref).or_default().fn_mut_trait_ref = Some(trait_ref);
1003 return;
1004 } else if Some(trait_def_id) == self.tcx().lang_items().fn_trait() {
1005 let super_trait_ref = crate::traits::util::supertraits(self.tcx(), trait_ref)
1006 .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait)
1007 .unwrap();
1008
1009 fn_traits.entry(super_trait_ref).or_default().fn_trait_ref = Some(trait_ref);
1010 return;
1011 }
1012 }
1013
1014 // Otherwise, just group our traits and projection types.
1015 traits.entry(trait_ref).or_default().extend(proj_ty);
1016 }
1017
ba9703b0
XL
1018 fn pretty_print_bound_var(
1019 &mut self,
1020 debruijn: ty::DebruijnIndex,
1021 var: ty::BoundVar,
1022 ) -> Result<(), Self::Error> {
1023 if debruijn == ty::INNERMOST {
1024 write!(self, "^{}", var.index())
1025 } else {
1026 write!(self, "^{}_{}", debruijn.index(), var.index())
1027 }
1028 }
1029
5099ac24
FG
1030 fn ty_infer_name(&self, _: ty::TyVid) -> Option<String> {
1031 None
1032 }
1033
1034 fn const_infer_name(&self, _: ty::ConstVid<'tcx>) -> Option<String> {
dc9dc135
XL
1035 None
1036 }
1037
532ac7d7
XL
1038 fn pretty_print_dyn_existential(
1039 mut self,
cdc7bbd5 1040 predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
532ac7d7 1041 ) -> Result<Self::DynExistential, Self::Error> {
532ac7d7
XL
1042 // Generate the main trait ref, including associated types.
1043 let mut first = true;
1044
1045 if let Some(principal) = predicates.principal() {
fc512014
XL
1046 self = self.wrap_binder(&principal, |principal, mut cx| {
1047 define_scoped_cx!(cx);
1048 p!(print_def_path(principal.def_id, &[]));
1049
1050 let mut resugared = false;
1051
5e7ed085 1052 // Special-case `Fn(...) -> ...` and re-sugar it.
fc512014
XL
1053 let fn_trait_kind = cx.tcx().fn_trait_kind_from_lang_item(principal.def_id);
1054 if !cx.tcx().sess.verbose() && fn_trait_kind.is_some() {
5e7ed085 1055 if let ty::Tuple(tys) = principal.substs.type_at(0).kind() {
fc512014
XL
1056 let mut projections = predicates.projection_bounds();
1057 if let (Some(proj), None) = (projections.next(), projections.next()) {
5099ac24 1058 p!(pretty_fn_sig(
5e7ed085 1059 tys,
5099ac24
FG
1060 false,
1061 proj.skip_binder().term.ty().expect("Return type was a const")
1062 ));
fc512014
XL
1063 resugared = true;
1064 }
532ac7d7
XL
1065 }
1066 }
532ac7d7 1067
fc512014
XL
1068 // HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`,
1069 // in order to place the projections inside the `<...>`.
1070 if !resugared {
1071 // Use a type that can't appear in defaults of type parameters.
1072 let dummy_cx = cx.tcx().mk_ty_infer(ty::FreshTy(0));
1073 let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
1074
1075 let args = cx.generic_args_to_print(
1076 cx.tcx().generics_of(principal.def_id),
1077 principal.substs,
1078 );
1079
1080 // Don't print `'_` if there's no unerased regions.
1081 let print_regions = args.iter().any(|arg| match arg.unpack() {
5099ac24 1082 GenericArgKind::Lifetime(r) => !r.is_erased(),
fc512014
XL
1083 _ => false,
1084 });
1085 let mut args = args.iter().cloned().filter(|arg| match arg.unpack() {
1086 GenericArgKind::Lifetime(_) => print_regions,
1087 _ => true,
1088 });
1089 let mut projections = predicates.projection_bounds();
532ac7d7 1090
fc512014
XL
1091 let arg0 = args.next();
1092 let projection0 = projections.next();
1093 if arg0.is_some() || projection0.is_some() {
1094 let args = arg0.into_iter().chain(args);
1095 let projections = projection0.into_iter().chain(projections);
532ac7d7 1096
fc512014
XL
1097 p!(generic_delimiters(|mut cx| {
1098 cx = cx.comma_sep(args)?;
1099 if arg0.is_some() && projection0.is_some() {
1100 write!(cx, ", ")?;
1101 }
1102 cx.comma_sep(projections)
1103 }));
1104 }
532ac7d7 1105 }
fc512014
XL
1106 Ok(cx)
1107 })?;
1108
532ac7d7
XL
1109 first = false;
1110 }
1111
fc512014
XL
1112 define_scoped_cx!(self);
1113
532ac7d7
XL
1114 // Builtin bounds.
1115 // FIXME(eddyb) avoid printing twice (needed to ensure
1116 // that the auto traits are sorted *and* printed via cx).
dfeec247
XL
1117 let mut auto_traits: Vec<_> =
1118 predicates.auto_traits().map(|did| (self.tcx().def_path_str(did), did)).collect();
532ac7d7
XL
1119
1120 // The auto traits come ordered by `DefPathHash`. While
1121 // `DefPathHash` is *stable* in the sense that it depends on
1122 // neither the host nor the phase of the moon, it depends
1123 // "pseudorandomly" on the compiler version and the target.
1124 //
1125 // To avoid that causing instabilities in compiletest
1126 // output, sort the auto-traits alphabetically.
1127 auto_traits.sort();
1128
1129 for (_, def_id) in auto_traits {
1130 if !first {
29967ef6 1131 p!(" + ");
532ac7d7
XL
1132 }
1133 first = false;
1134
1135 p!(print_def_path(def_id, &[]));
1136 }
1137
1138 Ok(self)
1139 }
1140
1141 fn pretty_fn_sig(
1142 mut self,
1143 inputs: &[Ty<'tcx>],
1144 c_variadic: bool,
1145 output: Ty<'tcx>,
1146 ) -> Result<Self, Self::Error> {
1147 define_scoped_cx!(self);
1148
29967ef6 1149 p!("(", comma_sep(inputs.iter().copied()));
ba9703b0
XL
1150 if c_variadic {
1151 if !inputs.is_empty() {
29967ef6 1152 p!(", ");
532ac7d7 1153 }
29967ef6 1154 p!("...");
532ac7d7 1155 }
29967ef6 1156 p!(")");
532ac7d7 1157 if !output.is_unit() {
29967ef6 1158 p!(" -> ", print(output));
532ac7d7
XL
1159 }
1160
1161 Ok(self)
1162 }
dc9dc135
XL
1163
1164 fn pretty_print_const(
1165 mut self,
5099ac24 1166 ct: ty::Const<'tcx>,
dfeec247 1167 print_ty: bool,
dc9dc135
XL
1168 ) -> Result<Self::Const, Self::Error> {
1169 define_scoped_cx!(self);
1170
e74abb32 1171 if self.tcx().sess.verbose() {
5099ac24 1172 p!(write("Const({:?}: {:?})", ct.val(), ct.ty()));
dc9dc135
XL
1173 return Ok(self);
1174 }
e74abb32 1175
dfeec247
XL
1176 macro_rules! print_underscore {
1177 () => {{
dfeec247 1178 if print_ty {
ba9703b0
XL
1179 self = self.typed_value(
1180 |mut this| {
1181 write!(this, "_")?;
1182 Ok(this)
1183 },
5099ac24 1184 |this| this.print_type(ct.ty()),
ba9703b0
XL
1185 ": ",
1186 )?;
1187 } else {
1188 write!(self, "_")?;
dfeec247
XL
1189 }
1190 }};
1191 }
1192
5099ac24
FG
1193 match ct.val() {
1194 ty::ConstKind::Unevaluated(ty::Unevaluated {
1195 def,
1196 substs,
1197 promoted: Some(promoted),
1198 }) => {
1199 p!(print_value_path(def.did, substs));
1200 p!(write("::{:?}", promoted));
1201 }
1202 ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) => {
1203 match self.tcx().def_kind(def.did) {
5e7ed085 1204 DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => {
5099ac24
FG
1205 p!(print_value_path(def.did, substs))
1206 }
1207 _ => {
1208 if def.is_local() {
1209 let span = self.tcx().def_span(def.did);
1210 if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
1211 p!(write("{}", snip))
dfeec247
XL
1212 } else {
1213 print_underscore!()
1214 }
5099ac24
FG
1215 } else {
1216 print_underscore!()
e74abb32 1217 }
dfeec247 1218 }
e74abb32 1219 }
dfeec247 1220 }
5099ac24
FG
1221 ty::ConstKind::Infer(infer_ct) => {
1222 match infer_ct {
1223 ty::InferConst::Var(ct_vid)
1224 if let Some(name) = self.const_infer_name(ct_vid) =>
1225 p!(write("{}", name)),
1226 _ => print_underscore!(),
1227 }
1228 }
ba9703b0
XL
1229 ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
1230 ty::ConstKind::Value(value) => {
5099ac24 1231 return self.pretty_print_const_value(value, ct.ty(), print_ty);
dfeec247 1232 }
60c5eb7d 1233
ba9703b0
XL
1234 ty::ConstKind::Bound(debruijn, bound_var) => {
1235 self.pretty_print_bound_var(debruijn, bound_var)?
60c5eb7d 1236 }
ba9703b0 1237 ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
29967ef6 1238 ty::ConstKind::Error(_) => p!("[const error]"),
60c5eb7d
XL
1239 };
1240 Ok(self)
1241 }
1242
ba9703b0 1243 fn pretty_print_const_scalar(
6a06907d 1244 self,
ba9703b0 1245 scalar: Scalar,
60c5eb7d 1246 ty: Ty<'tcx>,
dfeec247 1247 print_ty: bool,
6a06907d
XL
1248 ) -> Result<Self::Const, Self::Error> {
1249 match scalar {
136023e0 1250 Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty),
6a06907d
XL
1251 Scalar::Int(int) => self.pretty_print_const_scalar_int(int, ty, print_ty),
1252 }
1253 }
1254
1255 fn pretty_print_const_scalar_ptr(
1256 mut self,
1257 ptr: Pointer,
1258 ty: Ty<'tcx>,
1259 print_ty: bool,
60c5eb7d
XL
1260 ) -> Result<Self::Const, Self::Error> {
1261 define_scoped_cx!(self);
1262
136023e0 1263 let (alloc_id, offset) = ptr.into_parts();
6a06907d 1264 match ty.kind() {
ba9703b0 1265 // Byte strings (&[u8; N])
6a06907d
XL
1266 ty::Ref(
1267 _,
5099ac24
FG
1268 Ty(Interned(
1269 ty::TyS {
1270 kind:
1271 ty::Array(
1272 Ty(Interned(ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. }, _)),
1273 ty::Const(Interned(
1274 ty::ConstS {
1275 val: ty::ConstKind::Value(ConstValue::Scalar(int)),
1276 ..
1277 },
1278 _,
1279 )),
1280 ),
1281 ..
1282 },
1283 _,
1284 )),
6a06907d 1285 _,
136023e0 1286 ) => match self.tcx().get_global_alloc(alloc_id) {
f9f354fc 1287 Some(GlobalAlloc::Memory(alloc)) => {
17df50a5 1288 let len = int.assert_bits(self.tcx().data_layout.pointer_size);
136023e0 1289 let range = AllocRange { start: offset, size: Size::from_bytes(len) };
5e7ed085 1290 if let Ok(byte_str) = alloc.inner().get_bytes(&self.tcx(), range) {
f9f354fc
XL
1291 p!(pretty_print_byte_str(byte_str))
1292 } else {
29967ef6 1293 p!("<too short allocation>")
f9f354fc
XL
1294 }
1295 }
1296 // FIXME: for statics and functions, we could in principle print more detail.
1297 Some(GlobalAlloc::Static(def_id)) => p!(write("<static({:?})>", def_id)),
29967ef6
XL
1298 Some(GlobalAlloc::Function(_)) => p!("<function>"),
1299 None => p!("<dangling pointer>"),
f9f354fc 1300 },
6a06907d
XL
1301 ty::FnPtr(_) => {
1302 // FIXME: We should probably have a helper method to share code with the "Byte strings"
1303 // printing above (which also has to handle pointers to all sorts of things).
136023e0 1304 match self.tcx().get_global_alloc(alloc_id) {
6a06907d
XL
1305 Some(GlobalAlloc::Function(instance)) => {
1306 self = self.typed_value(
1307 |this| this.print_value_path(instance.def_id(), instance.substs),
1308 |this| this.print_type(ty),
1309 " as ",
1310 )?;
1311 }
1312 _ => self = self.pretty_print_const_pointer(ptr, ty, print_ty)?,
1313 }
1314 }
1315 // Any pointer values not covered by a branch above
1316 _ => {
1317 self = self.pretty_print_const_pointer(ptr, ty, print_ty)?;
1318 }
1319 }
1320 Ok(self)
1321 }
1322
1323 fn pretty_print_const_scalar_int(
1324 mut self,
1325 int: ScalarInt,
1326 ty: Ty<'tcx>,
1327 print_ty: bool,
1328 ) -> Result<Self::Const, Self::Error> {
1329 define_scoped_cx!(self);
1330
1331 match ty.kind() {
ba9703b0 1332 // Bool
6a06907d
XL
1333 ty::Bool if int == ScalarInt::FALSE => p!("false"),
1334 ty::Bool if int == ScalarInt::TRUE => p!("true"),
ba9703b0 1335 // Float
6a06907d 1336 ty::Float(ty::FloatTy::F32) => {
29967ef6 1337 p!(write("{}f32", Single::try_from(int).unwrap()))
dfeec247 1338 }
6a06907d 1339 ty::Float(ty::FloatTy::F64) => {
29967ef6 1340 p!(write("{}f64", Double::try_from(int).unwrap()))
dfeec247 1341 }
ba9703b0 1342 // Int
6a06907d 1343 ty::Uint(_) | ty::Int(_) => {
29967ef6
XL
1344 let int =
1345 ConstInt::new(int, matches!(ty.kind(), ty::Int(_)), ty.is_ptr_sized_integral());
f035d41b 1346 if print_ty { p!(write("{:#?}", int)) } else { p!(write("{:?}", int)) }
dfeec247 1347 }
ba9703b0 1348 // Char
6a06907d 1349 ty::Char if char::try_from(int).is_ok() => {
29967ef6 1350 p!(write("{:?}", char::try_from(int).unwrap()))
ba9703b0 1351 }
136023e0
XL
1352 // Pointer types
1353 ty::Ref(..) | ty::RawPtr(_) | ty::FnPtr(_) => {
29967ef6 1354 let data = int.assert_bits(self.tcx().data_layout.pointer_size);
ba9703b0
XL
1355 self = self.typed_value(
1356 |mut this| {
1357 write!(this, "0x{:x}", data)?;
1358 Ok(this)
1359 },
1360 |this| this.print_type(ty),
1361 " as ",
1362 )?;
dfeec247 1363 }
ba9703b0 1364 // For function type zsts just printing the path is enough
6a06907d 1365 ty::FnDef(d, s) if int == ScalarInt::ZST => {
29967ef6
XL
1366 p!(print_value_path(*d, s))
1367 }
ba9703b0 1368 // Nontrivial types with scalar bit representation
6a06907d 1369 _ => {
ba9703b0 1370 let print = |mut this: Self| {
29967ef6 1371 if int.size() == Size::ZERO {
ba9703b0 1372 write!(this, "transmute(())")?;
416331ca 1373 } else {
29967ef6 1374 write!(this, "transmute(0x{:x})", int)?;
dc9dc135 1375 }
ba9703b0
XL
1376 Ok(this)
1377 };
1378 self = if print_ty {
1379 self.typed_value(print, |this| this.print_type(ty), ": ")?
e74abb32 1380 } else {
ba9703b0 1381 print(self)?
e74abb32 1382 };
ba9703b0 1383 }
ba9703b0
XL
1384 }
1385 Ok(self)
1386 }
1387
1388 /// This is overridden for MIR printing because we only want to hide alloc ids from users, not
1389 /// from MIR where it is actually useful.
136023e0 1390 fn pretty_print_const_pointer<Tag: Provenance>(
ba9703b0 1391 mut self,
136023e0 1392 _: Pointer<Tag>,
ba9703b0
XL
1393 ty: Ty<'tcx>,
1394 print_ty: bool,
1395 ) -> Result<Self::Const, Self::Error> {
1396 if print_ty {
1397 self.typed_value(
1398 |mut this| {
1399 this.write_str("&_")?;
1400 Ok(this)
1401 },
1402 |this| this.print_type(ty),
1403 ": ",
1404 )
1405 } else {
1406 self.write_str("&_")?;
1407 Ok(self)
1408 }
1409 }
1410
1411 fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const, Self::Error> {
1412 define_scoped_cx!(self);
29967ef6 1413 p!("b\"");
ba9703b0
XL
1414 for &c in byte_str {
1415 for e in std::ascii::escape_default(c) {
1416 self.write_char(e as char)?;
1417 }
1418 }
29967ef6 1419 p!("\"");
ba9703b0
XL
1420 Ok(self)
1421 }
1422
1423 fn pretty_print_const_value(
1424 mut self,
1425 ct: ConstValue<'tcx>,
1426 ty: Ty<'tcx>,
1427 print_ty: bool,
1428 ) -> Result<Self::Const, Self::Error> {
1429 define_scoped_cx!(self);
1430
1431 if self.tcx().sess.verbose() {
29967ef6 1432 p!(write("ConstValue({:?}: ", ct), print(ty), ")");
ba9703b0
XL
1433 return Ok(self);
1434 }
1435
1436 let u8_type = self.tcx().types.u8;
1437
1b1a35ee 1438 match (ct, ty.kind()) {
ba9703b0
XL
1439 // Byte/string slices, printed as (byte) string literals.
1440 (
1441 ConstValue::Slice { data, start, end },
5099ac24 1442 ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Slice(t), .. }, _)), _),
ba9703b0
XL
1443 ) if *t == u8_type => {
1444 // The `inspect` here is okay since we checked the bounds, and there are
1445 // no relocations (we have an active slice reference here). We don't use
1446 // this result to affect interpreter execution.
5e7ed085
FG
1447 let byte_str =
1448 data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end);
ba9703b0
XL
1449 self.pretty_print_byte_str(byte_str)
1450 }
1451 (
1452 ConstValue::Slice { data, start, end },
5099ac24 1453 ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Str, .. }, _)), _),
ba9703b0
XL
1454 ) => {
1455 // The `inspect` here is okay since we checked the bounds, and there are no
1456 // relocations (we have an active `str` reference here). We don't use this
1457 // result to affect interpreter execution.
5e7ed085
FG
1458 let slice =
1459 data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end);
1460 p!(write("{:?}", String::from_utf8_lossy(slice)));
ba9703b0
XL
1461 Ok(self)
1462 }
1463 (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
5099ac24 1464 let n = n.val().try_to_bits(self.tcx().data_layout.pointer_size).unwrap();
ba9703b0 1465 // cast is ok because we already checked for pointer size (32 or 64 bit) above
17df50a5 1466 let range = AllocRange { start: offset, size: Size::from_bytes(n) };
ba9703b0 1467
5e7ed085 1468 let byte_str = alloc.inner().get_bytes(&self.tcx(), range).unwrap();
29967ef6 1469 p!("*");
ba9703b0
XL
1470 p!(pretty_print_byte_str(byte_str));
1471 Ok(self)
1472 }
1473
1474 // Aggregates, printed as array/tuple/struct/variant construction syntax.
1475 //
5099ac24 1476 // NB: the `has_param_types_or_consts` check ensures that we can use
ba9703b0
XL
1477 // the `destructure_const` query with an empty `ty::ParamEnv` without
1478 // introducing ICEs (e.g. via `layout_of`) from missing bounds.
1479 // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
1480 // to be able to destructure the tuple into `(0u8, *mut T)
1481 //
1482 // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
1483 // correct `ty::ParamEnv` to allow printing *all* constant values.
5099ac24
FG
1484 (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
1485 let Some(contents) = self.tcx().try_destructure_const(
ba9703b0 1486 ty::ParamEnv::reveal_all()
5099ac24
FG
1487 .and(self.tcx().mk_const(ty::ConstS { val: ty::ConstKind::Value(ct), ty })),
1488 ) else {
1489 // Fall back to debug pretty printing for invalid constants.
1490 p!(write("{:?}", ct));
1491 if print_ty {
1492 p!(": ", print(ty));
1493 }
1494 return Ok(self);
1495 };
1496
ba9703b0
XL
1497 let fields = contents.fields.iter().copied();
1498
1b1a35ee 1499 match *ty.kind() {
ba9703b0 1500 ty::Array(..) => {
29967ef6 1501 p!("[", comma_sep(fields), "]");
ba9703b0
XL
1502 }
1503 ty::Tuple(..) => {
29967ef6 1504 p!("(", comma_sep(fields));
ba9703b0 1505 if contents.fields.len() == 1 {
29967ef6 1506 p!(",");
ba9703b0 1507 }
29967ef6 1508 p!(")");
dfeec247 1509 }
5e7ed085 1510 ty::Adt(def, _) if def.variants().is_empty() => {
94222f64
XL
1511 self = self.typed_value(
1512 |mut this| {
1513 write!(this, "unreachable()")?;
1514 Ok(this)
1515 },
1516 |this| this.print_type(ty),
1517 ": ",
1518 )?;
f035d41b 1519 }
ba9703b0 1520 ty::Adt(def, substs) => {
94222f64
XL
1521 let variant_idx =
1522 contents.variant.expect("destructed const of adt without variant idx");
5e7ed085 1523 let variant_def = &def.variant(variant_idx);
ba9703b0
XL
1524 p!(print_value_path(variant_def.def_id, substs));
1525
1526 match variant_def.ctor_kind {
1527 CtorKind::Const => {}
1528 CtorKind::Fn => {
29967ef6 1529 p!("(", comma_sep(fields), ")");
ba9703b0
XL
1530 }
1531 CtorKind::Fictive => {
29967ef6 1532 p!(" {{ ");
ba9703b0 1533 let mut first = true;
cdc7bbd5 1534 for (field_def, field) in iter::zip(&variant_def.fields, fields) {
ba9703b0 1535 if !first {
29967ef6 1536 p!(", ");
ba9703b0 1537 }
5099ac24 1538 p!(write("{}: ", field_def.name), print(field));
ba9703b0
XL
1539 first = false;
1540 }
29967ef6 1541 p!(" }}");
ba9703b0
XL
1542 }
1543 }
1544 }
1545 _ => unreachable!(),
dc9dc135 1546 }
ba9703b0
XL
1547
1548 Ok(self)
dc9dc135 1549 }
ba9703b0
XL
1550
1551 (ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty),
1552
1553 // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
1554 // their fields instead of just dumping the memory.
1555 _ => {
1556 // fallback
1557 p!(write("{:?}", ct));
1558 if print_ty {
29967ef6 1559 p!(": ", print(ty));
ba9703b0
XL
1560 }
1561 Ok(self)
1562 }
1563 }
dc9dc135 1564 }
532ac7d7
XL
1565}
1566
1567// HACK(eddyb) boxed to avoid moving around a large struct by-value.
5e7ed085 1568pub struct FmtPrinter<'a, 'tcx>(Box<FmtPrinterData<'a, 'tcx>>);
532ac7d7 1569
5e7ed085 1570pub struct FmtPrinterData<'a, 'tcx> {
dc9dc135 1571 tcx: TyCtxt<'tcx>,
5e7ed085 1572 fmt: String,
532ac7d7
XL
1573
1574 empty_path: bool,
1575 in_value: bool,
ba9703b0 1576 pub print_alloc_ids: bool,
532ac7d7 1577
e74abb32 1578 used_region_names: FxHashSet<Symbol>,
532ac7d7
XL
1579 region_index: usize,
1580 binder_depth: usize,
6c58768f 1581 printed_type_count: usize,
532ac7d7 1582
5099ac24 1583 pub region_highlight_mode: RegionHighlightMode<'tcx>,
dc9dc135 1584
5099ac24
FG
1585 pub ty_infer_name_resolver: Option<Box<dyn Fn(ty::TyVid) -> Option<String> + 'a>>,
1586 pub const_infer_name_resolver: Option<Box<dyn Fn(ty::ConstVid<'tcx>) -> Option<String> + 'a>>,
532ac7d7
XL
1587}
1588
5e7ed085
FG
1589impl<'a, 'tcx> Deref for FmtPrinter<'a, 'tcx> {
1590 type Target = FmtPrinterData<'a, 'tcx>;
532ac7d7
XL
1591 fn deref(&self) -> &Self::Target {
1592 &self.0
1593 }
1594}
1595
5e7ed085 1596impl DerefMut for FmtPrinter<'_, '_> {
532ac7d7
XL
1597 fn deref_mut(&mut self) -> &mut Self::Target {
1598 &mut self.0
1599 }
1600}
1601
5e7ed085
FG
1602impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
1603 pub fn new(tcx: TyCtxt<'tcx>, ns: Namespace) -> Self {
532ac7d7
XL
1604 FmtPrinter(Box::new(FmtPrinterData {
1605 tcx,
5e7ed085
FG
1606 // Estimated reasonable capacity to allocate upfront based on a few
1607 // benchmarks.
1608 fmt: String::with_capacity(64),
532ac7d7
XL
1609 empty_path: false,
1610 in_value: ns == Namespace::ValueNS,
ba9703b0 1611 print_alloc_ids: false,
532ac7d7
XL
1612 used_region_names: Default::default(),
1613 region_index: 0,
1614 binder_depth: 0,
6c58768f 1615 printed_type_count: 0,
5099ac24
FG
1616 region_highlight_mode: RegionHighlightMode::new(tcx),
1617 ty_infer_name_resolver: None,
1618 const_infer_name_resolver: None,
532ac7d7
XL
1619 }))
1620 }
5e7ed085
FG
1621
1622 pub fn into_buffer(self) -> String {
1623 self.0.fmt
1624 }
532ac7d7
XL
1625}
1626
dfeec247
XL
1627// HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
1628// (but also some things just print a `DefId` generally so maybe we need this?)
1629fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
1630 match tcx.def_key(def_id).disambiguated_data.data {
1631 DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::ImplTrait => {
1632 Namespace::TypeNS
532ac7d7 1633 }
dfeec247
XL
1634
1635 DefPathData::ValueNs(..)
1636 | DefPathData::AnonConst
1637 | DefPathData::ClosureExpr
1638 | DefPathData::Ctor => Namespace::ValueNS,
1639
1640 DefPathData::MacroNs(..) => Namespace::MacroNS,
1641
1642 _ => Namespace::TypeNS,
532ac7d7 1643 }
dfeec247 1644}
532ac7d7 1645
a2a8927a 1646impl<'t> TyCtxt<'t> {
532ac7d7
XL
1647 /// Returns a string identifying this `DefId`. This string is
1648 /// suitable for user output.
1649 pub fn def_path_str(self, def_id: DefId) -> String {
60c5eb7d
XL
1650 self.def_path_str_with_substs(def_id, &[])
1651 }
1652
1653 pub fn def_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String {
dfeec247 1654 let ns = guess_def_namespace(self, def_id);
532ac7d7 1655 debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
5e7ed085 1656 FmtPrinter::new(self, ns).print_def_path(def_id, substs).unwrap().into_buffer()
532ac7d7
XL
1657 }
1658}
1659
5e7ed085 1660impl fmt::Write for FmtPrinter<'_, '_> {
532ac7d7 1661 fn write_str(&mut self, s: &str) -> fmt::Result {
5e7ed085
FG
1662 self.fmt.push_str(s);
1663 Ok(())
532ac7d7
XL
1664 }
1665}
1666
5e7ed085 1667impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
532ac7d7
XL
1668 type Error = fmt::Error;
1669
1670 type Path = Self;
1671 type Region = Self;
1672 type Type = Self;
1673 type DynExistential = Self;
dc9dc135 1674 type Const = Self;
532ac7d7 1675
a2a8927a 1676 fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
532ac7d7
XL
1677 self.tcx
1678 }
1679
1680 fn print_def_path(
1681 mut self,
1682 def_id: DefId,
e74abb32 1683 substs: &'tcx [GenericArg<'tcx>],
532ac7d7
XL
1684 ) -> Result<Self::Path, Self::Error> {
1685 define_scoped_cx!(self);
1686
1687 if substs.is_empty() {
1b1a35ee
XL
1688 match self.try_print_trimmed_def_path(def_id)? {
1689 (cx, true) => return Ok(cx),
1690 (cx, false) => self = cx,
1691 }
1692
532ac7d7
XL
1693 match self.try_print_visible_def_path(def_id)? {
1694 (cx, true) => return Ok(cx),
1695 (cx, false) => self = cx,
1696 }
1697 }
1698
1699 let key = self.tcx.def_key(def_id);
1700 if let DefPathData::Impl = key.disambiguated_data.data {
1701 // Always use types for non-local impls, where types are always
1702 // available, and filename/line-number is mostly uninteresting.
dfeec247
XL
1703 let use_types = !def_id.is_local() || {
1704 // Otherwise, use filename/line-number if forced.
1705 let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
1706 !force_no_types
1707 };
532ac7d7
XL
1708
1709 if !use_types {
1710 // If no type info is available, fall back to
1711 // pretty printing some span information. This should
1712 // only occur very early in the compiler pipeline.
1713 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
1714 let span = self.tcx.def_span(def_id);
1715
1716 self = self.print_def_path(parent_def_id, &[])?;
1717
1718 // HACK(eddyb) copy of `path_append` to avoid
1719 // constructing a `DisambiguatedDefPathData`.
1720 if !self.empty_path {
1721 write!(self, "::")?;
1722 }
17df50a5
XL
1723 write!(
1724 self,
1725 "<impl at {}>",
1726 // This may end up in stderr diagnostics but it may also be emitted
1727 // into MIR. Hence we use the remapped path if available
1728 self.tcx.sess.source_map().span_to_embeddable_string(span)
1729 )?;
532ac7d7
XL
1730 self.empty_path = false;
1731
1732 return Ok(self);
1733 }
1734 }
1735
1736 self.default_print_def_path(def_id, substs)
1737 }
1738
dfeec247 1739 fn print_region(self, region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
532ac7d7
XL
1740 self.pretty_print_region(region)
1741 }
1742
6c58768f 1743 fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
136023e0 1744 let type_length_limit = self.tcx.type_length_limit();
cdc7bbd5 1745 if type_length_limit.value_within_limit(self.printed_type_count) {
6c58768f
XL
1746 self.printed_type_count += 1;
1747 self.pretty_print_type(ty)
1748 } else {
1749 write!(self, "...")?;
1750 Ok(self)
1751 }
532ac7d7
XL
1752 }
1753
1754 fn print_dyn_existential(
1755 self,
cdc7bbd5 1756 predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
532ac7d7
XL
1757 ) -> Result<Self::DynExistential, Self::Error> {
1758 self.pretty_print_dyn_existential(predicates)
1759 }
1760
5099ac24 1761 fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
dfeec247 1762 self.pretty_print_const(ct, true)
dc9dc135
XL
1763 }
1764
dfeec247 1765 fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
532ac7d7
XL
1766 self.empty_path = true;
1767 if cnum == LOCAL_CRATE {
1768 if self.tcx.sess.rust_2018() {
1769 // We add the `crate::` keyword on Rust 2018, only when desired.
1770 if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
dc9dc135 1771 write!(self, "{}", kw::Crate)?;
532ac7d7
XL
1772 self.empty_path = false;
1773 }
1774 }
1775 } else {
1776 write!(self, "{}", self.tcx.crate_name(cnum))?;
1777 self.empty_path = false;
1778 }
1779 Ok(self)
1780 }
e1599b0c 1781
532ac7d7
XL
1782 fn path_qualified(
1783 mut self,
1784 self_ty: Ty<'tcx>,
1785 trait_ref: Option<ty::TraitRef<'tcx>>,
1786 ) -> Result<Self::Path, Self::Error> {
1787 self = self.pretty_path_qualified(self_ty, trait_ref)?;
1788 self.empty_path = false;
1789 Ok(self)
1790 }
1791
1792 fn path_append_impl(
1793 mut self,
1794 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
1795 _disambiguated_data: &DisambiguatedDefPathData,
1796 self_ty: Ty<'tcx>,
1797 trait_ref: Option<ty::TraitRef<'tcx>>,
1798 ) -> Result<Self::Path, Self::Error> {
dfeec247
XL
1799 self = self.pretty_path_append_impl(
1800 |mut cx| {
1801 cx = print_prefix(cx)?;
1802 if !cx.empty_path {
1803 write!(cx, "::")?;
1804 }
532ac7d7 1805
dfeec247
XL
1806 Ok(cx)
1807 },
1808 self_ty,
1809 trait_ref,
1810 )?;
532ac7d7
XL
1811 self.empty_path = false;
1812 Ok(self)
1813 }
e1599b0c 1814
532ac7d7
XL
1815 fn path_append(
1816 mut self,
1817 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
1818 disambiguated_data: &DisambiguatedDefPathData,
1819 ) -> Result<Self::Path, Self::Error> {
1820 self = print_prefix(self)?;
1821
a2a8927a
XL
1822 // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
1823 if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data {
ba9703b0 1824 return Ok(self);
532ac7d7
XL
1825 }
1826
1b1a35ee 1827 let name = disambiguated_data.data.name();
a2a8927a
XL
1828 if !self.empty_path {
1829 write!(self, "::")?;
1830 }
532ac7d7 1831
a2a8927a
XL
1832 if let DefPathDataName::Named(name) = name {
1833 if Ident::with_dummy_span(name).is_raw_guess() {
1834 write!(self, "r#")?;
532ac7d7 1835 }
a2a8927a 1836 }
532ac7d7 1837
a2a8927a
XL
1838 let verbose = self.tcx.sess.verbose();
1839 disambiguated_data.fmt_maybe_verbose(&mut self, verbose)?;
1b1a35ee 1840
a2a8927a 1841 self.empty_path = false;
532ac7d7
XL
1842
1843 Ok(self)
1844 }
e1599b0c 1845
532ac7d7
XL
1846 fn path_generic_args(
1847 mut self,
1848 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
e74abb32 1849 args: &[GenericArg<'tcx>],
532ac7d7
XL
1850 ) -> Result<Self::Path, Self::Error> {
1851 self = print_prefix(self)?;
1852
1853 // Don't print `'_` if there's no unerased regions.
5099ac24
FG
1854 let print_regions = self.tcx.sess.verbose()
1855 || args.iter().any(|arg| match arg.unpack() {
1856 GenericArgKind::Lifetime(r) => !r.is_erased(),
1857 _ => false,
1858 });
dfeec247
XL
1859 let args = args.iter().cloned().filter(|arg| match arg.unpack() {
1860 GenericArgKind::Lifetime(_) => print_regions,
1861 _ => true,
532ac7d7
XL
1862 });
1863
1864 if args.clone().next().is_some() {
1865 if self.in_value {
1866 write!(self, "::")?;
1867 }
1868 self.generic_delimiters(|cx| cx.comma_sep(args))
1869 } else {
1870 Ok(self)
1871 }
1872 }
1873}
1874
5e7ed085 1875impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
5099ac24
FG
1876 fn ty_infer_name(&self, id: ty::TyVid) -> Option<String> {
1877 self.0.ty_infer_name_resolver.as_ref().and_then(|func| func(id))
1878 }
1879
1880 fn const_infer_name(&self, id: ty::ConstVid<'tcx>) -> Option<String> {
1881 self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id))
dc9dc135
XL
1882 }
1883
532ac7d7
XL
1884 fn print_value_path(
1885 mut self,
1886 def_id: DefId,
e74abb32 1887 substs: &'tcx [GenericArg<'tcx>],
532ac7d7
XL
1888 ) -> Result<Self::Path, Self::Error> {
1889 let was_in_value = std::mem::replace(&mut self.in_value, true);
1890 self = self.print_def_path(def_id, substs)?;
1891 self.in_value = was_in_value;
1892
1893 Ok(self)
1894 }
1895
cdc7bbd5 1896 fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error>
dc9dc135
XL
1897 where
1898 T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
532ac7d7
XL
1899 {
1900 self.pretty_in_binder(value)
1901 }
1902
fc512014
XL
1903 fn wrap_binder<T, C: Fn(&T, Self) -> Result<Self, Self::Error>>(
1904 self,
cdc7bbd5 1905 value: &ty::Binder<'tcx, T>,
fc512014
XL
1906 f: C,
1907 ) -> Result<Self, Self::Error>
1908 where
1909 T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
1910 {
1911 self.pretty_wrap_binder(value, f)
1912 }
1913
ba9703b0
XL
1914 fn typed_value(
1915 mut self,
1916 f: impl FnOnce(Self) -> Result<Self, Self::Error>,
1917 t: impl FnOnce(Self) -> Result<Self, Self::Error>,
1918 conversion: &str,
1919 ) -> Result<Self::Const, Self::Error> {
1920 self.write_str("{")?;
1921 self = f(self)?;
1922 self.write_str(conversion)?;
1923 let was_in_value = std::mem::replace(&mut self.in_value, false);
1924 self = t(self)?;
1925 self.in_value = was_in_value;
1926 self.write_str("}")?;
1927 Ok(self)
1928 }
1929
532ac7d7
XL
1930 fn generic_delimiters(
1931 mut self,
1932 f: impl FnOnce(Self) -> Result<Self, Self::Error>,
1933 ) -> Result<Self, Self::Error> {
1934 write!(self, "<")?;
1935
1936 let was_in_value = std::mem::replace(&mut self.in_value, false);
1937 let mut inner = f(self)?;
1938 inner.in_value = was_in_value;
1939
1940 write!(inner, ">")?;
1941 Ok(inner)
1942 }
1943
5e7ed085 1944 fn should_print_region(&self, region: ty::Region<'_>) -> bool {
532ac7d7
XL
1945 let highlight = self.region_highlight_mode;
1946 if highlight.region_highlighted(region).is_some() {
1947 return true;
1948 }
1949
1950 if self.tcx.sess.verbose() {
1951 return true;
1952 }
1953
1954 let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions;
1955
1956 match *region {
1957 ty::ReEarlyBound(ref data) => {
5869c6ff 1958 data.name != kw::Empty && data.name != kw::UnderscoreLifetime
532ac7d7
XL
1959 }
1960
cdc7bbd5 1961 ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
dfeec247
XL
1962 | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
1963 | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
532ac7d7 1964 if let ty::BrNamed(_, name) = br {
5869c6ff 1965 if name != kw::Empty && name != kw::UnderscoreLifetime {
532ac7d7
XL
1966 return true;
1967 }
1968 }
1969
1970 if let Some((region, _)) = highlight.highlight_bound_region {
1971 if br == region {
1972 return true;
1973 }
1974 }
1975
1976 false
1977 }
1978
f9f354fc 1979 ty::ReVar(_) if identify_regions => true,
532ac7d7 1980
f9f354fc 1981 ty::ReVar(_) | ty::ReErased => false,
532ac7d7 1982
ba9703b0
XL
1983 ty::ReStatic | ty::ReEmpty(_) => true,
1984 }
1985 }
1986
136023e0 1987 fn pretty_print_const_pointer<Tag: Provenance>(
ba9703b0 1988 self,
136023e0 1989 p: Pointer<Tag>,
ba9703b0
XL
1990 ty: Ty<'tcx>,
1991 print_ty: bool,
1992 ) -> Result<Self::Const, Self::Error> {
1993 let print = |mut this: Self| {
1994 define_scoped_cx!(this);
1995 if this.print_alloc_ids {
1996 p!(write("{:?}", p));
1997 } else {
29967ef6 1998 p!("&_");
ba9703b0
XL
1999 }
2000 Ok(this)
2001 };
2002 if print_ty {
2003 self.typed_value(print, |this| this.print_type(ty), ": ")
2004 } else {
2005 print(self)
532ac7d7
XL
2006 }
2007 }
2008}
2009
2010// HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
5e7ed085 2011impl FmtPrinter<'_, '_> {
dfeec247 2012 pub fn pretty_print_region(mut self, region: ty::Region<'_>) -> Result<Self, fmt::Error> {
532ac7d7
XL
2013 define_scoped_cx!(self);
2014
2015 // Watch out for region highlights.
2016 let highlight = self.region_highlight_mode;
2017 if let Some(n) = highlight.region_highlighted(region) {
2018 p!(write("'{}", n));
2019 return Ok(self);
2020 }
2021
2022 if self.tcx.sess.verbose() {
2023 p!(write("{:?}", region));
2024 return Ok(self);
2025 }
2026
2027 let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions;
2028
2029 // These printouts are concise. They do not contain all the information
2030 // the user might want to diagnose an error, but there is basically no way
2031 // to fit that into a short string. Hence the recommendation to use
2032 // `explain_region()` or `note_and_explain_region()`.
2033 match *region {
2034 ty::ReEarlyBound(ref data) => {
5869c6ff 2035 if data.name != kw::Empty {
532ac7d7
XL
2036 p!(write("{}", data.name));
2037 return Ok(self);
2038 }
2039 }
cdc7bbd5 2040 ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
dfeec247
XL
2041 | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
2042 | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
532ac7d7 2043 if let ty::BrNamed(_, name) = br {
5869c6ff 2044 if name != kw::Empty && name != kw::UnderscoreLifetime {
532ac7d7
XL
2045 p!(write("{}", name));
2046 return Ok(self);
2047 }
2048 }
2049
2050 if let Some((region, counter)) = highlight.highlight_bound_region {
2051 if br == region {
2052 p!(write("'{}", counter));
2053 return Ok(self);
2054 }
2055 }
2056 }
532ac7d7
XL
2057 ty::ReVar(region_vid) if identify_regions => {
2058 p!(write("{:?}", region_vid));
2059 return Ok(self);
2060 }
2061 ty::ReVar(_) => {}
f9f354fc 2062 ty::ReErased => {}
532ac7d7 2063 ty::ReStatic => {
29967ef6 2064 p!("'static");
532ac7d7
XL
2065 return Ok(self);
2066 }
74b04a01 2067 ty::ReEmpty(ty::UniverseIndex::ROOT) => {
29967ef6 2068 p!("'<empty>");
532ac7d7
XL
2069 return Ok(self);
2070 }
74b04a01
XL
2071 ty::ReEmpty(ui) => {
2072 p!(write("'<empty:{:?}>", ui));
2073 return Ok(self);
2074 }
532ac7d7
XL
2075 }
2076
29967ef6 2077 p!("'_");
532ac7d7
XL
2078
2079 Ok(self)
2080 }
2081}
2082
136023e0
XL
2083/// Folds through bound vars and placeholders, naming them
2084struct RegionFolder<'a, 'tcx> {
2085 tcx: TyCtxt<'tcx>,
2086 current_index: ty::DebruijnIndex,
2087 region_map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
2088 name: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
2089}
2090
2091impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
2092 fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
2093 self.tcx
2094 }
2095
2096 fn fold_binder<T: TypeFoldable<'tcx>>(
2097 &mut self,
2098 t: ty::Binder<'tcx, T>,
2099 ) -> ty::Binder<'tcx, T> {
2100 self.current_index.shift_in(1);
2101 let t = t.super_fold_with(self);
2102 self.current_index.shift_out(1);
2103 t
2104 }
2105
2106 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
2107 match *t.kind() {
2108 _ if t.has_vars_bound_at_or_above(self.current_index) || t.has_placeholders() => {
2109 return t.super_fold_with(self);
2110 }
2111 _ => {}
2112 }
2113 t
2114 }
2115
2116 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
2117 let name = &mut self.name;
2118 let region = match *r {
5099ac24 2119 ty::ReLateBound(_, br) => *self.region_map.entry(br).or_insert_with(|| name(br)),
136023e0
XL
2120 ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => {
2121 // If this is an anonymous placeholder, don't rename. Otherwise, in some
2122 // async fns, we get a `for<'r> Send` bound
2123 match kind {
2124 ty::BrAnon(_) | ty::BrEnv => r,
2125 _ => {
2126 // Index doesn't matter, since this is just for naming and these never get bound
2127 let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind };
5099ac24 2128 *self.region_map.entry(br).or_insert_with(|| name(br))
136023e0
XL
2129 }
2130 }
2131 }
2132 _ => return r,
2133 };
2134 if let ty::ReLateBound(debruijn1, br) = *region {
2135 assert_eq!(debruijn1, ty::INNERMOST);
2136 self.tcx.mk_region(ty::ReLateBound(self.current_index, br))
2137 } else {
2138 region
2139 }
2140 }
2141}
2142
532ac7d7
XL
2143// HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`,
2144// `region_index` and `used_region_names`.
5e7ed085 2145impl<'tcx> FmtPrinter<'_, 'tcx> {
60c5eb7d
XL
2146 pub fn name_all_regions<T>(
2147 mut self,
cdc7bbd5 2148 value: &ty::Binder<'tcx, T>,
136023e0 2149 ) -> Result<(Self, T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
dc9dc135
XL
2150 where
2151 T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
532ac7d7 2152 {
e74abb32 2153 fn name_by_region_index(index: usize) -> Symbol {
532ac7d7 2154 match index {
e74abb32
XL
2155 0 => Symbol::intern("'r"),
2156 1 => Symbol::intern("'s"),
dfeec247 2157 i => Symbol::intern(&format!("'t{}", i - 2)),
48663c56 2158 }
532ac7d7
XL
2159 }
2160
2161 // Replace any anonymous late-bound regions with named
e74abb32 2162 // variants, using new unique identifiers, so that we can
532ac7d7
XL
2163 // clearly differentiate between named and unnamed regions in
2164 // the output. We'll probably want to tweak this over time to
2165 // decide just how much information to give.
2166 if self.binder_depth == 0 {
2167 self.prepare_late_bound_region_info(value);
2168 }
2169
2170 let mut empty = true;
2171 let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
136023e0
XL
2172 let w = if empty {
2173 empty = false;
2174 start
2175 } else {
2176 cont
2177 };
2178 let _ = write!(cx, "{}", w);
2179 };
2180 let do_continue = |cx: &mut Self, cont: Symbol| {
2181 let _ = write!(cx, "{}", cont);
532ac7d7
XL
2182 };
2183
2184 define_scoped_cx!(self);
2185
60c5eb7d 2186 let mut region_index = self.region_index;
5e7ed085 2187 // If we want to print verbosely, then print *all* binders, even if they
cdc7bbd5
XL
2188 // aren't named. Eventually, we might just want this as the default, but
2189 // this is not *quite* right and changes the ordering of some output
2190 // anyways.
136023e0 2191 let (new_value, map) = if self.tcx().sess.verbose() {
cdc7bbd5
XL
2192 // anon index + 1 (BrEnv takes 0) -> name
2193 let mut region_map: BTreeMap<u32, Symbol> = BTreeMap::default();
2194 let bound_vars = value.bound_vars();
2195 for var in bound_vars {
2196 match var {
2197 ty::BoundVariableKind::Region(ty::BrNamed(_, name)) => {
136023e0
XL
2198 start_or_continue(&mut self, "for<", ", ");
2199 do_continue(&mut self, name);
cdc7bbd5
XL
2200 }
2201 ty::BoundVariableKind::Region(ty::BrAnon(i)) => {
136023e0 2202 start_or_continue(&mut self, "for<", ", ");
cdc7bbd5
XL
2203 let name = loop {
2204 let name = name_by_region_index(region_index);
2205 region_index += 1;
2206 if !self.used_region_names.contains(&name) {
2207 break name;
2208 }
2209 };
136023e0 2210 do_continue(&mut self, name);
cdc7bbd5
XL
2211 region_map.insert(i + 1, name);
2212 }
2213 ty::BoundVariableKind::Region(ty::BrEnv) => {
136023e0 2214 start_or_continue(&mut self, "for<", ", ");
cdc7bbd5
XL
2215 let name = loop {
2216 let name = name_by_region_index(region_index);
2217 region_index += 1;
2218 if !self.used_region_names.contains(&name) {
2219 break name;
2220 }
2221 };
136023e0 2222 do_continue(&mut self, name);
cdc7bbd5
XL
2223 region_map.insert(0, name);
2224 }
2225 _ => continue,
532ac7d7 2226 }
cdc7bbd5 2227 }
136023e0 2228 start_or_continue(&mut self, "", "> ");
cdc7bbd5
XL
2229
2230 self.tcx.replace_late_bound_regions(value.clone(), |br| {
2231 let kind = match br.kind {
2232 ty::BrNamed(_, _) => br.kind,
2233 ty::BrAnon(i) => {
2234 let name = region_map[&(i + 1)];
2235 ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
2236 }
2237 ty::BrEnv => {
2238 let name = region_map[&0];
2239 ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
2240 }
2241 };
2242 self.tcx.mk_region(ty::ReLateBound(
2243 ty::INNERMOST,
2244 ty::BoundRegion { var: br.var, kind },
2245 ))
2246 })
2247 } else {
136023e0
XL
2248 let tcx = self.tcx;
2249 let mut name = |br: ty::BoundRegion| {
2250 start_or_continue(&mut self, "for<", ", ");
cdc7bbd5
XL
2251 let kind = match br.kind {
2252 ty::BrNamed(_, name) => {
136023e0 2253 do_continue(&mut self, name);
cdc7bbd5
XL
2254 br.kind
2255 }
2256 ty::BrAnon(_) | ty::BrEnv => {
2257 let name = loop {
2258 let name = name_by_region_index(region_index);
2259 region_index += 1;
2260 if !self.used_region_names.contains(&name) {
2261 break name;
2262 }
2263 };
136023e0 2264 do_continue(&mut self, name);
cdc7bbd5
XL
2265 ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
2266 }
2267 };
136023e0
XL
2268 tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
2269 };
2270 let mut folder = RegionFolder {
2271 tcx,
2272 current_index: ty::INNERMOST,
2273 name: &mut name,
2274 region_map: BTreeMap::new(),
2275 };
2276 let new_value = value.clone().skip_binder().fold_with(&mut folder);
2277 let region_map = folder.region_map;
2278 start_or_continue(&mut self, "", "> ");
2279 (new_value, region_map)
cdc7bbd5 2280 };
532ac7d7
XL
2281
2282 self.binder_depth += 1;
2283 self.region_index = region_index;
136023e0 2284 Ok((self, new_value, map))
60c5eb7d
XL
2285 }
2286
cdc7bbd5 2287 pub fn pretty_in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, fmt::Error>
60c5eb7d
XL
2288 where
2289 T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
2290 {
2291 let old_region_index = self.region_index;
136023e0
XL
2292 let (new, new_value, _) = self.name_all_regions(value)?;
2293 let mut inner = new_value.print(new)?;
532ac7d7
XL
2294 inner.region_index = old_region_index;
2295 inner.binder_depth -= 1;
2296 Ok(inner)
2297 }
2298
fc512014
XL
2299 pub fn pretty_wrap_binder<T, C: Fn(&T, Self) -> Result<Self, fmt::Error>>(
2300 self,
cdc7bbd5 2301 value: &ty::Binder<'tcx, T>,
fc512014
XL
2302 f: C,
2303 ) -> Result<Self, fmt::Error>
2304 where
2305 T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
2306 {
2307 let old_region_index = self.region_index;
136023e0
XL
2308 let (new, new_value, _) = self.name_all_regions(value)?;
2309 let mut inner = f(&new_value, new)?;
fc512014
XL
2310 inner.region_index = old_region_index;
2311 inner.binder_depth -= 1;
2312 Ok(inner)
2313 }
2314
c295e0f8 2315 #[instrument(skip(self), level = "debug")]
cdc7bbd5 2316 fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
dfeec247
XL
2317 where
2318 T: TypeFoldable<'tcx>,
532ac7d7 2319 {
cdc7bbd5
XL
2320 struct LateBoundRegionNameCollector<'a, 'tcx> {
2321 used_region_names: &'a mut FxHashSet<Symbol>,
2322 type_collector: SsoHashSet<Ty<'tcx>>,
2323 }
2324
2325 impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
2326 type BreakTy = ();
2327
c295e0f8 2328 #[instrument(skip(self), level = "trace")]
fc512014 2329 fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
5099ac24 2330 trace!("address: {:p}", r.0.0);
cdc7bbd5
XL
2331 if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
2332 self.used_region_names.insert(name);
136023e0
XL
2333 } else if let ty::RePlaceholder(ty::PlaceholderRegion {
2334 name: ty::BrNamed(_, name),
2335 ..
2336 }) = *r
2337 {
2338 self.used_region_names.insert(name);
532ac7d7
XL
2339 }
2340 r.super_visit_with(self)
2341 }
cdc7bbd5
XL
2342
2343 // We collect types in order to prevent really large types from compiling for
2344 // a really long time. See issue #83150 for why this is necessary.
c295e0f8 2345 #[instrument(skip(self), level = "trace")]
cdc7bbd5 2346 fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
cdc7bbd5
XL
2347 let not_previously_inserted = self.type_collector.insert(ty);
2348 if not_previously_inserted {
2349 ty.super_visit_with(self)
2350 } else {
2351 ControlFlow::CONTINUE
2352 }
2353 }
532ac7d7
XL
2354 }
2355
2356 self.used_region_names.clear();
cdc7bbd5
XL
2357 let mut collector = LateBoundRegionNameCollector {
2358 used_region_names: &mut self.used_region_names,
2359 type_collector: SsoHashSet::new(),
2360 };
532ac7d7
XL
2361 value.visit_with(&mut collector);
2362 self.region_index = 0;
2363 }
2364}
2365
cdc7bbd5 2366impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T>
dc9dc135
XL
2367where
2368 T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx>,
532ac7d7
XL
2369{
2370 type Output = P;
2371 type Error = P::Error;
2372 fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
2373 cx.in_binder(self)
2374 }
2375}
2376
dc9dc135
XL
2377impl<'tcx, T, U, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::OutlivesPredicate<T, U>
2378where
2379 T: Print<'tcx, P, Output = P, Error = P::Error>,
2380 U: Print<'tcx, P, Output = P, Error = P::Error>,
532ac7d7
XL
2381{
2382 type Output = P;
2383 type Error = P::Error;
2384 fn print(&self, mut cx: P) -> Result<Self::Output, Self::Error> {
2385 define_scoped_cx!(cx);
29967ef6 2386 p!(print(self.0), ": ", print(self.1));
532ac7d7
XL
2387 Ok(cx)
2388 }
2389}
2390
2391macro_rules! forward_display_to_print {
2392 ($($ty:ty),+) => {
a2a8927a
XL
2393 // Some of the $ty arguments may not actually use 'tcx
2394 $(#[allow(unused_lifetimes)] impl<'tcx> fmt::Display for $ty {
532ac7d7
XL
2395 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2396 ty::tls::with(|tcx| {
5e7ed085 2397 let cx = tcx.lift(*self)
532ac7d7 2398 .expect("could not lift for printing")
5e7ed085
FG
2399 .print(FmtPrinter::new(tcx, Namespace::TypeNS))?;
2400 f.write_str(&cx.into_buffer())?;
532ac7d7
XL
2401 Ok(())
2402 })
2403 }
2404 })+
2405 };
2406}
2407
2408macro_rules! define_print_and_forward_display {
2409 (($self:ident, $cx:ident): $($ty:ty $print:block)+) => {
dc9dc135 2410 $(impl<'tcx, P: PrettyPrinter<'tcx>> Print<'tcx, P> for $ty {
532ac7d7
XL
2411 type Output = P;
2412 type Error = fmt::Error;
2413 fn print(&$self, $cx: P) -> Result<Self::Output, Self::Error> {
2414 #[allow(unused_mut)]
2415 let mut $cx = $cx;
2416 define_scoped_cx!($cx);
2417 let _: () = $print;
2418 #[allow(unreachable_code)]
2419 Ok($cx)
2420 }
2421 })+
2422
2423 forward_display_to_print!($($ty),+);
2424 };
2425}
2426
2427// HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting.
5099ac24 2428impl<'tcx> fmt::Display for ty::Region<'tcx> {
532ac7d7
XL
2429 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2430 ty::tls::with(|tcx| {
5e7ed085 2431 f.write_str(&self.print(FmtPrinter::new(tcx, Namespace::TypeNS))?.into_buffer())
532ac7d7
XL
2432 })
2433 }
2434}
2435
60c5eb7d
XL
2436/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
2437/// the trait path. That is, it will print `Trait<U>` instead of
2438/// `<T as Trait<U>>`.
2439#[derive(Copy, Clone, TypeFoldable, Lift)]
2440pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
2441
a2a8927a 2442impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
60c5eb7d
XL
2443 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2444 fmt::Display::fmt(self, f)
2445 }
2446}
2447
c295e0f8
XL
2448/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
2449/// the trait name. That is, it will print `Trait` instead of
2450/// `<T as Trait<U>>`.
2451#[derive(Copy, Clone, TypeFoldable, Lift)]
2452pub struct TraitRefPrintOnlyTraitName<'tcx>(ty::TraitRef<'tcx>);
2453
a2a8927a 2454impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitName<'tcx> {
c295e0f8
XL
2455 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2456 fmt::Display::fmt(self, f)
2457 }
2458}
2459
a2a8927a 2460impl<'tcx> ty::TraitRef<'tcx> {
60c5eb7d
XL
2461 pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> {
2462 TraitRefPrintOnlyTraitPath(self)
2463 }
c295e0f8
XL
2464
2465 pub fn print_only_trait_name(self) -> TraitRefPrintOnlyTraitName<'tcx> {
2466 TraitRefPrintOnlyTraitName(self)
2467 }
60c5eb7d
XL
2468}
2469
a2a8927a 2470impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> {
cdc7bbd5 2471 pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> {
60c5eb7d
XL
2472 self.map_bound(|tr| tr.print_only_trait_path())
2473 }
2474}
2475
5099ac24
FG
2476#[derive(Copy, Clone, TypeFoldable, Lift)]
2477pub struct TraitPredPrintModifiersAndPath<'tcx>(ty::TraitPredicate<'tcx>);
2478
2479impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> {
2480 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2481 fmt::Display::fmt(self, f)
2482 }
2483}
2484
2485impl<'tcx> ty::TraitPredicate<'tcx> {
2486 pub fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> {
2487 TraitPredPrintModifiersAndPath(self)
2488 }
2489}
2490
2491impl<'tcx> ty::PolyTraitPredicate<'tcx> {
2492 pub fn print_modifiers_and_trait_path(
2493 self,
2494 ) -> ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>> {
2495 self.map_bound(TraitPredPrintModifiersAndPath)
2496 }
2497}
2498
532ac7d7
XL
2499forward_display_to_print! {
2500 Ty<'tcx>,
cdc7bbd5 2501 &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
5099ac24 2502 ty::Const<'tcx>,
532ac7d7
XL
2503
2504 // HACK(eddyb) these are exhaustive instead of generic,
dc9dc135 2505 // because `for<'tcx>` isn't possible yet.
cdc7bbd5
XL
2506 ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>,
2507 ty::Binder<'tcx, ty::TraitRef<'tcx>>,
dc3f5686 2508 ty::Binder<'tcx, ty::ExistentialTraitRef<'tcx>>,
cdc7bbd5 2509 ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
c295e0f8 2510 ty::Binder<'tcx, TraitRefPrintOnlyTraitName<'tcx>>,
cdc7bbd5
XL
2511 ty::Binder<'tcx, ty::FnSig<'tcx>>,
2512 ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
5099ac24 2513 ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>>,
cdc7bbd5
XL
2514 ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>,
2515 ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>,
2516 ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
2517 ty::Binder<'tcx, ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>,
532ac7d7
XL
2518
2519 ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
2520 ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
2521}
2522
2523define_print_and_forward_display! {
2524 (self, cx):
2525
2526 &'tcx ty::List<Ty<'tcx>> {
29967ef6 2527 p!("{{", comma_sep(self.iter()), "}}")
532ac7d7
XL
2528 }
2529
2530 ty::TypeAndMut<'tcx> {
60c5eb7d 2531 p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
532ac7d7
XL
2532 }
2533
2534 ty::ExistentialTraitRef<'tcx> {
2535 // Use a type that can't appear in defaults of type parameters.
48663c56 2536 let dummy_self = cx.tcx().mk_ty_infer(ty::FreshTy(0));
532ac7d7 2537 let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
60c5eb7d 2538 p!(print(trait_ref.print_only_trait_path()))
532ac7d7
XL
2539 }
2540
2541 ty::ExistentialProjection<'tcx> {
5099ac24
FG
2542 let name = cx.tcx().associated_item(self.item_def_id).name;
2543 p!(write("{} = ", name), print(self.term))
532ac7d7
XL
2544 }
2545
2546 ty::ExistentialPredicate<'tcx> {
2547 match *self {
2548 ty::ExistentialPredicate::Trait(x) => p!(print(x)),
2549 ty::ExistentialPredicate::Projection(x) => p!(print(x)),
2550 ty::ExistentialPredicate::AutoTrait(def_id) => {
2551 p!(print_def_path(def_id, &[]));
2552 }
2553 }
2554 }
2555
2556 ty::FnSig<'tcx> {
60c5eb7d 2557 p!(write("{}", self.unsafety.prefix_str()));
532ac7d7
XL
2558
2559 if self.abi != Abi::Rust {
2560 p!(write("extern {} ", self.abi));
2561 }
2562
29967ef6 2563 p!("fn", pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
532ac7d7
XL
2564 }
2565
532ac7d7 2566 ty::TraitRef<'tcx> {
60c5eb7d
XL
2567 p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
2568 }
2569
2570 TraitRefPrintOnlyTraitPath<'tcx> {
2571 p!(print_def_path(self.0.def_id, self.0.substs));
532ac7d7
XL
2572 }
2573
c295e0f8
XL
2574 TraitRefPrintOnlyTraitName<'tcx> {
2575 p!(print_def_path(self.0.def_id, &[]));
2576 }
2577
5099ac24
FG
2578 TraitPredPrintModifiersAndPath<'tcx> {
2579 if let ty::BoundConstness::ConstIfConst = self.0.constness {
2580 p!("~const ")
2581 }
2582
2583 if let ty::ImplPolarity::Negative = self.0.polarity {
2584 p!("!")
2585 }
2586
2587 p!(print(self.0.trait_ref.print_only_trait_path()));
2588 }
2589
532ac7d7
XL
2590 ty::ParamTy {
2591 p!(write("{}", self.name))
2592 }
2593
2594 ty::ParamConst {
2595 p!(write("{}", self.name))
2596 }
2597
2598 ty::SubtypePredicate<'tcx> {
29967ef6 2599 p!(print(self.a), " <: ", print(self.b))
532ac7d7
XL
2600 }
2601
94222f64
XL
2602 ty::CoercePredicate<'tcx> {
2603 p!(print(self.a), " -> ", print(self.b))
2604 }
2605
532ac7d7 2606 ty::TraitPredicate<'tcx> {
5099ac24
FG
2607 p!(print(self.trait_ref.self_ty()), ": ");
2608 if let ty::BoundConstness::ConstIfConst = self.constness {
2609 p!("~const ");
2610 }
2611 p!(print(self.trait_ref.print_only_trait_path()))
532ac7d7
XL
2612 }
2613
2614 ty::ProjectionPredicate<'tcx> {
5099ac24
FG
2615 p!(print(self.projection_ty), " == ", print(self.term))
2616 }
2617
2618 ty::Term<'tcx> {
2619 match self {
2620 ty::Term::Ty(ty) => p!(print(ty)),
2621 ty::Term::Const(c) => p!(print(c)),
2622 }
532ac7d7
XL
2623 }
2624
2625 ty::ProjectionTy<'tcx> {
2626 p!(print_def_path(self.item_def_id, self.substs));
2627 }
2628
2629 ty::ClosureKind {
2630 match *self {
29967ef6
XL
2631 ty::ClosureKind::Fn => p!("Fn"),
2632 ty::ClosureKind::FnMut => p!("FnMut"),
2633 ty::ClosureKind::FnOnce => p!("FnOnce"),
532ac7d7
XL
2634 }
2635 }
2636
2637 ty::Predicate<'tcx> {
5869c6ff
XL
2638 let binder = self.kind();
2639 p!(print(binder))
3dfed10e
XL
2640 }
2641
5869c6ff 2642 ty::PredicateKind<'tcx> {
3dfed10e 2643 match *self {
94222f64 2644 ty::PredicateKind::Trait(ref data) => {
dfeec247
XL
2645 p!(print(data))
2646 }
5869c6ff 2647 ty::PredicateKind::Subtype(predicate) => p!(print(predicate)),
94222f64 2648 ty::PredicateKind::Coerce(predicate) => p!(print(predicate)),
5869c6ff
XL
2649 ty::PredicateKind::RegionOutlives(predicate) => p!(print(predicate)),
2650 ty::PredicateKind::TypeOutlives(predicate) => p!(print(predicate)),
2651 ty::PredicateKind::Projection(predicate) => p!(print(predicate)),
2652 ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"),
2653 ty::PredicateKind::ObjectSafe(trait_def_id) => {
29967ef6 2654 p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
532ac7d7 2655 }
5869c6ff 2656 ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => {
29967ef6 2657 p!("the closure `",
3dfed10e
XL
2658 print_value_path(closure_def_id, &[]),
2659 write("` implements the trait `{}`", kind))
532ac7d7 2660 }
94222f64 2661 ty::PredicateKind::ConstEvaluatable(uv) => {
5099ac24 2662 p!("the constant `", print_value_path(uv.def.did, uv.substs), "` can be evaluated")
532ac7d7 2663 }
5869c6ff 2664 ty::PredicateKind::ConstEquate(c1, c2) => {
29967ef6 2665 p!("the constant `", print(c1), "` equals `", print(c2), "`")
f9f354fc 2666 }
5869c6ff 2667 ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
29967ef6 2668 p!("the type `", print(ty), "` is found in the environment")
1b1a35ee 2669 }
532ac7d7
XL
2670 }
2671 }
2672
e74abb32 2673 GenericArg<'tcx> {
532ac7d7 2674 match self.unpack() {
e74abb32
XL
2675 GenericArgKind::Lifetime(lt) => p!(print(lt)),
2676 GenericArgKind::Type(ty) => p!(print(ty)),
2677 GenericArgKind::Const(ct) => p!(print(ct)),
532ac7d7
XL
2678 }
2679 }
2680}
1b1a35ee
XL
2681
2682fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) {
2683 // Iterate all local crate items no matter where they are defined.
2684 let hir = tcx.hir();
c295e0f8 2685 for item in hir.items() {
1b1a35ee
XL
2686 if item.ident.name.as_str().is_empty() || matches!(item.kind, ItemKind::Use(_, _)) {
2687 continue;
2688 }
2689
6a06907d
XL
2690 let def_id = item.def_id.to_def_id();
2691 let ns = tcx.def_kind(def_id).ns().unwrap_or(Namespace::TypeNS);
2692 collect_fn(&item.ident, ns, def_id);
1b1a35ee
XL
2693 }
2694
2695 // Now take care of extern crate items.
2696 let queue = &mut Vec::new();
2697 let mut seen_defs: DefIdSet = Default::default();
2698
136023e0 2699 for &cnum in tcx.crates(()).iter() {
1b1a35ee
XL
2700 let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
2701
2702 // Ignore crates that are not direct dependencies.
2703 match tcx.extern_crate(def_id) {
2704 None => continue,
2705 Some(extern_crate) => {
2706 if !extern_crate.is_direct() {
2707 continue;
2708 }
2709 }
2710 }
2711
2712 queue.push(def_id);
2713 }
2714
2715 // Iterate external crate defs but be mindful about visibility
2716 while let Some(def) = queue.pop() {
5099ac24 2717 for child in tcx.module_children(def).iter() {
3c0e092e 2718 if !child.vis.is_public() {
1b1a35ee
XL
2719 continue;
2720 }
2721
2722 match child.res {
2723 def::Res::Def(DefKind::AssocTy, _) => {}
6a06907d 2724 def::Res::Def(DefKind::TyAlias, _) => {}
1b1a35ee
XL
2725 def::Res::Def(defkind, def_id) => {
2726 if let Some(ns) = defkind.ns() {
2727 collect_fn(&child.ident, ns, def_id);
2728 }
2729
5099ac24
FG
2730 if matches!(defkind, DefKind::Mod | DefKind::Enum | DefKind::Trait)
2731 && seen_defs.insert(def_id)
2732 {
1b1a35ee
XL
2733 queue.push(def_id);
2734 }
2735 }
2736 _ => {}
2737 }
2738 }
2739 }
2740}
2741
2742/// The purpose of this function is to collect public symbols names that are unique across all
2743/// crates in the build. Later, when printing about types we can use those names instead of the
2744/// full exported path to them.
2745///
2746/// So essentially, if a symbol name can only be imported from one place for a type, and as
2747/// long as it was not glob-imported anywhere in the current crate, we can trim its printed
2748/// path and print only the name.
2749///
2750/// This has wide implications on error messages with types, for example, shortening
2751/// `std::vec::Vec` to just `Vec`, as long as there is no other `Vec` importable anywhere.
2752///
2753/// The implementation uses similar import discovery logic to that of 'use' suggestions.
17df50a5 2754fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
c295e0f8 2755 let mut map: FxHashMap<DefId, Symbol> = FxHashMap::default();
1b1a35ee
XL
2756
2757 if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths {
2758 // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
2759 // wrapper can be used to suppress this query, in exchange for full paths being formatted.
2760 tcx.sess.delay_good_path_bug("trimmed_def_paths constructed");
2761 }
2762
2763 let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
2764 &mut FxHashMap::default();
2765
136023e0 2766 for symbol_set in tcx.resolutions(()).glob_map.values() {
1b1a35ee
XL
2767 for symbol in symbol_set {
2768 unique_symbols_rev.insert((Namespace::TypeNS, *symbol), None);
2769 unique_symbols_rev.insert((Namespace::ValueNS, *symbol), None);
2770 unique_symbols_rev.insert((Namespace::MacroNS, *symbol), None);
2771 }
2772 }
2773
2774 for_each_def(tcx, |ident, ns, def_id| {
2775 use std::collections::hash_map::Entry::{Occupied, Vacant};
2776
2777 match unique_symbols_rev.entry((ns, ident.name)) {
2778 Occupied(mut v) => match v.get() {
2779 None => {}
2780 Some(existing) => {
2781 if *existing != def_id {
2782 v.insert(None);
2783 }
2784 }
2785 },
2786 Vacant(v) => {
2787 v.insert(Some(def_id));
2788 }
2789 }
2790 });
2791
2792 for ((_, symbol), opt_def_id) in unique_symbols_rev.drain() {
c295e0f8
XL
2793 use std::collections::hash_map::Entry::{Occupied, Vacant};
2794
1b1a35ee 2795 if let Some(def_id) = opt_def_id {
c295e0f8
XL
2796 match map.entry(def_id) {
2797 Occupied(mut v) => {
2798 // A single DefId can be known under multiple names (e.g.,
2799 // with a `pub use ... as ...;`). We need to ensure that the
2800 // name placed in this map is chosen deterministically, so
2801 // if we find multiple names (`symbol`) resolving to the
2802 // same `def_id`, we prefer the lexicographically smallest
2803 // name.
2804 //
2805 // Any stable ordering would be fine here though.
2806 if *v.get() != symbol {
2807 if v.get().as_str() > symbol.as_str() {
2808 v.insert(symbol);
2809 }
2810 }
2811 }
2812 Vacant(v) => {
2813 v.insert(symbol);
2814 }
2815 }
1b1a35ee
XL
2816 }
2817 }
2818
2819 map
2820}
2821
2822pub fn provide(providers: &mut ty::query::Providers) {
2823 *providers = ty::query::Providers { trimmed_def_paths, ..*providers };
2824}
3c0e092e
XL
2825
2826#[derive(Default)]
2827pub struct OpaqueFnEntry<'tcx> {
2828 // The trait ref is already stored as a key, so just track if we have it as a real predicate
2829 has_fn_once: bool,
2830 fn_mut_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
2831 fn_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
5099ac24 2832 return_ty: Option<ty::Binder<'tcx, Term<'tcx>>>,
3c0e092e 2833}