Skip to content

Always format to internal String in FmtPrinter #94131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,8 +488,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Return the name of the provided `Ty` (that must be a reference) with a synthesized lifetime
/// name where required.
pub(super) fn get_name_for_ty(&self, ty: Ty<'tcx>, counter: usize) -> String {
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS);
let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, Namespace::TypeNS);

// We need to add synthesized lifetimes where appropriate. We do
// this by hooking into the pretty printer and telling it to label the
Expand All @@ -504,15 +503,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}

let _ = ty.print(printer);
s
ty.print(printer).unwrap().into_buffer()
}

/// Returns the name of the provided `Ty` (that must be a reference)'s region with a
/// synthesized lifetime name where required.
pub(super) fn get_region_name_for_ty(&self, ty: Ty<'tcx>, counter: usize) -> String {
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS);
let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, Namespace::TypeNS);

let region = if let ty::Ref(region, ..) = ty.kind() {
match **region {
Expand All @@ -527,8 +524,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
bug!("ty for annotation of borrow region is not a reference");
};

let _ = region.print(printer);
s
region.print(printer).unwrap().into_buffer()
}
}

Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_const_eval/src/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ rustc_data_structures::static_assert_size!(ImmTy<'_>, 72);
impl<Tag: Provenance> std::fmt::Display for ImmTy<'_, Tag> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
/// Helper function for printing a scalar to a FmtPrinter
fn p<'a, 'tcx, F: std::fmt::Write, Tag: Provenance>(
cx: FmtPrinter<'a, 'tcx, F>,
fn p<'a, 'tcx, Tag: Provenance>(
cx: FmtPrinter<'a, 'tcx>,
s: ScalarMaybeUninit<Tag>,
ty: Ty<'tcx>,
) -> Result<FmtPrinter<'a, 'tcx, F>, std::fmt::Error> {
) -> Result<FmtPrinter<'a, 'tcx>, std::fmt::Error> {
match s {
ScalarMaybeUninit::Scalar(Scalar::Int(int)) => {
cx.pretty_print_const_scalar_int(int, ty, true)
Expand All @@ -138,8 +138,8 @@ impl<Tag: Provenance> std::fmt::Display for ImmTy<'_, Tag> {
match self.imm {
Immediate::Scalar(s) => {
if let Some(ty) = tcx.lift(self.layout.ty) {
let cx = FmtPrinter::new(tcx, f, Namespace::ValueNS);
p(cx, s, ty)?;
let cx = FmtPrinter::new(tcx, Namespace::ValueNS);
f.write_str(&p(cx, s, ty)?.into_buffer())?;
return Ok(());
}
write!(f, "{}: {}", s, self.layout.ty)
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -988,8 +988,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
) -> (DiagnosticStyledString, DiagnosticStyledString) {
let get_lifetimes = |sig| {
use rustc_hir::def::Namespace;
let mut s = String::new();
let (_, sig, reg) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS)
let (_, sig, reg) = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS)
.name_all_regions(sig)
.unwrap();
let lts: Vec<String> = reg.into_iter().map(|(_, kind)| kind.to_string()).collect();
Expand Down
27 changes: 11 additions & 16 deletions compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,14 +395,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}

let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS);
if let Some(highlight) = highlight {
printer.region_highlight_mode = highlight;
}
let _ = ty.print(printer);
let name = ty.print(printer).unwrap().into_buffer();
InferenceDiagnosticsData {
name: s,
name,
span: None,
kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) },
parent: None,
Expand Down Expand Up @@ -431,15 +430,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}

debug_assert!(!origin.span.is_dummy());
let mut s = String::new();
let mut printer =
ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS);
let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::ValueNS);
if let Some(highlight) = highlight {
printer.region_highlight_mode = highlight;
}
let _ = ct.print(printer);
let name = ct.print(printer).unwrap().into_buffer();
InferenceDiagnosticsData {
name: s,
name,
span: Some(origin.span),
kind: UnderspecifiedArgKind::Const { is_parameter: false },
parent: None,
Expand Down Expand Up @@ -495,8 +492,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

let mut local_visitor = FindHirNodeVisitor::new(&self, arg, span);
let ty_to_string = |ty: Ty<'tcx>| -> String {
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS);
let ty_getter = move |ty_vid| {
if let TypeVariableOriginKind::TypeParameterDefinition(name, _) =
self.inner.borrow_mut().type_variables().var_origin(ty_vid).kind
Expand All @@ -523,14 +519,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
};
printer.const_infer_name_resolver = Some(Box::new(const_getter));

