1
Fork 0

don't duplicate late-bound region names in print of Binder

This commit is contained in:
b-naber 2022-09-15 18:46:40 +02:00
parent 72f4923979
commit 456f4e8d22
2 changed files with 81 additions and 27 deletions

View file

@ -1562,7 +1562,9 @@ pub struct FmtPrinterData<'a, 'tcx> {
in_value: bool, in_value: bool,
pub print_alloc_ids: bool, pub print_alloc_ids: bool,
// set of all named (non-anonymous) region names
used_region_names: FxHashSet<Symbol>, used_region_names: FxHashSet<Symbol>,
region_index: usize, region_index: usize,
binder_depth: usize, binder_depth: usize,
printed_type_count: usize, printed_type_count: usize,
@ -2118,23 +2120,31 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
where where
T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
{ {
fn name_by_region_index(index: usize) -> Symbol { fn name_by_region_index(
match index { index: usize,
0 => Symbol::intern("'r"), available_names: &mut Vec<Symbol>,
1 => Symbol::intern("'s"), num_available: usize,
i => Symbol::intern(&format!("'t{}", i - 2)), ) -> 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 // Replace any anonymous late-bound regions with named
// variants, using new unique identifiers, so that we can // variants, using new unique identifiers, so that we can
// clearly differentiate between named and unnamed regions in // clearly differentiate between named and unnamed regions in
// the output. We'll probably want to tweak this over time to // the output. We'll probably want to tweak this over time to
// decide just how much information to give. // decide just how much information to give.
if self.binder_depth == 0 { 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 empty = true;
let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
let w = if empty { let w = if empty {
@ -2151,13 +2161,23 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
define_scoped_cx!(self); 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::<Vec<_>>();
debug!(?available_names);
let num_available = available_names.len();
let mut region_index = self.region_index; let mut region_index = self.region_index;
let mut next_name = |this: &Self| loop { let mut next_name = |this: &Self| {
let name = name_by_region_index(region_index); let name = name_by_region_index(region_index, &mut available_names, num_available);
debug!(?name);
region_index += 1; region_index += 1;
if !this.used_region_names.contains(&name) { assert!(!this.used_region_names.contains(&name));
break name;
} name
}; };
// If we want to print verbosely, then print *all* binders, even if they // 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 => { ty::BrAnon(_) | ty::BrEnv => {
start_or_continue(&mut self, "for<", ", "); start_or_continue(&mut self, "for<", ", ");
let name = next_name(&self); let name = next_name(&self);
debug!(?name);
do_continue(&mut self, name); do_continue(&mut self, name);
ty::BrNamed(CRATE_DEF_ID.to_def_id(), name) ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
} }
@ -2271,29 +2292,37 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
Ok(inner) Ok(inner)
} }
fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>) fn prepare_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
where where
T: TypeVisitable<'tcx>, T: TypeVisitable<'tcx>,
{ {
struct LateBoundRegionNameCollector<'a, 'tcx> { struct RegionNameCollector<'tcx> {
used_region_names: &'a mut FxHashSet<Symbol>, used_region_names: FxHashSet<Symbol>,
type_collector: SsoHashSet<Ty<'tcx>>, type_collector: SsoHashSet<Ty<'tcx>>,
} }
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 = (); type BreakTy = ();
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
trace!("address: {:p}", r.0.0); trace!("address: {:p}", r.0.0);
if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
self.used_region_names.insert(name); // Collect all named lifetimes. These allow us to prevent duplication
} else if let ty::RePlaceholder(ty::PlaceholderRegion { // of already existing lifetime names when introducing names for
name: ty::BrNamed(_, name), // anonymous late-bound regions.
.. if let Some(name) = r.get_name() {
}) = *r
{
self.used_region_names.insert(name); self.used_region_names.insert(name);
} }
r.super_visit_with(self) r.super_visit_with(self)
} }
@ -2309,12 +2338,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
} }
} }
self.used_region_names.clear(); let mut collector = RegionNameCollector::new();
let mut collector = LateBoundRegionNameCollector {
used_region_names: &mut self.used_region_names,
type_collector: SsoHashSet::new(),
};
value.visit_with(&mut collector); value.visit_with(&mut collector);
self.used_region_names = collector.used_region_names;
self.region_index = 0; self.region_index = 0;
} }
} }

View file

@ -85,6 +85,17 @@ impl BoundRegionKind {
_ => false, _ => false,
} }
} }
pub fn get_name(&self) -> Option<Symbol> {
if self.is_named() {
match *self {
BoundRegionKind::BrNamed(_, name) => return Some(name),
_ => unreachable!(),
}
}
None
}
} }
pub trait Article { pub trait Article {
@ -1445,6 +1456,23 @@ impl<'tcx> Region<'tcx> {
*self.0.0 *self.0.0
} }
pub fn get_name(self) -> Option<Symbol> {
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? /// Is this region named by the user?
pub fn has_name(self) -> bool { pub fn has_name(self) -> bool {
match *self { match *self {