Skip to content

Commit 0d7f259

Browse files
committed
rustc: don't keep RegionHighlightMode in a thread-local.
1 parent 2cfca91 commit 0d7f259

File tree

6 files changed

+335
-307
lines changed

6 files changed

+335
-307
lines changed

src/librustc/infer/error_reporting/need_type_info.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use hir::intravisit::{self, Visitor, NestedVisitorMap};
33
use infer::InferCtxt;
44
use infer::type_variable::TypeVariableOrigin;
55
use ty::{self, Ty, Infer, TyVar};
6+
use ty::print::Print;
67
use syntax::source_map::CompilerDesugaringKind;
78
use syntax_pos::Span;
89
use errors::DiagnosticBuilder;
@@ -64,18 +65,28 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
6465

6566

6667
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
67-
pub fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
68+
pub fn extract_type_name(
69+
&self,
70+
ty: &'a Ty<'tcx>,
71+
highlight: Option<ty::print::RegionHighlightMode>,
72+
) -> String {
6873
if let ty::Infer(ty::TyVar(ty_vid)) = (*ty).sty {
6974
let ty_vars = self.type_variables.borrow();
7075
if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
7176
*ty_vars.var_origin(ty_vid) {
72-
name.to_string()
73-
} else {
74-
ty.to_string()
77+
return name.to_string();
7578
}
76-
} else {
77-
ty.to_string()
7879
}
80+
81+
let mut s = String::new();
82+
let mut printer = ty::print::FmtPrinter::new(&mut s);
83+
if let Some(highlight) = highlight {
84+
printer.region_highlight_mode = highlight;
85+
}
86+
let _ = ty::print::PrintCx::with(self.tcx, printer, |cx| {
87+
ty.print(cx)
88+
});
89+
s
7990
}
8091

8192
pub fn need_type_info_err(&self,
@@ -84,7 +95,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
8495
ty: Ty<'tcx>)
8596
-> DiagnosticBuilder<'gcx> {
8697
let ty = self.resolve_type_vars_if_possible(&ty);
87-
let name = self.extract_type_name(&ty);
98+
let name = self.extract_type_name(&ty, None);
8899

89100
let mut err_span = span;
90101
let mut labels = vec![(

src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs

Lines changed: 124 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ use infer::lexical_region_resolve::RegionResolutionError;
55
use infer::ValuePairs;
66
use infer::{SubregionOrigin, TypeTrace};
77
use traits::{ObligationCause, ObligationCauseCode};
8-
use ty;
8+
use ty::{self, TyCtxt};
99
use ty::error::ExpectedFound;
1010
use ty::subst::Substs;
11+
use ty::print::{Print, RegionHighlightMode, FmtPrinter};
1112
use util::common::ErrorReported;
12-
use util::ppaux::RegionHighlightMode;
13+
14+
use std::fmt::{self, Write};
1315

1416
impl NiceRegionError<'me, 'gcx, 'tcx> {
1517
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
@@ -311,13 +313,48 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
311313
sup_placeholder: Option<ty::Region<'tcx>>,
312314
has_sub: Option<usize>,
313315
has_sup: Option<usize>,
314-
expected_trait_ref: ty::TraitRef<'_>,
315-
actual_trait_ref: ty::TraitRef<'_>,
316+
expected_trait_ref: ty::TraitRef<'tcx>,
317+
actual_trait_ref: ty::TraitRef<'tcx>,
316318
vid: Option<ty::Region<'tcx>>,
317319
expected_has_vid: Option<usize>,
318320
actual_has_vid: Option<usize>,
319321
any_self_ty_has_vid: bool,
320322
) {
323+
// HACK(eddyb) maybe move this in a more central location.
324+
#[derive(Copy, Clone)]
325+
struct Highlighted<'a, 'gcx, 'tcx, T> {
326+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
327+
highlight: RegionHighlightMode,
328+
value: T,
329+
}
330+
331+
impl<'a, 'gcx, 'tcx, T> Highlighted<'a, 'gcx, 'tcx, T> {
332+
fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'a, 'gcx, 'tcx, U> {
333+
Highlighted {
334+
tcx: self.tcx,
335+
highlight: self.highlight,
336+
value: f(self.value),
337+
}
338+
}
339+
}
340+
341+
impl<'tcx, T> fmt::Display for Highlighted<'_, '_, 'tcx, T>
342+
where T: for<'a, 'b> Print<'tcx,
343+
FmtPrinter<&'a mut fmt::Formatter<'b>>,
344+
Error = fmt::Error,
345+
>,
346+
{
347+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
348+
let mut printer = ty::print::FmtPrinter::new(f);
349+
printer.region_highlight_mode = self.highlight;
350+
351+
ty::print::PrintCx::with(self.tcx, printer, |cx| {
352+
self.value.print(cx)?;
353+
Ok(())
354+
})
355+
}
356+
}
357+
321358
// The weird thing here with the `maybe_highlighting_region` calls and the
322359
// the match inside is meant to be like this:
323360
//
@@ -333,112 +370,93 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
333370
// None, an then we check again inside the closure, but this
334371
// setup sort of minimized the number of calls and so form.
335372