let _ = if let ty::FnDef(..) = ty.kind() {
if let ty::FnDef(..) = ty.kind() {
// We don't want the regular output for `fn`s because it includes its path in
// invalid pseudo-syntax, we want the `fn`-pointer output instead.
ty.fn_sig(self.tcx).print(printer)
ty.fn_sig(self.tcx).print(printer).unwrap().into_buffer()
} else {
ty.print(printer)
};
s
ty.print(printer).unwrap().into_buffer()
}
};

if let Some(body_id) = body_id {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,18 +335,19 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {

impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
where
T: for<'a, 'b, 'c> Print<
T: for<'a> Print<
'tcx,
FmtPrinter<'a, 'tcx, &'b mut fmt::Formatter<'c>>,
FmtPrinter<'a, 'tcx>,
Error = fmt::Error,
Output = FmtPrinter<'a, 'tcx>,
>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut printer = ty::print::FmtPrinter::new(self.tcx, f, Namespace::TypeNS);
let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS);
printer.region_highlight_mode = self.highlight;

self.value.print(printer)?;
Ok(())
let s = self.value.print(printer)?.into_buffer();
f.write_str(&s)
}
}

Expand Down
16 changes: 9 additions & 7 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2421,11 +2421,11 @@ impl<'tcx> Debug for Rvalue<'tcx> {

AggregateKind::Adt(adt_did, variant, substs, _user_ty, _) => {
ty::tls::with(|tcx| {
let mut name = String::new();
let variant_def = &tcx.adt_def(adt_did).variants[variant];
let substs = tcx.lift(substs).expect("could not lift for printing");
FmtPrinter::new(tcx, &mut name, Namespace::ValueNS)
.print_def_path(variant_def.def_id, substs)?;
let name = FmtPrinter::new(tcx, Namespace::ValueNS)
.print_def_path(variant_def.def_id, substs)?
.into_buffer();

match variant_def.ctor_kind {
CtorKind::Const => fmt.write_str(&name),
Expand Down Expand Up @@ -2847,9 +2847,10 @@ fn pretty_print_const<'tcx>(
use crate::ty::print::PrettyPrinter;
ty::tls::with(|tcx| {
let literal = tcx.lift(c).unwrap();
let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS);
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
cx.print_alloc_ids = true;
cx.pretty_print_const(literal, print_types)?;
let cx = cx.pretty_print_const(literal, print_types)?;
fmt.write_str(&cx.into_buffer())?;
Ok(())
})
}
Expand All @@ -2864,9 +2865,10 @@ fn pretty_print_const_value<'tcx>(
ty::tls::with(|tcx| {
let val = tcx.lift(val).unwrap();
let ty = tcx.lift(ty).unwrap();
let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS);
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
cx.print_alloc_ids = true;
cx.pretty_print_const_value(val, ty, print_types)?;
let cx = cx.pretty_print_const_value(val, ty, print_types)?;
fmt.write_str(&cx.into_buffer())?;
Ok(())
})
}
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_middle/src/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -983,10 +983,9 @@ fn foo(&self) -> Self::T { String::new() }
}

fn format_generic_args(self, args: &[ty::GenericArg<'tcx>]) -> String {
let mut item_args = String::new();
FmtPrinter::new(self, &mut item_args, hir::def::Namespace::TypeNS)
FmtPrinter::new(self, hir::def::Namespace::TypeNS)
.path_generic_args(Ok, args)
.expect("could not write to `String`.");
item_args
.expect("could not write to `String`.")
.into_buffer()
}
}
7 changes: 4 additions & 3 deletions compiler/rustc_middle/src/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,10 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ty::tls::with(|tcx| {
let substs = tcx.lift(self.substs).expect("could not lift for printing");
FmtPrinter::new(tcx, &mut *f, Namespace::ValueNS)
.print_def_path(self.def_id(), substs)?;
Ok(())
let s = FmtPrinter::new(tcx, Namespace::ValueNS)
.print_def_path(self.def_id(), substs)?
.into_buffer();
f.write_str(&s)
})?;

match self.def {
Expand Down
49 changes: 27 additions & 22 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1545,11 +1545,11 @@ pub trait PrettyPrinter<'tcx>:
}

// HACK(eddyb) boxed to avoid moving around a large struct by-value.
pub struct FmtPrinter<'a, 'tcx, F>(Box<FmtPrinterData<'a, 'tcx, F>>);
pub struct FmtPrinter<'a, 'tcx>(Box<FmtPrinterData<'a, 'tcx>>);

