don't duplicate late-bound region names in print of Binder
This commit is contained in:
parent
72f4923979
commit
456f4e8d22
2 changed files with 81 additions and 27 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue