use crate::hir::def::Namespace;
use crate::hir::map::DefPathData;
use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use crate::middle::region;
use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind};
use crate::middle::cstore::{ExternCrate, ExternCrateSource};
/// This is used when you have a signature like `fn foo(x: &u32,
/// y: &'a u32)` and we want to give a name to the region of the
/// reference `x`.
- pub(crate) highlight_bound_region: Option<(ty::BoundRegion, usize)>,
+ highlight_bound_region: Option<(ty::BoundRegion, usize)>,
}
impl RegionHighlightMode {
}
/// Returns `Some(n)` with the number to use for the given region, if any.
- pub(crate) fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
+ fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
self
.highlight_regions
.iter()
type Error;
type Path;
+ type Region;
fn print_def_path(
self: PrintCx<'_, '_, 'tcx, Self>,
self.default_print_impl_path(impl_def_id, substs, ns, self_ty, trait_ref)
}
+ fn print_region(
+ self: PrintCx<'_, '_, '_, Self>,
+ region: ty::Region<'_>,
+ ) -> Result<Self::Region, Self::Error>;
+
fn path_crate(
self: PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
}
/// Trait for printers that pretty-print using `fmt::Write` to the printer.
-pub trait PrettyPrinter: Printer<Error = fmt::Error, Path = Self> + fmt::Write {
+pub trait PrettyPrinter: Printer<Error = fmt::Error, Path = Self, Region = Self> + fmt::Write {
/// Enter a nested print context, for pretty-printing
/// nested components in some larger context.
fn nest<'a, 'gcx, 'tcx, E>(
})
}
- fn region_highlight_mode(&self) -> RegionHighlightMode {
- RegionHighlightMode::default()
+ /// Return `true` if the region should be printed in path generic args
+ /// even when it's `'_`, such as in e.g. `Foo<'_, '_, '_>`.
+ fn always_print_region_in_paths(
+ self: &PrintCx<'_, '_, '_, Self>,
+ _region: ty::Region<'_>,
+ ) -> bool {
+ false
}
+
+ // HACK(eddyb) Trying to print a lifetime might not print anything, which
+ // may need special handling in the caller (of `ty::RegionKind::print`).
+ // To avoid printing to a temporary string (which isn't even supported),
+ // the `print_region_outputs_anything` method can instead be used to
+ // determine this, ahead of time.
+ //
+ // NB: this must be kept in sync with the implementation of `print_region`.
+ fn print_region_outputs_anything(
+ self: &PrintCx<'_, '_, '_, Self>,
+ region: ty::Region<'_>,
+ ) -> bool;
}
macro_rules! nest {
let start = if ns == Namespace::ValueNS { "::<" } else { "<" };
- // Don't print any regions if they're all erased.
+ // Don't print `'_` if there's no printed region.
let print_regions = params.iter().any(|param| {
match substs[param.index as usize].unpack() {
- UnpackedKind::Lifetime(r) => *r != ty::ReErased,
+ UnpackedKind::Lifetime(r) => {
+ self.always_print_region_in_paths(r) ||
+ self.print_region_outputs_anything(r)
+ }
_ => false,
}
});
continue;
}
start_or_continue(&mut self, start, ", ")?;
- if !region.display_outputs_anything(&self) {
+ if !self.print_region_outputs_anything(region) {
// This happens when the value of the region
// parameter is not easily serialized. This may be
// because the user omitted it in the first place,
type Error = fmt::Error;
type Path = Self;
+ type Region = Self;
fn print_def_path(
mut self: PrintCx<'_, '_, 'tcx, Self>,
self.default_print_def_path(def_id, substs, ns, projections)
}
+ fn print_region(
+ mut self: PrintCx<'_, '_, '_, Self>,
+ region: ty::Region<'_>,
+ ) -> Result<Self::Region, Self::Error> {
+ // Watch out for region highlights.
+ let highlight = self.printer.region_highlight_mode;
+ if let Some(n) = highlight.region_highlighted(region) {
+ write!(self.printer, "'{}", n)?;
+ return Ok(self.printer);
+ }
+
+ if self.config.is_verbose {
+ return region.print_debug(self);
+ }
+
+ // These printouts are concise. They do not contain all the information
+ // the user might want to diagnose an error, but there is basically no way
+ // to fit that into a short string. Hence the recommendation to use
+ // `explain_region()` or `note_and_explain_region()`.
+ match *region {
+ ty::ReEarlyBound(ref data) => {
+ if data.name != "'_" {
+ write!(self.printer, "{}", data.name)?;
+ }
+ }
+ ty::ReLateBound(_, br) |
+ ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
+ ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+ if let ty::BrNamed(_, name) = br {
+ if name != "" && name != "'_" {
+ write!(self.printer, "{}", name)?;
+ return Ok(self.printer);
+ }
+ }
+
+ if let Some((region, counter)) = highlight.highlight_bound_region {
+ if br == region {
+ write!(self.printer, "'{}", counter)?;
+ }
+ }
+ }
+ ty::ReScope(scope) if self.config.identify_regions => {
+ match scope.data {
+ region::ScopeData::Node =>
+ write!(self.printer, "'{}s", scope.item_local_id().as_usize())?,
+ region::ScopeData::CallSite =>
+ write!(self.printer, "'{}cs", scope.item_local_id().as_usize())?,
+ region::ScopeData::Arguments =>
+ write!(self.printer, "'{}as", scope.item_local_id().as_usize())?,
+ region::ScopeData::Destruction =>
+ write!(self.printer, "'{}ds", scope.item_local_id().as_usize())?,
+ region::ScopeData::Remainder(first_statement_index) => write!(self.printer,
+ "'{}_{}rs",
+ scope.item_local_id().as_usize(),
+ first_statement_index.index()
+ )?,
+ }
+ }
+ ty::ReVar(region_vid) if self.config.identify_regions => {
+ write!(self.printer, "{:?}", region_vid)?;
+ }
+ ty::ReVar(_) => {}
+ ty::ReScope(_) |
+ ty::ReErased => {}
+ ty::ReStatic => write!(self.printer, "'static")?,
+ ty::ReEmpty => write!(self.printer, "'<empty>")?,
+
+ // The user should never encounter these in unsubstituted form.
+ ty::ReClosureBound(vid) => write!(self.printer, "{:?}", vid)?,
+ }
+
+ Ok(self.printer)
+ }
+
fn path_crate(
mut self: PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
})
}
- fn region_highlight_mode(&self) -> RegionHighlightMode {
- self.region_highlight_mode
+ fn always_print_region_in_paths(
+ self: &PrintCx<'_, '_, '_, Self>,
+ region: ty::Region<'_>,
+ ) -> bool {
+ *region != ty::ReErased
+ }
+
+ fn print_region_outputs_anything(
+ self: &PrintCx<'_, '_, '_, Self>,
+ region: ty::Region<'_>,
+ ) -> bool {
+ let highlight = self.printer.region_highlight_mode;
+ if highlight.region_highlighted(region).is_some() {
+ return true;
+ }
+
+ if self.config.is_verbose {
+ return true;
+ }
+
+ match *region {
+ ty::ReEarlyBound(ref data) => {
+ data.name != "" && data.name != "'_"
+ }
+
+ ty::ReLateBound(_, br) |
+ ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
+ ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+ if let ty::BrNamed(_, name) = br {
+ if name != "" && name != "'_" {
+ return true;
+ }
+ }
+
+ if let Some((region, _)) = highlight.highlight_bound_region {
+ if br == region {
+ return true;
+ }
+ }
+
+ false
+ }
+
+ ty::ReScope(_) |
+ ty::ReVar(_) if self.config.identify_regions => true,
+
+ ty::ReVar(_) |
+ ty::ReScope(_) |
+ ty::ReErased => false,
+
+ ty::ReStatic |
+ ty::ReEmpty |
+ ty::ReClosureBound(_) => true,
+ }
}
}
use crate::hir::def::Namespace;
use crate::hir::def_id::DefId;
-use crate::middle::region;
use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind};
use crate::ty::{Bool, Char, Adt};
use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
define_print! {
() ty::RegionKind, (self, cx) {
display {
- // Watch out for region highlights.
- let highlight = cx.printer.region_highlight_mode();
- if let Some(n) = highlight.region_highlighted(self) {
- p!(write("'{}", n));
- return Ok(cx.printer);
- }
-
- if cx.config.is_verbose {
- return self.print_debug(cx);
- }
-
- // These printouts are concise. They do not contain all the information
- // the user might want to diagnose an error, but there is basically no way
- // to fit that into a short string. Hence the recommendation to use
- // `explain_region()` or `note_and_explain_region()`.
- match *self {
- ty::ReEarlyBound(ref data) => {
- if data.name != "'_" {
- p!(write("{}", data.name))
- }
- }
- ty::ReLateBound(_, br) |
- ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
- ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
- if let ty::BrNamed(_, name) = br {
- if name != "" && name != "'_" {
- p!(write("{}", name));
- return Ok(cx.printer);
- }
- }
-
- if let Some((region, counter)) = highlight.highlight_bound_region {
- if br == region {
- p!(write("'{}", counter));
- }
- }
- }
- ty::ReScope(scope) if cx.config.identify_regions => {
- match scope.data {
- region::ScopeData::Node =>
- p!(write("'{}s", scope.item_local_id().as_usize())),
- region::ScopeData::CallSite =>
- p!(write("'{}cs", scope.item_local_id().as_usize())),
- region::ScopeData::Arguments =>
- p!(write("'{}as", scope.item_local_id().as_usize())),
- region::ScopeData::Destruction =>
- p!(write("'{}ds", scope.item_local_id().as_usize())),
- region::ScopeData::Remainder(first_statement_index) => p!(write(
- "'{}_{}rs",
- scope.item_local_id().as_usize(),
- first_statement_index.index()
- )),
- }
- }
- ty::ReVar(region_vid) if cx.config.identify_regions => {
- p!(write("{:?}", region_vid));
- }
- ty::ReVar(_) => {}
- ty::ReScope(_) |
- ty::ReErased => {}
- ty::ReStatic => p!(write("'static")),
- ty::ReEmpty => p!(write("'<empty>")),
-
- // The user should never encounter these in unsubstituted form.
- ty::ReClosureBound(vid) => p!(write("{:?}", vid)),
- }
+ return cx.print_region(self);
}
debug {
match *self {
}
}
-// HACK(eddyb) Trying to print a lifetime might not print anything, which
-// may need special handling in the caller (of `ty::RegionKind::print`).
-// To avoid printing to a temporary string, the `display_outputs_anything`
-// method can instead be used to determine this, ahead of time.
-//
-// NB: this must be kept in sync with the printing logic above.
-impl ty::RegionKind {
- // HACK(eddyb) `pub(crate)` only for `ty::print`.
- pub(crate) fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool
- where P: PrettyPrinter
- {
- let highlight = cx.printer.region_highlight_mode();
- if highlight.region_highlighted(self).is_some() {
- return true;
- }
-
- if cx.config.is_verbose {
- return true;
- }
-
- match *self {
- ty::ReEarlyBound(ref data) => {
- data.name != "" && data.name != "'_"
- }
-
- ty::ReLateBound(_, br) |
- ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
- ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
- if let ty::BrNamed(_, name) = br {
- if name != "" && name != "'_" {
- return true;
- }
- }
-
- if let Some((region, _)) = highlight.highlight_bound_region {
- if br == region {
- return true;
- }
- }
-
- false
- }
-
- ty::ReScope(_) |
- ty::ReVar(_) if cx.config.identify_regions => true,
-
- ty::ReVar(_) |
- ty::ReScope(_) |
- ty::ReErased => false,
-
- ty::ReStatic |
- ty::ReEmpty |
- ty::ReClosureBound(_) => true,
- }
- }
-}
-
define_print! {
() ty::FreeRegion, (self, cx) {
debug {
}
Ref(r, ty, mutbl) => {
p!(write("&"));
- if r.display_outputs_anything(&cx) {
+ if cx.print_region_outputs_anything(r) {
p!(print_display(r), write(" "));
}
p!(print(ty::TypeAndMut { ty, mutbl }))
));
}
Dynamic(data, r) => {
- let print_r = r.display_outputs_anything(&cx);
+ let print_r = cx.print_region_outputs_anything(r);
if print_r {
p!(write("("));
}