]> git.lizzy.rs Git - rust.git/commitdiff
rustc: don't keep RegionHighlightMode in a thread-local.
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Fri, 11 Jan 2019 11:07:01 +0000 (13:07 +0200)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Fri, 15 Mar 2019 11:25:10 +0000 (13:25 +0200)
src/librustc/infer/error_reporting/need_type_info.rs
src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
src/librustc/ty/print.rs
src/librustc/util/ppaux.rs
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs

index 9e0e48e474118fd14730ee363d1f804427b4b026..26deecfdbf0fc74a9a4801076dc6c4dc6107fc1a 100644 (file)
@@ -3,6 +3,7 @@
 use crate::infer::InferCtxt;
 use crate::infer::type_variable::TypeVariableOrigin;
 use crate::ty::{self, Ty, Infer, TyVar};
+use ty::print::Print;
 use syntax::source_map::CompilerDesugaringKind;
 use syntax_pos::Span;
 use errors::DiagnosticBuilder;
@@ -64,18 +65,28 @@ fn visit_body(&mut self, body: &'gcx Body) {
 
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-    pub fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
+    pub fn extract_type_name(
+        &self,
+        ty: &'a Ty<'tcx>,
+        highlight: Option<ty::print::RegionHighlightMode>,
+    ) -> String {
         if let ty::Infer(ty::TyVar(ty_vid)) = (*ty).sty {
             let ty_vars = self.type_variables.borrow();
             if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
                 *ty_vars.var_origin(ty_vid) {
-                name.to_string()
-            } else {
-                ty.to_string()
+                return name.to_string();
             }
-        } else {
-            ty.to_string()
         }
+
+        let mut s = String::new();
+        let mut printer = ty::print::FmtPrinter::new(&mut s);
+        if let Some(highlight) = highlight {
+            printer.region_highlight_mode = highlight;
+        }
+        let _ = ty::print::PrintCx::with(self.tcx, printer, |cx| {
+            ty.print(cx)
+        });
+        s
     }
 
     pub fn need_type_info_err(&self,
@@ -84,7 +95,7 @@ pub fn need_type_info_err(&self,
                             ty: Ty<'tcx>)
                             -> DiagnosticBuilder<'gcx> {
         let ty = self.resolve_type_vars_if_possible(&ty);
-        let name = self.extract_type_name(&ty);
+        let name = self.extract_type_name(&ty, None);
 
         let mut err_span = span;
         let mut labels = vec![(
index 189ecf53e0e8496dd3537deee41ac52e95476ce1..65fcc69a338675c38ffc9ec65f9edde6df3912ca 100644 (file)
@@ -5,10 +5,12 @@
 use crate::infer::ValuePairs;
 use crate::infer::{SubregionOrigin, TypeTrace};
 use crate::traits::{ObligationCause, ObligationCauseCode};
-use crate::ty;
+use crate::ty::{self, TyCtxt};
 use crate::ty::error::ExpectedFound;
 use crate::ty::subst::SubstsRef;
-use crate::util::ppaux::RegionHighlightMode;
+use crate::ty::print::{Print, RegionHighlightMode, FmtPrinter};
+
+use std::fmt::{self, Write};
 
 impl NiceRegionError<'me, 'gcx, 'tcx> {
     /// When given a `ConcreteFailure` for a function with arguments containing a named region and
@@ -309,13 +311,48 @@ fn explain_actual_impl_that_was_found(
         sup_placeholder: Option<ty::Region<'tcx>>,
         has_sub: Option<usize>,
         has_sup: Option<usize>,
-        expected_trait_ref: ty::TraitRef<'_>,
-        actual_trait_ref: ty::TraitRef<'_>,
+        expected_trait_ref: ty::TraitRef<'tcx>,
+        actual_trait_ref: ty::TraitRef<'tcx>,
         vid: Option<ty::Region<'tcx>>,
         expected_has_vid: Option<usize>,
         actual_has_vid: Option<usize>,
         any_self_ty_has_vid: bool,
     ) {
+        // HACK(eddyb) maybe move this in a more central location.
+        #[derive(Copy, Clone)]
+        struct Highlighted<'a, 'gcx, 'tcx, T> {
+            tcx: TyCtxt<'a, 'gcx, 'tcx>,
+            highlight: RegionHighlightMode,
+            value: T,
+        }
+
+        impl<'a, 'gcx, 'tcx, T> Highlighted<'a, 'gcx, 'tcx, T> {
+            fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'a, 'gcx, 'tcx, U> {
+                Highlighted {
+                    tcx: self.tcx,
+                    highlight: self.highlight,
+                    value: f(self.value),
+                }
+            }
+        }
+
+        impl<'tcx, T> fmt::Display for Highlighted<'_, '_, 'tcx, T>
+            where T: for<'a, 'b> Print<'tcx,
+                FmtPrinter<&'a mut fmt::Formatter<'b>>,
+                Error = fmt::Error,
+            >,
+        {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                let mut printer = ty::print::FmtPrinter::new(f);
+                printer.region_highlight_mode = self.highlight;
+
+                ty::print::PrintCx::with(self.tcx, printer, |cx| {
+                    self.value.print(cx)?;
+                    Ok(())
+                })
+            }
+        }
+
         // The weird thing here with the `maybe_highlighting_region` calls and the
         // the match inside is meant to be like this:
         //
@@ -331,112 +368,93 @@ fn explain_actual_impl_that_was_found(
         // None, an then we check again inside the closure, but this
         // setup sort of minimized the number of calls and so form.
 
-        RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || {
-            RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || {
-                match (has_sub, has_sup) {
-                    (Some(n1), Some(n2)) => {
-                        if any_self_ty_has_vid {
-                            err.note(&format!(
-                                "`{}` would have to be implemented for the type `{}`, \
-                                 for any two lifetimes `'{}` and `'{}`",
-                                expected_trait_ref,
-                                expected_trait_ref.self_ty(),
-                                std::cmp::min(n1, n2),
-                                std::cmp::max(n1, n2),
-                            ));
-                        } else {
-                            err.note(&format!(
-                                "`{}` must implement `{}`, \
-                                 for any two lifetimes `'{}` and `'{}`",
-                                expected_trait_ref.self_ty(),
-                                expected_trait_ref,
-                                std::cmp::min(n1, n2),
-                                std::cmp::max(n1, n2),
-                            ));
-                        }
-                    }
-                    (Some(n), _) | (_, Some(n)) => {
-                        if any_self_ty_has_vid {
-                            err.note(&format!(
-                                "`{}` would have to be implemented for the type `{}`, \
-                                 for any lifetime `'{}`",
-                                expected_trait_ref,
-                                expected_trait_ref.self_ty(),
-                                n,
-                            ));
-                        } else {
-                            err.note(&format!(
-                                "`{}` must implement `{}`, for any lifetime `'{}`",
-                                expected_trait_ref.self_ty(),
-                                expected_trait_ref,
-                                n,
-                            ));
-                        }
-                    }
-                    (None, None) => RegionHighlightMode::maybe_highlighting_region(
-                        vid,
-                        expected_has_vid,
-                        || {
-                            if let Some(n) = expected_has_vid {
-                                err.note(&format!(
-                                    "`{}` would have to be implemented for the type `{}`, \
-                                     for some specific lifetime `'{}`",
-                                    expected_trait_ref,
-                                    expected_trait_ref.self_ty(),
-                                    n,
-                                ));
-                            } else {
-                                if any_self_ty_has_vid {
-                                    err.note(&format!(
-                                        "`{}` would have to be implemented for the type `{}`",
-                                        expected_trait_ref,
-                                        expected_trait_ref.self_ty(),
-                                    ));
-                                } else {
-                                    err.note(&format!(
-                                        "`{}` must implement `{}`",
-                                        expected_trait_ref.self_ty(),
-                                        expected_trait_ref,
-                                    ));
-                                }
-                            }
-                        },
-                    ),
-                }
-            })
-        });
+        let highlight_trait_ref = |trait_ref| Highlighted {
+            tcx: self.tcx(),
+            highlight: RegionHighlightMode::default(),
+            value: trait_ref,
+        };
 
-        RegionHighlightMode::maybe_highlighting_region(
-            vid,
-            actual_has_vid,
-            || match actual_has_vid {
-                Some(n) => {
-                    if any_self_ty_has_vid {
-                        err.note(&format!(
-                            "but `{}` is actually implemented for the type `{}`, \
-                             for some specific lifetime `'{}`",
-                            actual_trait_ref,
-                            actual_trait_ref.self_ty(),
-                            n
-                        ));
-                    } else {
-                        err.note(&format!(
-                            "but `{}` actually implements `{}`, for some specific lifetime `'{}`",
-                            actual_trait_ref.self_ty(),
-                            actual_trait_ref,
-                            n
-                        ));
+        let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
+        expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
+        expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
+        err.note(&{
+            let passive_voice = match (has_sub, has_sup) {
+                (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
+                (None, None) => {
+                    expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
+                    match expected_has_vid {
+                        Some(_) => true,
+                        None => any_self_ty_has_vid,
                     }
                 }
+            };
 
-                _ => {
-                    err.note(&format!(
-                        "but `{}` is actually implemented for the type `{}`",
-                        actual_trait_ref,
-                        actual_trait_ref.self_ty(),
-                    ));
+            let mut note = if passive_voice {
+                format!(
+                    "`{}` would have to be implemented for the type `{}`",
+                    expected_trait_ref,
+                    expected_trait_ref.map(|tr| tr.self_ty()),
+                )
+            } else {
+                format!(
+                    "`{}` must implement `{}`",
+                    expected_trait_ref.map(|tr| tr.self_ty()),
+                    expected_trait_ref,
+                )
+            };
+
+            match (has_sub, has_sup) {
+                (Some(n1), Some(n2)) => {
+                    let _ = write!(note,
+                        ", for any two lifetimes `'{}` and `'{}`",
+                        std::cmp::min(n1, n2),
+                        std::cmp::max(n1, n2),
+                    );
                 }
-            },
-        );
+                (Some(n), _) | (_, Some(n)) => {
+                    let _ = write!(note,
+                        ", for any lifetime `'{}`",
+                        n,
+                    );
+                }
+                (None, None) => if let Some(n) = expected_has_vid {
+                    let _ = write!(note,
+                        ", for some specific lifetime `'{}`",
+                        n,
+                    );
+                },
+            }
+
+            note
+        });
+
+        let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
+        actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
+        err.note(&{
+            let passive_voice = match actual_has_vid {
+                Some(_) => any_self_ty_has_vid,
+                None => true,
+            };
+
+            let mut note = if passive_voice {
+                format!(
+                    "but `{}` is actually implemented for the type `{}`",
+                    actual_trait_ref,
+                    actual_trait_ref.map(|tr| tr.self_ty()),
+                )
+            } else {
+                format!(
+                    "but `{}` actually implements `{}`",
+                    actual_trait_ref.map(|tr| tr.self_ty()),
+                    actual_trait_ref,
+                )
+            };
+
+            if let Some(n) = actual_has_vid {
+                let _ = write!(note, ", for some specific lifetime `'{}`", n);
+            }
+
+            note
+        });
     }
 }
index 986d65b2d9b6a374a3007f0775cb0a9c31dad505..28e21b28f7e449ded41274e47318778660f798d1 100644 (file)
@@ -47,6 +47,102 @@ pub fn with_crate_prefix<F: FnOnce() -> R, R>(f: F) -> R {
 // FIXME(eddyb) this module uses `pub(crate)` for things used only
 // from `ppaux` - when that is removed, they can be re-privatized.
 
+/// The "region highlights" are used to control region printing during
+/// specific error messages. When a "region highlight" is enabled, it
+/// gives an alternate way to print specific regions. For now, we
+/// always print those regions using a number, so something like "`'0`".
+///
+/// Regions not selected by the region highlight mode are presently
+/// unaffected.
+#[derive(Copy, Clone, Default)]
+pub struct RegionHighlightMode {
+    /// If enabled, when we see the selected region, use "`'N`"
+    /// instead of the ordinary behavior.
+    highlight_regions: [Option<(ty::RegionKind, usize)>; 3],
+
+    /// If enabled, when printing a "free region" that originated from
+    /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
+    /// have names print as normal.
+    ///
+    /// This is used when you have a signature like `fn foo(x: &u32,
+    /// y: &'a u32)` and we want to give a name to the region of the
+    /// reference `x`.
+    pub(crate) highlight_bound_region: Option<(ty::BoundRegion, usize)>,
+}
+
+impl RegionHighlightMode {
+    /// If `region` and `number` are both `Some`, invokes
+    /// `highlighting_region`.
+    pub fn maybe_highlighting_region(
+        &mut self,
+        region: Option<ty::Region<'_>>,
+        number: Option<usize>,
+    ) {
+        if let Some(k) = region {
+            if let Some(n) = number {
+                self.highlighting_region(k, n);
+            }
+        }
+    }
+
+    /// Highlights the region inference variable `vid` as `'N`.
+    pub fn highlighting_region(
+        &mut self,
+        region: ty::Region<'_>,
+        number: usize,
+    ) {
+        let num_slots = self.highlight_regions.len();
+        let first_avail_slot = self.highlight_regions.iter_mut()
+            .filter(|s| s.is_none())
+            .next()
+            .unwrap_or_else(|| {
+                bug!(
+                    "can only highlight {} placeholders at a time",
+                    num_slots,
+                )
+            });
+        *first_avail_slot = Some((*region, number));
+    }
+
+    /// Convenience wrapper for `highlighting_region`.
+    pub fn highlighting_region_vid(
+        &mut self,
+        vid: ty::RegionVid,
+        number: usize,
+    ) {
+        self.highlighting_region(&ty::ReVar(vid), number)
+    }
+
+    /// Returns `Some(n)` with the number to use for the given region, if any.
+    pub(crate) fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
+        self
+            .highlight_regions
+            .iter()
+            .filter_map(|h| match h {
+                Some((r, n)) if r == region => Some(*n),
+                _ => None,
+            })
+            .next()
+    }
+
+    /// Highlight the given bound region.
+    /// We can only highlight one bound region at a time. See
+    /// the field `highlight_bound_region` for more detailed notes.
+    pub fn highlighting_bound_region(
+        &mut self,
+        br: ty::BoundRegion,
+        number: usize,
+    ) {
+        assert!(self.highlight_bound_region.is_none());
+        self.highlight_bound_region = Some((br, number));
+    }
+
+    /// Returns `Some(N)` if the placeholder `p` is highlighted to print as "`'N`".
+    pub(crate) fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option<usize> {
+        self.region_highlighted(&ty::RePlaceholder(p))
+    }
+}
+
 struct LateBoundRegionNameCollector(FxHashSet<InternedString>);
 impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector {
     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
@@ -237,6 +333,10 @@ fn nest<'a, 'gcx, 'tcx, E>(
             config: self.config,
         })
     }
+
+    fn region_highlight_mode(&self) -> RegionHighlightMode {
+        RegionHighlightMode::default()
+    }
 }
 
 macro_rules! nest {
@@ -450,6 +550,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
 pub struct FmtPrinter<F: fmt::Write> {
     pub(crate) fmt: F,
     empty: bool,
+    pub region_highlight_mode: RegionHighlightMode,
 }
 
 impl<F: fmt::Write> FmtPrinter<F> {
@@ -457,6 +558,7 @@ pub fn new(fmt: F) -> Self {
         FmtPrinter {
             fmt,
             empty: true,
+            region_highlight_mode: RegionHighlightMode::default(),
         }
     }
 }
@@ -920,4 +1022,8 @@ fn nest<'a, 'gcx, 'tcx, E>(
             config: self.config,
         })
     }
