From 456f4e8d22dfa18de1fc0bafb4455a6b27f92aea Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 15 Sep 2022 18:46:40 +0200 Subject: [PATCH] don't duplicate late-bound region names in print of Binder --- compiler/rustc_middle/src/ty/print/pretty.rs | 80 +++++++++++++------- compiler/rustc_middle/src/ty/sty.rs | 28 +++++++ 2 files changed, 81 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 99e5722ddad..da964077285 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1562,7 +1562,9 @@ pub struct FmtPrinterData<'a, 'tcx> { in_value: bool, pub print_alloc_ids: bool, + // set of all named (non-anonymous) region names used_region_names: FxHashSet, + region_index: usize, binder_depth: usize, printed_type_count: usize, @@ -2118,23 +2120,31 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { - fn name_by_region_index(index: usize) -> Symbol { - match index { - 0 => Symbol::intern("'r"), - 1 => Symbol::intern("'s"), - i => Symbol::intern(&format!("'t{}", i - 2)), + fn name_by_region_index( + index: usize, + available_names: &mut Vec, + num_available: usize, + ) -> Symbol { + if let Some(name) = available_names.pop() { + name + } else { + Symbol::intern(&format!("'t{}", index - num_available)) } } + debug!("name_all_regions"); + // Replace any anonymous late-bound regions with named // variants, using new unique identifiers, so that we can // clearly differentiate between named and unnamed regions in // the output. We'll probably want to tweak this over time to // decide just how much information to give. if self.binder_depth == 0 { - self.prepare_late_bound_region_info(value); + self.prepare_region_info(value); } + debug!("self.used_region_names: {:?}", &self.used_region_names); + let mut empty = true; let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { let w = if empty { @@ -2151,13 +2161,23 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { define_scoped_cx!(self); + let possible_names = vec![Symbol::intern("'t"), Symbol::intern("'s"), Symbol::intern("'r")]; + + let mut available_names = possible_names + .into_iter() + .filter(|name| !self.used_region_names.contains(&name)) + .collect::>(); + debug!(?available_names); + let num_available = available_names.len(); + let mut region_index = self.region_index; - let mut next_name = |this: &Self| loop { - let name = name_by_region_index(region_index); + let mut next_name = |this: &Self| { + let name = name_by_region_index(region_index, &mut available_names, num_available); + debug!(?name); region_index += 1; - if !this.used_region_names.contains(&name) { - break name; - } + assert!(!this.used_region_names.contains(&name)); + + name }; // If we want to print verbosely, then print *all* binders, even if they @@ -2178,6 +2198,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { ty::BrAnon(_) | ty::BrEnv => { start_or_continue(&mut self, "for<", ", "); let name = next_name(&self); + debug!(?name); do_continue(&mut self, name); ty::BrNamed(CRATE_DEF_ID.to_def_id(), name) } @@ -2271,29 +2292,37 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { Ok(inner) } - fn prepare_late_bound_region_info(&mut self, value: &ty::Binder<'tcx, T>) + fn prepare_region_info(&mut self, value: &ty::Binder<'tcx, T>) where T: TypeVisitable<'tcx>, { - struct LateBoundRegionNameCollector<'a, 'tcx> { - used_region_names: &'a mut FxHashSet, + struct RegionNameCollector<'tcx> { + used_region_names: FxHashSet, type_collector: SsoHashSet>, } - impl<'tcx> ty::visit::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> { + impl<'tcx> RegionNameCollector<'tcx> { + fn new() -> Self { + RegionNameCollector { + used_region_names: Default::default(), + type_collector: SsoHashSet::new(), + } + } + } + + impl<'tcx> ty::visit::TypeVisitor<'tcx> for RegionNameCollector<'tcx> { type BreakTy = (); fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { 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 { - name: ty::BrNamed(_, name), - .. - }) = *r - { + + // Collect all named lifetimes. These allow us to prevent duplication + // of already existing lifetime names when introducing names for + // anonymous late-bound regions. + if let Some(name) = r.get_name() { self.used_region_names.insert(name); } + r.super_visit_with(self) } @@ -2309,12 +2338,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } } - self.used_region_names.clear(); - let mut collector = LateBoundRegionNameCollector { - used_region_names: &mut self.used_region_names, - type_collector: SsoHashSet::new(), - }; + let mut collector = RegionNameCollector::new(); value.visit_with(&mut collector); + self.used_region_names = collector.used_region_names; self.region_index = 0; } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 258fb2e2f9f..08fb6a329df 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -85,6 +85,17 @@ impl BoundRegionKind { _ => false, } } + + pub fn get_name(&self) -> Option { + if self.is_named() { + match *self { + BoundRegionKind::BrNamed(_, name) => return Some(name), + _ => unreachable!(), + } + } + + None + } } pub trait Article { @@ -1445,6 +1456,23 @@ impl<'tcx> Region<'tcx> { *self.0.0 } + pub fn get_name(self) -> Option { + if self.has_name() { + let name = match *self { + ty::ReEarlyBound(ebr) => Some(ebr.name), + ty::ReLateBound(_, br) => br.kind.get_name(), + ty::ReFree(fr) => fr.bound_region.get_name(), + ty::ReStatic => Some(Symbol::intern("static")), + ty::RePlaceholder(placeholder) => placeholder.name.get_name(), + _ => None, + }; + + return name; + } + + None + } + /// Is this region named by the user? pub fn has_name(self) -> bool { match *self {