Change:
On E0308 type mismatch errors we already perform a basic check to type arguments in order to only highlight differences between the expected and found type. I recently came across a case where the two types had identifiers of the same length with no type arguments, but that were not local so the path was quite long. It took me some time to realize that the two types were actually different and not caused by different crate versions. It'd be nice if for the following, only the parts of the path that differ were highlighted/bolded in the CLI output: CC
Hello, I'd like to implement this feature.
Hi Will you be needing a hand? To begin with, I would recommend searching for in order to find how it works today. Particularly, shows how the highlighting for specific type arguments is currently handled. It is extremely verbose, but the comments should help somewhat. Also, the is a good primer on how to develop in the compiler's codebase. If you need a hand, don't hesitate to reach out.
Thanks, I'd found that struct and file, but I'd overlooked that method due to how complicated it seemed at a glance.
Should I add a test for this? If so, how would I implement that? The standard UI testing method doesn't seem to track highlights.
sadly, we do not have any way to test correct application of colors in the test suite. Attach screenshots to the PR so that we can see the changes, but we have to rely on being extra careful when touching this part of the codebase.

Discussion:
/// Compares two given types, eliding parts that are the same between them and highlighting /// relevant differences, and return two representation of those types for highlighted printing. fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString) { <ins> debug!("cmp(t1={}, t1.kind={:?}, t2={}, t2.kind={:?})", t1, t1.kind, t2, t2.kind); // helper functions </ins> fn equals<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { match (&a.kind, &b.kind) { (a, b) if *a == *b => true,

s.push_normal(ty.to_string()); } <ins> // process starts here </ins> match (&t1.kind, &t2.kind) { (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => { let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1);

return values; } <del> // We couldn't find anything in common, highlight everything. //     let x: Bar<Qux> = y::<Foo<Zar>>(); ( DiagnosticStyledString::highlighted(t1.to_string()), DiagnosticStyledString::highlighted(t2.to_string()), ) </del> <ins> // We can't find anything in common, highlight relevant part of type path. //     let x: foo::bar::Baz<Qux> = y:<foo::bar::Bar<Zar>>(); //     foo::bar::Baz<Qux> //     foo::bar::Bar<Zar> //               -------- this part of the path is different let t1_str = t1.to_string(); let t2_str = t2.to_string(); let min_len = t1_str.len().min(t2_str.len()); const SEPARATOR: &str = "::"; let separator_len = SEPARATOR.len(); let split_idx: usize = t1_str.split(SEPARATOR) .zip(t2_str.split(SEPARATOR)) .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str) .map(|(mod_str, _)| mod_str.len() + separator_len) .sum(); debug!("cmp: separator_len={}, split_idx={}, min_len={}", separator_len, split_idx, min_len ); if split_idx >= min_len { // paths are identical, highlight everything ( DiagnosticStyledString::highlighted(t1_str), DiagnosticStyledString::highlighted(t2_str) ) } else { let (common, uniq1) = t1_str.split_at(split_idx); let (_, uniq2) = t2_str.split_at(split_idx); debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2); values.0.push_normal(common); values.0.push_highlighted(uniq1); values.1.push_normal(common); values.1.push_highlighted(uniq2); values } </ins> } }

_ => {} } <ins> debug!("note_type_err(diag={:?})", diag); </ins> let (expected_found, exp_found, is_simple_error) = match values { None => (None, None, false), Some(values) => {

); } (_, false, _) => { <ins> debug!( "note_type_err: exp_found={:?}, expected={:?} found={:?}", exp_found, expected, found ); </ins> if let Some(exp_found) = exp_found { self.suggest_as_ref_where_appropriate(span, &exp_found, diag); }

pub render_span: Option<MultiSpan>, } <del> #[derive(PartialEq, Eq)] </del> <ins> #[derive(Debug, PartialEq, Eq)] </ins> pub struct DiagnosticStyledString(pub Vec<StringPart>); impl DiagnosticStyledString {

} } <del> #[derive(PartialEq, Eq)] </del> <ins> #[derive(Debug, PartialEq, Eq)] </ins> pub enum StringPart { Normal(String), Highlighted(String),