pub struct FmtPrinterData<'a, 'tcx, F> {
pub struct FmtPrinterData<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
fmt: F,
fmt: String,

empty_path: bool,
in_value: bool,
Expand All @@ -1566,24 +1566,26 @@ pub struct FmtPrinterData<'a, 'tcx, F> {
pub const_infer_name_resolver: Option<Box<dyn Fn(ty::ConstVid<'tcx>) -> Option<String> + 'a>>,
}

impl<'a, 'tcx, F> Deref for FmtPrinter<'a, 'tcx, F> {
type Target = FmtPrinterData<'a, 'tcx, F>;
impl<'a, 'tcx> Deref for FmtPrinter<'a, 'tcx> {
type Target = FmtPrinterData<'a, 'tcx>;
fn deref(&self) -> &Self::Target {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be enough to slap #[inline] on all the functions in this file that appear in cachegrind for the first time after this PR

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of these functions appear in cachegrind -- they're not the direct problem. For example on stm32f4-check-full, we see a diff like this:

245,045,449  PROGRAM TOTALS

--------------------------------------------------------------------------------
Ir             file:function
--------------------------------------------------------------------------------
  372,484,116  ???:<core::iter::adapters::map::Map<core::iter::adapters::enumerate::Enumerate<core::iter::adapters::zip::Zip<core::iter::adapters::copied::Copied<core::slice::iter::Iter<rustc_middle::ty::subst::>
 -326,700,323  ???:rustc_middle::ty::relate::relate_substs::<rustc_infer::infer::equate::Equate>
  123,186,012  ???:<rustc_middle::ty::subst::SubstFolder as rustc_middle::ty::fold::TypeFolder>::fold_ty
   86,186,243  ???:rustc_middle::ty::relate::super_relate_tys::<rustc_infer::infer::equate::Equate>
  -55,808,143  ???:<rustc_middle::ty::Ty as rustc_middle::ty::fold::TypeFoldable>::super_fold_with::<rustc_middle::ty::subst::SubstFolder>
   30,561,468  ???:<alloc::collections::btree::map::entry::OccupiedEntry<rustc_infer::infer::region_constraints::Constraint, rustc_infer::infer::SubregionOrigin>>::remove_entry
  -27,764,057  ???:<alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Mut, rustc_infer::infer::region_constraints::Constraint, rustc_infer:>
   20,749,456  ???:<&mut alloc::vec::Vec<ena::unify::VarValue<rustc_type_ir::TyVid>> as core::convert::AsRef<[ena::unify::VarValue<rustc_type_ir::TyVid>]>>::as_ref
   18,135,210  ???:<rustc_middle::mir::Rvalue>::ty::<rustc_middle::mir::Body>
   15,490,475  ???:<rustc_middle::ty::fold::RegionFolder as rustc_middle::ty::fold::FallibleTypeFolder>::try_fold_ty
  -12,892,781  ???:<rustc_middle::ty::Ty as rustc_middle::ty::fold::TypeFoldable>::super_fold_with::<rustc_middle::ty::fold::RegionFolder>
   12,520,606  ???:<rustc_infer::infer::combine::CombineFields>::instantiate
   12,024,623  ???:<rustc_data_structures::stable_hasher::StableHasher>::finish::<u128>
  -11,945,001  ???:<core::iter::adapters::map::Map<std::collections::hash::map::Iter<rustc_span::def_id::LocalDefId, rustc_hir::hir_id::ItemLocalId>, rustc_data_structures::stable_hasher::stable_hash_reduce<rust>
  -10,922,924  ???:<rustc_middle::ty::subst::GenericArg as rustc_middle::ty::relate::Relate>::relate::<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>
    9,837,670  ???:<alloc::vec::Vec<rustc_type_ir::TyVid> as alloc::vec::spec_from_iter::SpecFromIter<rustc_type_ir::TyVid, core::iter::adapters::filter_map::FilterMap<core::ops::range::Range<usize>, <rustc_infe>
   -8,795,699  ???:<rustc_infer::infer::sub::Sub as rustc_middle::ty::relate::TypeRelation>::relate_with_variance::<rustc_middle::ty::Ty>
    8,712,904  ???:<&mut rustc_middle::ty::relate::relate_substs<rustc_infer::infer::nll_relate::TypeRelating<rustc_borrowck::type_check::relate_tys::NllTypeRelatingDelegate>>::{closure#0} as core::ops::function>
    8,332,971  ???:<rustc_infer::infer::equate::Equate as rustc_middle::ty::relate::TypeRelation>::relate_with_variance::<rustc_middle::ty::Ty>
    8,262,191  ???:<rustc_infer::infer::sub::Sub as rustc_middle::ty::relate::TypeRelation>::tys
   -8,099,008  ???:<rustc_infer::infer::InferCtxt>::unsolved_variables

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah lol, yea, inlining cost boundaries are fun. Yea, just slap the attribute on all previously generic methods, that should make callers big enough again to stop them from being inlined. Alternatively add inline(never) with a comment to functions that disappeared from cachegrind.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not practical -- almost every single method became non-generic after removing the parameter; that's the whole reason for the big win on compile times. IMO trying to second-guess LLVM here on inlining (in either direction) is not the right approach, we're not likely to find a magic bullet.

The diff above is illustrative of typical inlining decisions slightly changing, but trying to recover from that by adding attributes isn't likely to really help that much -- the changes are too scattered and ultimately I suspect arise from things that we can't really influence easily.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the gains are from not instantiating the generics in 5 different crates and generating LLVM IR for them and optimizing them?

Having them only get compiled once is a different aspect than removing the implicit #[inline] that generic function have

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[inline] on all of these methods will -- AFAIK -- force generation in every crate that uses them; it's equivalent to generics in that respect. It also adds an inline hint, but that's a separate effect and unlikely to matter as much given the large size of many of the functions here. We save a little of course on generating just one copy per crate instead of 2-3, but that's still a higher cost.

&self.0
}
}

impl<F> DerefMut for FmtPrinter<'_, '_, F> {
impl DerefMut for FmtPrinter<'_, '_> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl<'a, 'tcx, F> FmtPrinter<'a, 'tcx, F> {
pub fn new(tcx: TyCtxt<'tcx>, fmt: F, ns: Namespace) -> Self {
impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, ns: Namespace) -> Self {
FmtPrinter(Box::new(FmtPrinterData {
tcx,
fmt,
// Estimated reasonable capacity to allocate upfront based on a few
// benchmarks.
fmt: String::with_capacity(64),
empty_path: false,
in_value: ns == Namespace::ValueNS,
print_alloc_ids: false,
Expand All @@ -1596,6 +1598,10 @@ impl<'a, 'tcx, F> FmtPrinter<'a, 'tcx, F> {
const_infer_name_resolver: None,
}))
}

pub fn into_buffer(self) -> String {
self.0.fmt
}
}

// HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
Expand Down Expand Up @@ -1627,19 +1633,18 @@ impl<'t> TyCtxt<'t> {
pub fn def_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String {
let ns = guess_def_namespace(self, def_id);
debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
let mut s = String::new();
let _ = FmtPrinter::new(self, &mut s, ns).print_def_path(def_id, substs);
s
FmtPrinter::new(self, ns).print_def_path(def_id, substs).unwrap().into_buffer()
}
}

impl<F: fmt::Write> fmt::Write for FmtPrinter<'_, '_, F> {
impl fmt::Write for FmtPrinter<'_, '_> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.fmt.write_str(s)
self.fmt.push_str(s);
Ok(())
}
}

impl<'tcx, F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
type Error = fmt::Error;

type Path = Self;
Expand Down Expand Up @@ -1847,7 +1852,7 @@ impl<'tcx, F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
}
}

impl<'tcx, F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
fn ty_infer_name(&self, id: ty::TyVid) -> Option<String> {
self.0.ty_infer_name_resolver.as_ref().and_then(|func| func(id))
}
Expand Down Expand Up @@ -1983,7 +1988,7 @@ impl<'tcx, F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
}

// HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
impl FmtPrinter<'_, '_> {
pub fn pretty_print_region(mut self, region: ty::Region<'_>) -> Result<Self, fmt::Error> {
define_scoped_cx!(self);

Expand Down Expand Up @@ -2117,7 +2122,7 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {

// HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`,
// `region_index` and `used_region_names`.
impl<'tcx, F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
impl<'tcx> FmtPrinter<'_, 'tcx> {
pub fn name_all_regions<T>(
mut self,
value: &ty::Binder<'tcx, T>,
Expand Down Expand Up @@ -2369,9 +2374,10 @@ macro_rules! forward_display_to_print {
$(#[allow(unused_lifetimes)] impl<'tcx> fmt::Display for $ty {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ty::tls::with(|tcx| {
tcx.lift(*self)
let cx = tcx.lift(*self)
.expect("could not lift for printing")
.print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?;
.print(FmtPrinter::new(tcx, Namespace::TypeNS))?;
f.write_str(&cx.into_buffer())?;
Ok(())
})
}
Expand Down Expand Up @@ -2402,8 +2408,7 @@ macro_rules! define_print_and_forward_display {
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))?;
Ok(())
f.write_str(&self.print(FmtPrinter::new(tcx, Namespace::TypeNS))?.into_buffer())
})
}
}
Expand Down
Loading