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;
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,
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![(
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
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:
//
// 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
+ });
}
}
// 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 {
config: self.config,
})
}
+
+ fn region_highlight_mode(&self) -> RegionHighlightMode {
+ RegionHighlightMode::default()
+ }
}
macro_rules! nest {
pub struct FmtPrinter<F: fmt::Write> {
pub(crate) fmt: F,
empty: bool,
+ pub region_highlight_mode: RegionHighlightMode,
}
impl<F: fmt::Write> FmtPrinter<F> {
FmtPrinter {
fmt,
empty: true,
+ region_highlight_mode: RegionHighlightMode::default(),
}
}
}
config: self.config,
})
}
+
+ fn region_highlight_mode(&self) -> RegionHighlightMode {
+ self.region_highlight_mode
+ }
}
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 {
}
}
- 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));
//
// 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;
}
}
}
- let highlight = RegionHighlightMode::get();
+ let highlight = cx.printer.region_highlight_mode();
if let Some((region, _)) = highlight.highlight_bound_region {
if *self == region {
return true;
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 {
//
// 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;
}
}
// 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);
}
}
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))
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")),
// 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;
}
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()));
}
//
// 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;
}
// 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(">"));
}
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;
);
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,
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);
&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)?;
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,
} => {
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,
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,
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,
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));
}
}
}
}
+}
+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`.
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
}
}
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;
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={:?}",
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");