提交 cafd83d1 编写于 作者: E Eduard-Mihai Burtescu

rustc: don't keep RegionHighlightMode in a thread-local.

上级 7c4eecef
......@@ -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![(
......
......@@ -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
});
}
}
......@@ -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
}
}
......@@ -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<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(">"));
}
......
......@@ -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
}
}
......
......@@ -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");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册