about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-11-17 07:03:26 -0500
committerNiko Matsakis <niko@alum.mit.edu>2019-01-02 17:35:05 -0500
commit1597f2a0fca681219c1f495ed3bbe01aa889fb43 (patch)
treed83db2c606d0e47d9bad25e241386512b3810423
parent37b0b3e9a36ccbf4a6baace1f5d0f3ccf738d6b9 (diff)
downloadrust-1597f2a0fca681219c1f495ed3bbe01aa889fb43.tar.gz
rust-1597f2a0fca681219c1f495ed3bbe01aa889fb43.zip
add the ability to highlight placeholders
-rw-r--r--src/librustc/util/ppaux.rs83
1 files changed, 81 insertions, 2 deletions
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index ea0495c5c73..55e3f3e6f93 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -43,6 +43,13 @@ pub struct RegionHighlightMode {
     /// y: &'a u32)` and we want to give a name to the region of the
     /// reference `x`.
     highlight_bound_region: Option<(ty::BoundRegion, usize)>,
+
+    /// If enabled, when printing a "placeholder" (what we get when
+    /// substituting a universally quantified region as in `for<'a> T:
+    /// Foo<'a>`), print out instead `'N`.
+    ///
+    /// (Unlike other modes, we can highlight more than one placeholder at a time.)
+    highlight_placeholders: [Option<(ty::PlaceholderRegion, usize)>; 2],
 }
 
 thread_local! {
@@ -53,10 +60,12 @@ thread_local! {
 }
 
 impl RegionHighlightMode {
+    /// Read and return current region highlight settings (accesses thread-local state).a
     pub fn get() -> Self {
         REGION_HIGHLIGHT_MODE.with(|c| c.get())
     }
 
+    /// Internal helper to update current settings during the execution of `op`.
     fn set<R>(
         old_mode: Self,
         new_mode: Self,
@@ -70,6 +79,9 @@ impl RegionHighlightMode {
         })
     }
 
+    /// During the execution of `op`, highlight the region inference
+    /// vairable `vid` as `'N`.  We can only highlight one region vid
+    /// at a time.
     pub fn highlighting_region_vid<R>(vid: RegionVid, number: usize, op: impl FnOnce() -> R) -> R {
         let old_mode = Self::get();
         assert!(old_mode.highlight_region_vid.is_none());
@@ -102,6 +114,52 @@ impl RegionHighlightMode {
             op,
         )
     }
+
+    /// During the execution of `op`, highlight the given placeholders
+    /// with the given numbers. Unlike other modes: non-highlighted
+    /// placeholders are printed as `'_` (where they might normally print
+    /// differently. This may want to be tweaked; but we do it for two reasons
+    ///
+    /// (a) to draw attention to the placeholders we are trying to highlight
+    /// (b) because placeholder names can come from other scopes than the one
+    ///     in which the error occurred, so that can be misleading.
+    ///
+    /// We can highlight up to two placeholders at a time.
+    pub fn highlighting_placeholder<R>(
+        placeholder: ty::PlaceholderRegion,
+        number: usize,
+        op: impl FnOnce() -> R,
+    ) -> R {
+        let old_mode = Self::get();
+        let mut new_mode = old_mode;
+        let first_avail_slot = new_mode.highlight_placeholders.iter_mut()
+            .filter(|s| s.is_none())
+            .next()
+            .unwrap_or_else(|| {
+                panic!(
+                    "can only highlight {} placeholders at a time",
+                    old_mode.highlight_placeholders.len(),
+                )
+            });
+        *first_avail_slot = Some((placeholder, number));
+        Self::set(old_mode, new_mode, op)
+    }
+
+    /// Returns true if any placeholders are highlighted.
+    pub fn any_placeholders_highlighted(&self) -> bool {
+        self.highlight_placeholders.iter().any(|p| p.is_some())
+    }
+
+    /// Returns `Some(N)` if the placeholder `p` is highlighted to print as `'N`.
+    pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option<usize> {
+        self.highlight_placeholders
+            .iter()
+            .filter_map(|h| match h {
+                &Some((h, n)) if h == p => Some(n),
+                _ => None,
+            })
+            .next()
+    }
 }
 
 macro_rules! gen_display_debug_body {
@@ -803,6 +861,25 @@ define_print! {
 }
 
 define_print! {
+    () ty::PlaceholderRegion, (self, f, cx) {
+        display {
+            if cx.is_verbose {
+                return self.print_debug(f, cx);
+            }
+
+            let highlight = RegionHighlightMode::get();
+            if let Some(counter) = highlight.placeholder_highlight(*self) {
+                write!(f, "'{}", counter)
+            } else if highlight.any_placeholders_highlighted() {
+                write!(f, "'_")
+            } else {
+                write!(f, "{}", self.name)
+            }
+        }
+    }
+}
+
+define_print! {
     () ty::RegionKind, (self, f, cx) {
         display {
             if cx.is_verbose {
@@ -818,10 +895,12 @@ define_print! {
                     write!(f, "{}", data.name)
                 }
                 ty::ReLateBound(_, br) |
-                ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
-                ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
+                ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
                     write!(f, "{}", br)
                 }
+                ty::RePlaceholder(p) => {
+                    write!(f, "{}", p)
+                }
                 ty::ReScope(scope) if cx.identify_regions => {
                     match scope.data {
                         region::ScopeData::Node =>