+
+    fn region_highlight_mode(&self) -> RegionHighlightMode {
+        self.region_highlight_mode
+    }
 }
index ff5d9335909eee7fee9d5864872ef7ed4248db1e..d4111e0375f1613a12b09aff43915208937c6141 100644 (file)
@@ -12,7 +12,6 @@
 use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer};
 use crate::mir::interpret::ConstValue;
 
-use std::cell::Cell;
 use std::fmt::{self, Write as _};
 use std::iter;
 use std::usize;
 use syntax::symbol::{Symbol, InternedString};
 use crate::hir;
 
-/// The "region highlights" are used to control region printing during
-/// specific error messages. When a "region highlight" is enabled, it
-/// gives an alternate way to print specific regions. For now, we
-/// always print those regions using a number, so something like "`'0`".
-///
-/// Regions not selected by the region highlight mode are presently
-/// unaffected.
-#[derive(Copy, Clone, Default)]
-pub struct RegionHighlightMode {
-    /// If enabled, when we see the selected region, use "`'N`"
-    /// instead of the ordinary behavior.
-    highlight_regions: [Option<(ty::RegionKind, usize)>; 3],
-
-    /// If enabled, when printing a "free region" that originated from
-    /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
-    /// have names print as normal.
-    ///
-    /// This is used when you have a signature like `fn foo(x: &u32,
-    /// y: &'a u32)` and we want to give a name to the region of the
-    /// reference `x`.
-    highlight_bound_region: Option<(ty::BoundRegion, usize)>,
-}
-
-thread_local! {
-    /// Mechanism for highlighting of specific regions for display in NLL region inference errors.
-    /// Contains region to highlight and counter for number to use when highlighting.
-    static REGION_HIGHLIGHT_MODE: Cell<RegionHighlightMode> =
-        Cell::new(RegionHighlightMode::default())
-}
-
-impl RegionHighlightMode {
-    /// Reads and returns the current region highlight settings (accesses thread-local state).
-    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,
-        op: impl FnOnce() -> R,
-    ) -> R {
-        REGION_HIGHLIGHT_MODE.with(|c| {
-            c.set(new_mode);
-            let result = op();
-            c.set(old_mode);
-            result
-        })
-    }
-
-    /// If `region` and `number` are both `Some`, invokes
-    /// `highlighting_region`; otherwise, just invokes `op` directly.
-    pub fn maybe_highlighting_region<R>(
-        region: Option<ty::Region<'_>>,
-        number: Option<usize>,
-        op: impl FnOnce() -> R,
-    ) -> R {
-        if let Some(k) = region {
-            if let Some(n) = number {
-                return Self::highlighting_region(k, n, op);
-            }
-        }
-
-        op()
-    }
-
-    /// During the execution of `op`, highlights the region inference
-    /// variable `vid` as `'N`. We can only highlight one region `vid`
-    /// at a time.
-    pub fn highlighting_region<R>(
-        region: ty::Region<'_>,
-        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_regions.iter_mut()
-            .filter(|s| s.is_none())
-            .next()
-            .unwrap_or_else(|| {
-                panic!(
-                    "can only highlight {} placeholders at a time",
-                    old_mode.highlight_regions.len(),
-                )
-            });
-        *first_avail_slot = Some((*region, number));
-        Self::set(old_mode, new_mode, op)
-    }
-
-    /// Convenience wrapper for `highlighting_region`.
-    pub fn highlighting_region_vid<R>(
-        vid: ty::RegionVid,
-        number: usize,
-        op: impl FnOnce() -> R,
-    ) -> R {
-        Self::highlighting_region(&ty::ReVar(vid), number, op)
-    }
-
-    /// Returns `Some(n)` with the number to use for the given region, if any.
-    fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
-        Self::get()
-            .highlight_regions
-            .iter()
-            .filter_map(|h| match h {
-                Some((r, n)) if r == region => Some(*n),
-                _ => None,
-            })
-            .next()
-    }
-
-    /// During the execution of `op`, highlight the given bound
-    /// region. We can only highlight one bound region at a time. See
-    /// the field `highlight_bound_region` for more detailed notes.
-    pub fn highlighting_bound_region<R>(
-        br: ty::BoundRegion,
-        number: usize,
-        op: impl FnOnce() -> R,
-    ) -> R {
-        let old_mode = Self::get();
-        assert!(old_mode.highlight_bound_region.is_none());
-        Self::set(
-            old_mode,
-            Self {
-                highlight_bound_region: Some((br, number)),
-                ..old_mode
-            },
-            op,
-        )
-    }
-
-    /// Returns `Some(N)` if the placeholder `p` is highlighted to print as "`'N`".
-    pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option<usize> {
-        self.region_highlighted(&ty::RePlaceholder(p))
-    }
-}
-
 macro_rules! gen_display_debug_body {
     ( $with:path ) => {
         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -622,7 +485,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 }
             }
 
