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,
pub print_alloc_ids: bool,
// set of all named (non-anonymous) region names
used_region_names: FxHashSet<Symbol>,
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<Symbol>,
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::<Vec<_>>();
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<T>(&mut self, value: &ty::Binder<'tcx, T>)
fn prepare_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
where
T: TypeVisitable<'tcx>,
{
struct LateBoundRegionNameCollector<'a, 'tcx> {
used_region_names: &'a mut FxHashSet<Symbol>,
struct RegionNameCollector<'tcx> {
used_region_names: FxHashSet<Symbol>,
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 = ();
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
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;
}
}

View file

@ -85,6 +85,17 @@ impl BoundRegionKind {
_ => 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 {
@ -1445,6 +1456,23 @@ impl<'tcx> Region<'tcx> {
*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?
pub fn has_name(self) -> bool {
match *self {