336-
RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || {
337-
RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || {
338-
match (has_sub, has_sup) {
339-
(Some(n1), Some(n2)) => {
340-
if any_self_ty_has_vid {
341-
err.note(&format!(
342-
"`{}` would have to be implemented for the type `{}`, \
343-
for any two lifetimes `'{}` and `'{}`",
344-
expected_trait_ref,
345-
expected_trait_ref.self_ty(),
346-
std::cmp::min(n1, n2),
347-
std::cmp::max(n1, n2),
348-
));
349-
} else {
350-
err.note(&format!(
351-
"`{}` must implement `{}`, \
352-
for any two lifetimes `'{}` and `'{}`",
353-
expected_trait_ref.self_ty(),
354-
expected_trait_ref,
355-
std::cmp::min(n1, n2),
356-
std::cmp::max(n1, n2),
357-
));
358-
}
359-
}
360-
(Some(n), _) | (_, Some(n)) => {
361-
if any_self_ty_has_vid {
362-
err.note(&format!(
363-
"`{}` would have to be implemented for the type `{}`, \
364-
for any lifetime `'{}`",
365-
expected_trait_ref,
366-
expected_trait_ref.self_ty(),
367-
n,
368-
));
369-
} else {
370-
err.note(&format!(
371-
"`{}` must implement `{}`, for any lifetime `'{}`",
372-
expected_trait_ref.self_ty(),
373-
expected_trait_ref,
374-
n,
375-
));
376-
}
377-
}
378-
(None, None) => RegionHighlightMode::maybe_highlighting_region(
379-
vid,
380-
expected_has_vid,
381-
|| {
382-
if let Some(n) = expected_has_vid {
383-
err.note(&format!(
384-
"`{}` would have to be implemented for the type `{}`, \
385-
for some specific lifetime `'{}`",
386-
expected_trait_ref,
387-
expected_trait_ref.self_ty(),
388-
n,
389-
));
390-
} else {
391-
if any_self_ty_has_vid {
392-
err.note(&format!(
393-
"`{}` would have to be implemented for the type `{}`",
394-
expected_trait_ref,
395-
expected_trait_ref.self_ty(),
396-
));
397-
} else {
398-
err.note(&format!(
399-
"`{}` must implement `{}`",
400-
expected_trait_ref.self_ty(),
401-
expected_trait_ref,
402-
));
403-
}
404-
}
405-
},
406-
),
407-
}
408-
})
409-
});
373+
let highlight_trait_ref = |trait_ref| Highlighted {
374+
tcx: self.tcx(),
375+
highlight: RegionHighlightMode::default(),
376+
value: trait_ref,
377+
};
410378

411-
RegionHighlightMode::maybe_highlighting_region(
412-
vid,
413-
actual_has_vid,
414-
|| match actual_has_vid {
415-
Some(n) => {
416-
if any_self_ty_has_vid {
417-
err.note(&format!(
418-
"but `{}` is actually implemented for the type `{}`, \
419-
for some specific lifetime `'{}`",
420-
actual_trait_ref,
421-
actual_trait_ref.self_ty(),
422-
n
423-
));
424-
} else {
425-
err.note(&format!(
426-
"but `{}` actually implements `{}`, for some specific lifetime `'{}`",
427-
actual_trait_ref.self_ty(),
428-
actual_trait_ref,
429-
n
430-
));
379+
let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
380+
expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
381+
expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
382+
err.note(&{
383+
let passive_voice = match (has_sub, has_sup) {
384+
(Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
385+
(None, None) => {
386+
expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
387+
match expected_has_vid {
388+
Some(_) => true,
389+
None => any_self_ty_has_vid,
431390
}
432391
}
392+
};
433393

434-
_ => {
435-
err.note(&format!(
436-
"but `{}` is actually implemented for the type `{}`",
437-
actual_trait_ref,
438-
actual_trait_ref.self_ty(),
439-
));
394+
let mut note = if passive_voice {
395+
format!(
396+
"`{}` would have to be implemented for the type `{}`",
397+
expected_trait_ref,
398+
expected_trait_ref.map(|tr| tr.self_ty()),
399+
)
400+
} else {
401+
format!(
402+
"`{}` must implement `{}`",
403+
expected_trait_ref.map(|tr| tr.self_ty()),
404+
expected_trait_ref,
405+
)
406+
};
407+
408+
match (has_sub, has_sup) {
409+
(Some(n1), Some(n2)) => {
410+
let _ = write!(note,
411+
", for any two lifetimes `'{}` and `'{}`",
412+
std::cmp::min(n1, n2),
413+
std::cmp::max(n1, n2),
414+
);
440415
}
441-
},
442-
);
416+
(Some(n), _) | (_, Some(n)) => {
417+
let _ = write!(note,
418+
", for any lifetime `'{}`",
419+
n,
420+
);
421+
}
422+
(None, None) => if let Some(n) = expected_has_vid {
423+
let _ = write!(note,
424+
", for some specific lifetime `'{}`",
425+
n,
426+
);
427+
},
428+
}
429+
430+
note
431+
});
432+
433+
let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
434+
actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
435+
err.note(&{
436+
let passive_voice = match actual_has_vid {
437+
Some(_) => any_self_ty_has_vid,
438+
None => true,
439+
};
440+
441+
let mut note = if passive_voice {
442+
format!(
443+
"but `{}` is actually implemented for the type `{}`",
444+
actual_trait_ref,
445+
actual_trait_ref.map(|tr| tr.self_ty()),
446+
)
447+
} else {
448+
format!(
449+
"but `{}` actually implements `{}`",
450+
actual_trait_ref.map(|tr| tr.self_ty()),
451+
actual_trait_ref,
452+
)
453+
};
454+
455+
if let Some(n) = actual_has_vid {
456+
let _ = write!(note, ", for some specific lifetime `'{}`", n);
457+
}
458+
459+
note
460+
});
443461
}
444462
}

0 commit comments

Comments
 (0)