Skip to content

Commit 7e3d872

Browse files
authored
Rollup merge of #136415 - estebank:highlight-clarification, r=compiler-errors
Highlight clarifying information in "expected/found" error When the expected and found types have the same textual representation, we add clarifying in parentheses. We now visually highlight it in the output. Detect a corner case where the clarifying information would be the same for both types and skip it, as it doesn't add anything useful. ![Screenshot of the rustc highlighted output on the terminal](https://github.com/user-attachments/assets/aa4b9433-5332-4941-b2c2-1a43e5cadff7)
2 parents e066208 + c75e601 commit 7e3d872

File tree

6 files changed

+160
-27
lines changed

6 files changed

+160
-27
lines changed

compiler/rustc_errors/src/diagnostic.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,14 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
644644
found_label: &dyn fmt::Display,
645645
found: DiagStyledString,
646646
) -> &mut Self {
647-
self.note_expected_found_extra(expected_label, expected, found_label, found, &"", &"")
647+
self.note_expected_found_extra(
648+
expected_label,
649+
expected,
650+
found_label,
651+
found,
652+
DiagStyledString::normal(""),
653+
DiagStyledString::normal(""),
654+
)
648655
}
649656

650657
#[rustc_lint_diagnostics]
@@ -654,8 +661,8 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
654661
expected: DiagStyledString,
655662
found_label: &dyn fmt::Display,
656663
found: DiagStyledString,
657-
expected_extra: &dyn fmt::Display,
658-
found_extra: &dyn fmt::Display,
664+
expected_extra: DiagStyledString,
665+
found_extra: DiagStyledString,
659666
) -> &mut Self {
660667
let expected_label = expected_label.to_string();
661668
let expected_label = if expected_label.is_empty() {
@@ -680,10 +687,13 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
680687
expected_label
681688
))];
682689
msg.extend(expected.0);
683-
msg.push(StringPart::normal(format!("`{expected_extra}\n")));
690+
msg.push(StringPart::normal(format!("`")));
691+
msg.extend(expected_extra.0);
692+
msg.push(StringPart::normal(format!("\n")));
684693
msg.push(StringPart::normal(format!("{}{} `", " ".repeat(found_padding), found_label)));
685694
msg.extend(found.0);
686-
msg.push(StringPart::normal(format!("`{found_extra}")));
695+
msg.push(StringPart::normal(format!("`")));
696+
msg.extend(found_extra.0);
687697

688698
// For now, just attach these as notes.
689699
self.highlighted_note(msg);

compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs

+28-18
Original file line numberDiff line numberDiff line change
@@ -1722,32 +1722,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17221722
}
17231723
}
17241724
TypeError::Sorts(values) => {
1725-
let extra = expected == found;
1725+
let extra = expected == found
1726+
// Ensure that we don't ever say something like
1727+
// expected `impl Trait` (opaque type `impl Trait`)
1728+
// found `impl Trait` (opaque type `impl Trait`)
1729+
&& values.expected.sort_string(self.tcx)
1730+
!= values.found.sort_string(self.tcx);
17261731
let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
17271732
(true, ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) => {
17281733
let sm = self.tcx.sess.source_map();
17291734
let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
1730-
format!(
1735+
DiagStyledString::normal(format!(
17311736
" (opaque type at <{}:{}:{}>)",
17321737
sm.filename_for_diagnostics(&pos.file.name),
17331738
pos.line,
17341739
pos.col.to_usize() + 1,
1735-
)
1740+
))
17361741
}
17371742
(true, ty::Alias(ty::Projection, proj))
17381743
if self.tcx.is_impl_trait_in_trait(proj.def_id) =>
17391744
{
17401745
let sm = self.tcx.sess.source_map();
17411746
let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
1742-
format!(
1747+
DiagStyledString::normal(format!(
17431748
" (trait associated opaque type at <{}:{}:{}>)",
17441749
sm.filename_for_diagnostics(&pos.file.name),
17451750
pos.line,
17461751
pos.col.to_usize() + 1,
1747-
)
1752+
))
17481753
}
1749-
(true, _) => format!(" ({})", ty.sort_string(self.tcx)),
1750-
(false, _) => "".to_string(),
1754+
(true, _) => {
1755+
let mut s = DiagStyledString::normal(" (");
1756+
s.push_highlighted(ty.sort_string(self.tcx));
1757+
s.push_normal(")");
1758+
s
1759+
}
1760+
(false, _) => DiagStyledString::normal(""),
17511761
};
17521762
if !(values.expected.is_simple_text() && values.found.is_simple_text())
17531763
|| (exp_found.is_some_and(|ef| {
@@ -1764,23 +1774,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17641774
}
17651775
}))
17661776
{
1767-
if let Some(ExpectedFound { found: found_ty, .. }) = exp_found {
1777+
if let Some(ExpectedFound { found: found_ty, .. }) = exp_found
1778+
&& !self.tcx.ty_is_opaque_future(found_ty)
1779+
{
17681780
// `Future` is a special opaque type that the compiler
17691781
// will try to hide in some case such as `async fn`, so
17701782
// to make an error more use friendly we will
17711783
// avoid to suggest a mismatch type with a
17721784
// type that the user usually are not using
17731785
// directly such as `impl Future<Output = u8>`.
1774-
if !self.tcx.ty_is_opaque_future(found_ty) {
1775-
diag.note_expected_found_extra(
1776-
&expected_label,
1777-
expected,
1778-
&found_label,
1779-
found,
1780-
&sort_string(values.expected),
1781-
&sort_string(values.found),
1782-
);
1783-
}
1786+
diag.note_expected_found_extra(
1787+
&expected_label,
1788+
expected,
1789+
&found_label,
1790+
found,
1791+
sort_string(values.expected),
1792+
sort_string(values.found),
1793+
);
17841794
}
17851795
}
17861796
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ compile-flags: -Zunstable-options --error-format=human-unicode --color=always
2+
//@ only-linux
3+
// Ensure that when we have a type error where both types have the same textual representation, the
4+
// diagnostic machinery highlights the clarifying comment that comes after in parentheses.
5+
trait Foo: Copy + ToString {}
6+
7+
impl<T: Copy + ToString> Foo for T {}
8+
9+
fn hide<T: Foo>(x: T) -> impl Foo {
10+
x
11+
}
12+
13+
fn main() {
14+
let mut x = (hide(0_u32), hide(0_i32));
15+
x = (x.1, x.0);
16+
}
Loading

tests/ui/impl-trait/impl-trait-in-macro.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ LL | let mut a = x;
1212
LL | a = y;
1313
| ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
1414
|
15-
= note: expected type parameter `impl Debug` (type parameter `impl Debug`)
16-
found type parameter `impl Debug` (type parameter `impl Debug`)
15+
= note: expected type parameter `impl Debug`
16+
found type parameter `impl Debug`
1717
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
1818
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
1919

tests/ui/impl-trait/universal-two-impl-traits.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ LL | let mut a = x;
1010
LL | a = y;
1111
| ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
1212
|
13-
= note: expected type parameter `impl Debug` (type parameter `impl Debug`)
14-
found type parameter `impl Debug` (type parameter `impl Debug`)
13+
= note: expected type parameter `impl Debug`
14+
found type parameter `impl Debug`
1515
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
1616
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
1717

0 commit comments

Comments
 (0)