-            let highlight = RegionHighlightMode::get();
+            let highlight = cx.printer.region_highlight_mode();
             if let Some((region, counter)) = highlight.highlight_bound_region {
                 if *self == region {
                     p!(write("'{}", counter));
@@ -647,7 +510,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 //
 // NB: this must be kept in sync with the printing logic above.
 impl ty::BoundRegion {
-    fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
+    fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool
+        where P: PrettyPrinter
+    {
         if cx.config.is_verbose {
             return true;
         }
@@ -658,7 +523,7 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
             }
         }
 
-        let highlight = RegionHighlightMode::get();
+        let highlight = cx.printer.region_highlight_mode();
         if let Some((region, _)) = highlight.highlight_bound_region {
             if *self == region {
                 return true;
@@ -676,7 +541,7 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
                 return self.print_debug(cx);
             }
 
-            let highlight = RegionHighlightMode::get();
+            let highlight = cx.printer.region_highlight_mode();
             if let Some(counter) = highlight.placeholder_highlight(*self) {
                 p!(write("'{}", counter));
             } else {
@@ -690,12 +555,14 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
 //
 // NB: this must be kept in sync with the printing logic above.
 impl ty::PlaceholderRegion {
-    fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
+    fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool
+        where P: PrettyPrinter
+    {
         if cx.config.is_verbose {
             return true;
         }
 
-        let highlight = RegionHighlightMode::get();
+        let highlight = cx.printer.region_highlight_mode();
         if highlight.placeholder_highlight(*self).is_some() {
             return true;
         }
@@ -712,8 +579,8 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
             }
 
             // Watch out for region highlights.
-            if let Some(n) = RegionHighlightMode::get().region_highlighted(self) {
-                p!(write("'{:?}", n));
+            if let Some(n) = cx.printer.region_highlight_mode().region_highlighted(self) {
+                p!(write("'{}", n));
                 return Ok(cx.printer);
             }
 
@@ -780,12 +647,12 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
                 }
 
                 ty::ReLateBound(binder_id, ref bound_region) => {
-                    p!(write("ReLateBound({:?}, {:?})",
-                           binder_id,
-                           bound_region))
+                    p!(write("ReLateBound({:?}, ", binder_id),
+                       print_debug(bound_region),
+                       write(")"))
                 }
 
-                ty::ReFree(ref fr) => p!(write("{:?}", fr)),
+                ty::ReFree(ref fr) => p!(print_debug(fr)),
 
                 ty::ReScope(id) => {
                     p!(write("ReScope({:?})", id))
@@ -794,11 +661,11 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
                 ty::ReStatic => p!(write("ReStatic")),
 
                 ty::ReVar(ref vid) => {
-                    p!(write("{:?}", vid))
+                    p!(print_debug(vid))
                 }
 
                 ty::RePlaceholder(placeholder) => {
-                    p!(write("RePlaceholder({:?})", placeholder))
+                    p!(write("RePlaceholder("), print_debug(placeholder), write(")"))
                 }
 
                 ty::ReEmpty => p!(write("ReEmpty")),
@@ -817,12 +684,14 @@ fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
 // NB: this must be kept in sync with the printing logic above.
 impl ty::RegionKind {
     // HACK(eddyb) `pub(crate)` only for `ty::print`.
-    pub(crate) fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
+    pub(crate) fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool
+        where P: PrettyPrinter
+    {
         if cx.config.is_verbose {
             return true;
         }
 
-        if RegionHighlightMode::get().region_highlighted(self).is_some() {
+        if cx.printer.region_highlight_mode().region_highlighted(self).is_some() {
             return true;
         }
 
@@ -926,17 +795,17 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 return self.print_debug(cx);
             }
 
-            let highlight = RegionHighlightMode::get();
+            let highlight = cx.printer.region_highlight_mode();
             if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
-                p!(write("'{:?}", counter));
+                p!(write("'{}", counter));
             }
         }
         debug {
             // HACK(eddyb) this is duplicated from `display` printing,
             // to keep NLL borrowck working even with `-Zverbose`.
-            let highlight = RegionHighlightMode::get();
+            let highlight = cx.printer.region_highlight_mode();
             if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
-                p!(write("'{:?}", counter));
+                p!(write("'{}", counter));
             } else {
                 p!(write("'_#{}r", self.index()));
             }
@@ -948,12 +817,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 //
 // NB: this must be kept in sync with the printing logic above.
 impl ty::RegionVid {
-    fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool {
+    fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool
+        where P: PrettyPrinter
+    {
         if cx.config.is_verbose {
             return true;
         }
 
-        let highlight = RegionHighlightMode::get();
+        let highlight = cx.printer.region_highlight_mode();
         if highlight.region_highlighted(&ty::ReVar(*self)).is_some() {
             return true;
         }
@@ -1165,9 +1036,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                         // FIXME(eddyb) print this with `print_def_path`.
                         if let Some(first) = substs.next() {
                             p!(write("::<"));
-                            p!(write("{}", first));
+                            p!(print_display(first));
                             for subst in substs {
-                                p!(write(", {}", subst));
+                                p!(write(", "), print_display(subst));
                             }
                             p!(write(">"));
                         }
index aa3750946d366cf879d9f66f1b90c40acd04f9c2..9a80415827e89ff040fa9c060117d9b986596c58 100644 (file)
@@ -12,7 +12,7 @@
     TerminatorKind, VarBindingForm,
 };
 use rustc::ty::{self, DefIdTree};
-use rustc::util::ppaux::RegionHighlightMode;
+use rustc::ty::print::Print;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::sync::Lrc;
@@ -831,7 +831,7 @@ fn report_local_value_does_not_live_long_enough(
         );
 
         if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) {
-            let region_name = annotation.emit(&mut err);
+            let region_name = annotation.emit(self, &mut err);
 
             err.span_label(
                 borrow_span,
@@ -1875,7 +1875,7 @@ fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'t
     fn annotate_argument_and_return_for_borrow(
         &self,
         borrow: &BorrowData<'tcx>,
-    ) -> Option<AnnotatedBorrowFnSignature<'_>> {
+    ) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
         // Define a fallback for when we can't match a closure.
         let fallback = || {
             let is_closure = self.infcx.tcx.is_closure(self.mir_def_id);
@@ -2099,7 +2099,7 @@ fn annotate_fn_sig(
         &self,
         did: DefId,
         sig: ty::PolyFnSig<'tcx>,
-    ) -> Option<AnnotatedBorrowFnSignature<'_>> {
+    ) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
         debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
         let is_closure = self.infcx.tcx.is_closure(did);
         let fn_hir_id = self.infcx.tcx.hir().as_local_hir_id(did)?;
@@ -2245,7 +2245,11 @@ enum AnnotatedBorrowFnSignature<'tcx> {
 impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
     /// Annotate the provided diagnostic with information about borrow from the fn signature that
     /// helps explain.
-    fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
+    fn emit(
+        &self,
+        cx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
+        diag: &mut DiagnosticBuilder<'_>,
+    ) -> String {
         match self {
             AnnotatedBorrowFnSignature::Closure {
                 argument_ty,
@@ -2253,10 +2257,10 @@ fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
             } => {
                 diag.span_label(
                     *argument_span,
-                    format!("has type `{}`", self.get_name_for_ty(argument_ty, 0)),
+                    format!("has type `{}`", cx.get_name_for_ty(argument_ty, 0)),
                 );
 
-                self.get_region_name_for_ty(argument_ty, 0)
+                cx.get_region_name_for_ty(argument_ty, 0)
             }
             AnnotatedBorrowFnSignature::AnonymousFunction {
                 argument_ty,
@@ -2264,10 +2268,10 @@ fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
                 return_ty,
                 return_span,
             } => {
-                let argument_ty_name = self.get_name_for_ty(argument_ty, 0);
+                let argument_ty_name = cx.get_name_for_ty(argument_ty, 0);
                 diag.span_label(*argument_span, format!("has type `{}`", argument_ty_name));
 
-                let return_ty_name = self.get_name_for_ty(return_ty, 0);
+                let return_ty_name = cx.get_name_for_ty(return_ty, 0);
                 let types_equal = return_ty_name == argument_ty_name;
                 diag.span_label(
                     *return_span,
@@ -2286,7 +2290,7 @@ fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
                      lifetime-syntax.html#lifetime-elision>",
                 );
 
-                self.get_region_name_for_ty(return_ty, 0)
+                cx.get_region_name_for_ty(return_ty, 0)
             }
             AnnotatedBorrowFnSignature::NamedFunction {
                 arguments,
@@ -2294,7 +2298,7 @@ fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
                 return_span,
             } => {
                 // Region of return type and arguments checked to be the same earlier.
-                let region_name = self.get_region_name_for_ty(return_ty, 0);
+                let region_name = cx.get_region_name_for_ty(return_ty, 0);
                 for (_, argument_span) in arguments {
                     diag.span_label(*argument_span, format!("has lifetime `{}`", region_name));
                 }
@@ -2314,10 +2318,15 @@ fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String {
             }
         }
     }
+}
 
+impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     /// Return the name of the provided `Ty` (that must be a reference) with a synthesized lifetime
     /// name where required.
     fn get_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
+        let mut s = String::new();
+        let mut printer = ty::print::FmtPrinter::new(&mut s);
+
         // We need to add synthesized lifetimes where appropriate. We do
         // this by hooking into the pretty printer and telling it to label the
         // lifetimes without names with the value `'0`.
@@ -2327,28 +2336,41 @@ fn get_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
                 ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }),
                 _,
                 _,
-            ) => RegionHighlightMode::highlighting_bound_region(*br, counter, || ty.to_string()),
-            _ => ty.to_string(),
+            ) => printer.region_highlight_mode.highlighting_bound_region(*br, counter),
+            _ => {}
         }
+
+        let _ = ty::print::PrintCx::with(self.infcx.tcx, printer, |cx| {
+            ty.print(cx)
+        });
+        s
     }
 
     /// Returns the name of the provided `Ty` (that must be a reference)'s region with a
     /// synthesized lifetime name where required.
     fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
-        match ty.sty {
-            ty::TyKind::Ref(region, _, _) => match region {
-                ty::RegionKind::ReLateBound(_, br)
-                | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
-                    RegionHighlightMode::highlighting_bound_region(
-                        *br,
-                        counter,
-                        || region.to_string(),
-                    )
+        let mut s = String::new();
+        let mut printer = ty::print::FmtPrinter::new(&mut s);
+
+        let region = match ty.sty {
+            ty::TyKind::Ref(region, _, _) => {
+                match region {
+                    ty::RegionKind::ReLateBound(_, br)
+                    | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
+                        printer.region_highlight_mode.highlighting_bound_region(*br, counter)
+                    }
+                    _ => {}
                 }
-                _ => region.to_string(),
-            },
+
+                region
+            }
             _ => bug!("ty for annotation of borrow region is not a reference"),
-        }
+        };
+
+        let _ = ty::print::PrintCx::with(self.infcx.tcx, printer, |cx| {
+            region.print(cx)
+        });
+        s
     }
 }
 
index fdede054e15f304516dffe2c3c5d9f233c6363b7..362214d3257123d5b54de71737686a0f60fd5160 100644 (file)
@@ -8,7 +8,7 @@
 use rustc::mir::Mir;
 use rustc::ty::subst::{SubstsRef, UnpackedKind};
 use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt};
-use rustc::util::ppaux::RegionHighlightMode;
+use rustc::ty::print::RegionHighlightMode;
 use rustc_errors::DiagnosticBuilder;
 use syntax::ast::Name;
 use syntax::symbol::keywords;
@@ -396,9 +396,9 @@ fn give_name_if_we_cannot_match_hir_ty(
         argument_ty: Ty<'tcx>,
         counter: &mut usize,
     ) -> Option<RegionName> {
-        let type_name = RegionHighlightMode::highlighting_region_vid(needle_fr, *counter, || {
-            infcx.extract_type_name(&argument_ty)
-        });
+        let mut highlight = RegionHighlightMode::default();
+        highlight.highlighting_region_vid(needle_fr, *counter);
+        let type_name = infcx.extract_type_name(&argument_ty, Some(highlight));
 
         debug!(
             "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
@@ -680,9 +680,9 @@ fn give_name_if_anonymous_region_appears_in_output(
             return None;
         }
 
-        let type_name = RegionHighlightMode::highlighting_region_vid(
-            fr, *counter, || infcx.extract_type_name(&return_ty),
-        );
+        let mut highlight = RegionHighlightMode::default();
+        highlight.highlighting_region_vid(fr, *counter);
+        let type_name = infcx.extract_type_name(&return_ty, Some(highlight));
 
         let mir_node_id = tcx.hir().as_local_node_id(mir_def_id).expect("non-local mir");