about summary refs log tree commit diff
diff options
context:
space:
mode:
authorb-naber <bn263@gmx.de>2022-09-15 18:46:40 +0200
committerb-naber <bn263@gmx.de>2022-09-26 13:10:55 +0200
commit456f4e8d22dfa18de1fc0bafb4455a6b27f92aea (patch)
tree6ccec8e8b267e3e1237276e2db20895760606fff
parent72f4923979979abb5d6b975353e9b3053d257e60 (diff)
downloadrust-456f4e8d22dfa18de1fc0bafb4455a6b27f92aea.tar.gz
rust-456f4e8d22dfa18de1fc0bafb4455a6b27f92aea.zip
don't duplicate late-bound region names in print of Binder
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs80
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs28
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<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;
     }
 }
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<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 {