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,
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue