From: Eduard-Mihai Burtescu Date: Fri, 11 Jan 2019 11:07:01 +0000 (+0200) Subject: rustc: don't keep RegionHighlightMode in a thread-local. X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=cafd83d1d5f81ac1ed74bf97a950120505009a23;p=rust.git rustc: don't keep RegionHighlightMode in a thread-local. --- diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 9e0e48e4741..26deecfdbf0 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -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, + ) -> 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![( diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 189ecf53e0e..65fcc69a338 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -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>, has_sub: Option, has_sup: Option, - expected_trait_ref: ty::TraitRef<'_>, - actual_trait_ref: ty::TraitRef<'_>, + expected_trait_ref: ty::TraitRef<'tcx>, + actual_trait_ref: ty::TraitRef<'tcx>, vid: Option>, expected_has_vid: Option, actual_has_vid: Option, 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(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 + }); } } diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 986d65b2d9b..28e21b28f7e 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -47,6 +47,102 @@ pub fn with_crate_prefix 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>, + number: Option, + ) { + 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 { + 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 { + self.region_highlighted(&ty::RePlaceholder(p)) + } +} + struct LateBoundRegionNameCollector(FxHashSet); 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 { pub struct FmtPrinter { pub(crate) fmt: F, empty: bool, + pub region_highlight_mode: RegionHighlightMode, } impl FmtPrinter { @@ -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 + } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index ff5d9335909..d4111e0375f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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; @@ -22,142 +21,6 @@ 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 = - 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( - 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( - region: Option>, - number: Option, - 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( - 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( - 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 { - 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( - 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 { - 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

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { + fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool + where P: PrettyPrinter + { if cx.config.is_verbose { return true; } @@ -658,7 +523,7 @@ fn display_outputs_anything

(&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

(&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

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { // // NB: this must be kept in sync with the printing logic above. impl ty::PlaceholderRegion { - fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { + fn display_outputs_anything

(&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

(&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

(&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

(&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

(&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

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { + pub(crate) fn display_outputs_anything

(&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

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { + fn display_outputs_anything

(&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(">")); } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index aa3750946d3..9a80415827e 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -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> { + ) -> Option> { // 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> { + ) -> Option> { 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 } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index fdede054e15..362214d3257 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -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 { - 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");