X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_middle%2Fsrc%2Fty%2Fprint%2Fpretty.rs;h=a741c4cb32e98745bd95276609384aa45e8606cd;hb=976348603485b216b0d5314eca674a2b24df4c73;hp=6521957ec944c36b9b26a7fdbe31fa530666a5c0;hpb=54ecec9b7a0754077725081ef326646d95a8d954;p=rust.git diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6521957ec94..a741c4cb32e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3,6 +3,7 @@ use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::ieee::{Double, Single}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::intern::Interned; use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; @@ -62,66 +63,59 @@ macro_rules! scoped_cx { static NO_VISIBLE_PATH: Cell = const { Cell::new(false) }; } -/// Avoids running any queries during any prints that occur -/// during the closure. This may alter the appearance of some -/// types (e.g. forcing verbose printing for opaque types). -/// This method is used during some queries (e.g. `explicit_item_bounds` -/// for opaque types), to ensure that any debug printing that -/// occurs during the query computation does not end up recursively -/// calling the same query. -pub fn with_no_queries R, R>(f: F) -> R { - NO_QUERIES.with(|no_queries| { - let old = no_queries.replace(true); - let result = f(); - no_queries.set(old); - result - }) -} +macro_rules! define_helper { + ($($(#[$a:meta])* fn $name:ident($helper:ident, $tl:ident);)+) => { + $( + #[must_use] + pub struct $helper(bool); -/// Force us to name impls with just the filename/line number. We -/// normally try to use types. But at some points, notably while printing -/// cycle errors, this can result in extra or suboptimal error output, -/// so this variable disables that check. -pub fn with_forced_impl_filename_line R, R>(f: F) -> R { - FORCE_IMPL_FILENAME_LINE.with(|force| { - let old = force.replace(true); - let result = f(); - force.set(old); - result - }) -} + impl $helper { + pub fn new() -> $helper { + $helper($tl.with(|c| c.replace(true))) + } + } -/// Adds the `crate::` prefix to paths where appropriate. -pub fn with_crate_prefix R, R>(f: F) -> R { - SHOULD_PREFIX_WITH_CRATE.with(|flag| { - let old = flag.replace(true); - let result = f(); - flag.set(old); - result - }) -} + $(#[$a])* + pub macro $name($e:expr) { + { + let _guard = $helper::new(); + $e + } + } -/// Prevent path trimming if it is turned on. Path trimming affects `Display` impl -/// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`, -/// if no other `Vec` is found. -pub fn with_no_trimmed_paths R, R>(f: F) -> R { - NO_TRIMMED_PATH.with(|flag| { - let old = flag.replace(true); - let result = f(); - flag.set(old); - result - }) + impl Drop for $helper { + fn drop(&mut self) { + $tl.with(|c| c.set(self.0)) + } + } + )+ + } } -/// Prevent selection of visible paths. `Display` impl of DefId will prefer visible (public) reexports of types as paths. -pub fn with_no_visible_paths R, R>(f: F) -> R { - NO_VISIBLE_PATH.with(|flag| { - let old = flag.replace(true); - let result = f(); - flag.set(old); - result - }) -} +define_helper!( + /// Avoids running any queries during any prints that occur + /// during the closure. This may alter the appearance of some + /// types (e.g. forcing verbose printing for opaque types). + /// This method is used during some queries (e.g. `explicit_item_bounds` + /// for opaque types), to ensure that any debug printing that + /// occurs during the query computation does not end up recursively + /// calling the same query. + fn with_no_queries(NoQueriesGuard, NO_QUERIES); + /// Force us to name impls with just the filename/line number. We + /// normally try to use types. But at some points, notably while printing + /// cycle errors, this can result in extra or suboptimal error output, + /// so this variable disables that check. + fn with_forced_impl_filename_line(ForcedImplGuard, FORCE_IMPL_FILENAME_LINE); + /// Adds the `crate::` prefix to paths where appropriate. + fn with_crate_prefix(CratePrefixGuard, SHOULD_PREFIX_WITH_CRATE); + /// Prevent path trimming if it is turned on. Path trimming affects `Display` impl + /// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`, + /// if no other `Vec` is found. + fn with_no_trimmed_paths(NoTrimmedGuard, NO_TRIMMED_PATH); + /// Prevent selection of visible paths. `Display` impl of DefId will prefer + /// visible (public) reexports of types as paths. + fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH); +); /// The "region highlights" are used to control region printing during /// specific error messages. When a "region highlight" is enabled, it @@ -130,11 +124,13 @@ pub fn with_no_visible_paths R, R>(f: F) -> R { /// /// Regions not selected by the region highlight mode are presently /// unaffected. -#[derive(Copy, Clone, Default)] -pub struct RegionHighlightMode { +#[derive(Copy, Clone)] +pub struct RegionHighlightMode<'tcx> { + tcx: TyCtxt<'tcx>, + /// If enabled, when we see the selected region, use "`'N`" /// instead of the ordinary behavior. - highlight_regions: [Option<(ty::RegionKind, usize)>; 3], + highlight_regions: [Option<(ty::Region<'tcx>, usize)>; 3], /// If enabled, when printing a "free region" that originated from /// the given `ty::BoundRegionKind`, print it as "`'1`". Free regions that would ordinarily @@ -146,12 +142,20 @@ pub struct RegionHighlightMode { highlight_bound_region: Option<(ty::BoundRegionKind, usize)>, } -impl RegionHighlightMode { +impl<'tcx> RegionHighlightMode<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>) -> Self { + Self { + tcx, + highlight_regions: Default::default(), + highlight_bound_region: Default::default(), + } + } + /// If `region` and `number` are both `Some`, invokes /// `highlighting_region`. pub fn maybe_highlighting_region( &mut self, - region: Option>, + region: Option>, number: Option, ) { if let Some(k) = region { @@ -162,24 +166,24 @@ pub fn maybe_highlighting_region( } /// Highlights the region inference variable `vid` as `'N`. - pub fn highlighting_region(&mut self, region: ty::Region<'_>, number: usize) { + pub fn highlighting_region(&mut self, region: ty::Region<'tcx>, number: usize) { let num_slots = self.highlight_regions.len(); let first_avail_slot = self.highlight_regions.iter_mut().find(|s| s.is_none()).unwrap_or_else(|| { bug!("can only highlight {} placeholders at a time", num_slots,) }); - *first_avail_slot = Some((*region, number)); + *first_avail_slot = Some((region, number)); } /// Convenience wrapper for `highlighting_region`. pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) { - self.highlighting_region(&ty::ReVar(vid), number) + self.highlighting_region(self.tcx.mk_region(ty::ReVar(vid)), number) } /// Returns `Some(n)` with the number to use for the given region, if any. fn region_highlighted(&self, region: ty::Region<'_>) -> Option { self.highlight_regions.iter().find_map(|h| match h { - Some((r, n)) if r == region => Some(*n), + Some((r, n)) if *r == region => Some(*n), _ => None, }) } @@ -368,7 +372,7 @@ fn try_print_visible_def_path_recur( // in cases where the `extern crate foo` has non-trivial // parents, e.g. it's nested in `impl foo::Trait for Bar` // (see also issues #55779 and #87932). - self = with_no_visible_paths(|| self.print_def_path(def_id, &[]))?; + self = with_no_visible_paths!(self.print_def_path(def_id, &[])?); return Ok((self, true)); } @@ -644,23 +648,20 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result return Ok(self); } - let parent = self.tcx().parent(def_id).expect("opaque types always have a parent"); - match self.tcx().def_kind(parent) { - DefKind::TyAlias | DefKind::AssocTy => { - if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() { - if d == def_id { - // If the type alias directly starts with the `impl` of the - // opaque type we're printing, then skip the `::{opaque#1}`. - p!(print_def_path(parent, substs)); - return Ok(self); - } + return with_no_queries!({ + let def_key = self.tcx().def_key(def_id); + if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { + p!(write("{}", name)); + // FIXME(eddyb) print this with `print_def_path`. + if !substs.is_empty() { + p!("::"); + p!(generic_delimiters(|cx| cx.comma_sep(substs.iter()))); } - // Complex opaque type, e.g. `type Foo = (i32, impl Debug);` - p!(print_def_path(def_id, substs)); return Ok(self); } - _ => return self.pretty_print_opaque_impl_type(def_id, substs), - } + + self.pretty_print_opaque_impl_type(def_id, substs) + }); } ty::Str => p!("str"), ty::Generator(did, substs, movability) => { @@ -746,14 +747,14 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result p!("[", print(ty), "; "); if self.tcx().sess.verbose() { p!(write("{:?}", sz)); - } else if let ty::ConstKind::Unevaluated(..) = sz.val { + } else if let ty::ConstKind::Unevaluated(..) = sz.val() { // Do not try to evaluate unevaluated constants. If we are const evaluating an // array length anon const, rustc will (with debug assertions) print the // constant's path. Which will end up here again. p!("_"); - } else if let Some(n) = sz.val.try_to_bits(self.tcx().data_layout.pointer_size) { + } else if let Some(n) = sz.val().try_to_bits(self.tcx().data_layout.pointer_size) { p!(write("{}", n)); - } else if let ty::ConstKind::Param(param) = sz.val { + } else if let ty::ConstKind::Param(param) = sz.val() { p!(write("{}", param)); } else { p!("_"); @@ -1056,7 +1057,7 @@ fn pretty_print_dyn_existential( // Don't print `'_` if there's no unerased regions. let print_regions = args.iter().any(|arg| match arg.unpack() { - GenericArgKind::Lifetime(r) => *r != ty::ReErased, + GenericArgKind::Lifetime(r) => !r.is_erased(), _ => false, }); let mut args = args.iter().cloned().filter(|arg| match arg.unpack() { @@ -1140,13 +1141,13 @@ fn pretty_fn_sig( fn pretty_print_const( mut self, - ct: &'tcx ty::Const<'tcx>, + ct: ty::Const<'tcx>, print_ty: bool, ) -> Result { define_scoped_cx!(self); if self.tcx().sess.verbose() { - p!(write("Const({:?}: {:?})", ct.val, ct.ty)); + p!(write("Const({:?}: {:?})", ct.val(), ct.ty())); return Ok(self); } @@ -1158,7 +1159,7 @@ macro_rules! print_underscore { write!(this, "_")?; Ok(this) }, - |this| this.print_type(ct.ty), + |this| this.print_type(ct.ty()), ": ", )?; } else { @@ -1167,7 +1168,7 @@ macro_rules! print_underscore { }}; } - match ct.val { + match ct.val() { ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, @@ -1198,7 +1199,7 @@ macro_rules! print_underscore { ty::ConstKind::Infer(..) => print_underscore!(), ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)), ty::ConstKind::Value(value) => { - return self.pretty_print_const_value(value, ct.ty, print_ty); + return self.pretty_print_const_value(value, ct.ty(), print_ty); } ty::ConstKind::Bound(debruijn, bound_var) => { @@ -1235,16 +1236,23 @@ fn pretty_print_const_scalar_ptr( // Byte strings (&[u8; N]) ty::Ref( _, - ty::TyS { - kind: - ty::Array( - ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. }, - ty::Const { - val: ty::ConstKind::Value(ConstValue::Scalar(int)), .. - }, - ), - .. - }, + Ty(Interned( + ty::TyS { + kind: + ty::Array( + Ty(Interned(ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. }, _)), + ty::Const(Interned( + ty::ConstS { + val: ty::ConstKind::Value(ConstValue::Scalar(int)), + .. + }, + _, + )), + ), + .. + }, + _, + )), _, ) => match self.tcx().get_global_alloc(alloc_id) { Some(GlobalAlloc::Memory(alloc)) => { @@ -1402,7 +1410,7 @@ fn pretty_print_const_value( // Byte/string slices, printed as (byte) string literals. ( ConstValue::Slice { data, start, end }, - ty::Ref(_, ty::TyS { kind: ty::Slice(t), .. }, _), + ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Slice(t), .. }, _)), _), ) if *t == u8_type => { // The `inspect` here is okay since we checked the bounds, and there are // no relocations (we have an active slice reference here). We don't use @@ -1412,7 +1420,7 @@ fn pretty_print_const_value( } ( ConstValue::Slice { data, start, end }, - ty::Ref(_, ty::TyS { kind: ty::Str, .. }, _), + ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Str, .. }, _)), _), ) => { // The `inspect` here is okay since we checked the bounds, and there are no // relocations (we have an active `str` reference here). We don't use this @@ -1423,7 +1431,7 @@ fn pretty_print_const_value( Ok(self) } (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { - let n = n.val.try_to_bits(self.tcx().data_layout.pointer_size).unwrap(); + let n = n.val().try_to_bits(self.tcx().data_layout.pointer_size).unwrap(); // cast is ok because we already checked for pointer size (32 or 64 bit) above let range = AllocRange { start: offset, size: Size::from_bytes(n) }; @@ -1444,10 +1452,10 @@ fn pretty_print_const_value( // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the // correct `ty::ParamEnv` to allow printing *all* constant values. (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => { - let contents = self.tcx().destructure_const( - ty::ParamEnv::reveal_all() - .and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })), - ); + let contents = + self.tcx().destructure_const(ty::ParamEnv::reveal_all().and( + self.tcx().mk_const(ty::ConstS { val: ty::ConstKind::Value(ct), ty }), + )); let fields = contents.fields.iter().copied(); match *ty.kind() { @@ -1534,7 +1542,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> { binder_depth: usize, printed_type_count: usize, - pub region_highlight_mode: RegionHighlightMode, + pub region_highlight_mode: RegionHighlightMode<'tcx>, pub name_resolver: Option Option>>, } @@ -1564,7 +1572,7 @@ pub fn new(tcx: TyCtxt<'tcx>, fmt: F, ns: Namespace) -> Self { region_index: 0, binder_depth: 0, printed_type_count: 0, - region_highlight_mode: RegionHighlightMode::default(), + region_highlight_mode: RegionHighlightMode::new(tcx), name_resolver: None, })) } @@ -1705,7 +1713,7 @@ fn print_dyn_existential( self.pretty_print_dyn_existential(predicates) } - fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result { + fn print_const(self, ct: ty::Const<'tcx>) -> Result { self.pretty_print_const(ct, true) } @@ -1800,7 +1808,7 @@ fn path_generic_args( // Don't print `'_` if there's no unerased regions. let print_regions = self.tcx.sess.verbose() || args.iter().any(|arg| match arg.unpack() { - GenericArgKind::Lifetime(r) => *r != ty::ReErased, + GenericArgKind::Lifetime(r) => !r.is_erased(), _ => false, }); let args = args.iter().cloned().filter(|arg| match arg.unpack() { @@ -2059,7 +2067,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { let name = &mut self.name; let region = match *r { - ty::ReLateBound(_, br) => self.region_map.entry(br).or_insert_with(|| name(br)), + ty::ReLateBound(_, br) => *self.region_map.entry(br).or_insert_with(|| name(br)), ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => { // If this is an anonymous placeholder, don't rename. Otherwise, in some // async fns, we get a `for<'r> Send` bound @@ -2068,7 +2076,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { _ => { // Index doesn't matter, since this is just for naming and these never get bound let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind }; - self.region_map.entry(br).or_insert_with(|| name(br)) + *self.region_map.entry(br).or_insert_with(|| name(br)) } } } @@ -2270,7 +2278,7 @@ impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx #[instrument(skip(self), level = "trace")] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - trace!("address: {:p}", r); + trace!("address: {:p}", r.0.0); if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r { self.used_region_names.insert(name); } else if let ty::RePlaceholder(ty::PlaceholderRegion { @@ -2367,7 +2375,7 @@ fn print(&$self, $cx: P) -> Result { } // HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting. -impl fmt::Display for ty::RegionKind { +impl<'tcx> fmt::Display for ty::Region<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { self.print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?; @@ -2442,7 +2450,7 @@ pub fn print_modifiers_and_trait_path( forward_display_to_print! { Ty<'tcx>, &'tcx ty::List>>, - &'tcx ty::Const<'tcx>, + ty::Const<'tcx>, // HACK(eddyb) these are exhaustive instead of generic, // because `for<'tcx>` isn't possible yet. @@ -2610,9 +2618,6 @@ pub fn print_modifiers_and_trait_path( ty::PredicateKind::TypeWellFormedFromEnv(ty) => { p!("the type `", print(ty), "` is found in the environment") } - ty::PredicateKind::OpaqueType(a, b) => { - p!("opaque type assigment with `", print(a), "` == `", print(b) ,"`") - } } }