Change:
In , adding an parameter to the type, that defaults to induces changes to UI tests that are indicative of something that seemed to need improvement in the compiler, namely that when you have a type , errors should present instead of when they can. It turns out, the compiler does. But not consistently. The following is derived from : () This yields the following errors: See how it prints instead of the (imho) desired , but , not .
This all stems from the fact that in some cases, types are just printed out by formatting the instances, while in other cases, there is manual machinery to highlight parts of the type that handle things, and that doesn't have the default-param elimination that has.

Discussion:
use super::region_constraints::GenericKind; use super::lexical_region_resolve::RegionResolutionError; <del> use std::fmt; </del> <ins> use std::{cmp, fmt}; </ins> use hir; use hir::map as hir_map; use hir::def_id::DefId; use middle::region; use traits::{ObligationCause, ObligationCauseCode}; <del> use ty::{self, Region, Ty, TyCtxt, TypeFoldable, TypeVariants}; </del> <ins> use ty::{self, subst::Subst, Region, Ty, TyCtxt, TypeFoldable, TypeVariants}; </ins> use ty::error::TypeError; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span};

} } <ins> /// For generic types with parameters with defaults, remove the parameters corresponding to /// the defaults. This repeats a lot of the logic found in `PrintContext::parameterized`. fn strip_generic_default_params( &self, def_id: DefId, substs: &ty::subst::Substs<'tcx> ) -> &'tcx ty::subst::Substs<'tcx> { let generics = self.tcx.generics_of(def_id); let mut num_supplied_defaults = 0; let mut type_params = generics.params.iter().rev().filter_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => None, ty::GenericParamDefKind::Type { has_default, .. } => { Some((param.def_id, has_default)) } }).peekable(); let has_default = { let has_default = type_params.peek().map(|(_, has_default)| has_default); *has_default.unwrap_or(&false) }; if has_default { let types = substs.types().rev(); for ((def_id, has_default), actual) in type_params.zip(types) { if !has_default { break; } if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual { break; } num_supplied_defaults += 1; } } let len = generics.params.len(); let mut generics = generics.clone(); generics.params.truncate(len - num_supplied_defaults); substs.truncate_to(self.tcx, &generics) } </ins> /// Compare 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) {

match (&t1.sty, &t2.sty) { (&ty::TyAdt(def1, sub1), &ty::TyAdt(def2, sub2)) => { <ins> let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1); let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2); </ins> let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new()); let path1 = self.tcx.item_path_str(def1.did.clone()); let path2 = self.tcx.item_path_str(def2.did.clone());

values.0.push_normal(path1); values.1.push_normal(path2); <ins> // Avoid printing out default generic parameters that are common to both // types. let len1 = sub_no_defaults_1.len(); let len2 = sub_no_defaults_2.len(); let common_len = cmp::min(len1, len2); let remainder1: Vec<_> = sub1.types().skip(common_len).collect(); let remainder2: Vec<_> = sub2.types().skip(common_len).collect(); let common_default_params = remainder1.iter().rev().zip(remainder2.iter().rev()) .filter(|(a, b)| a == b).count(); let len = sub1.len() - common_default_params; </ins> // Only draw `<...>` if there're lifetime/type arguments. <del> let len = sub1.len(); </del> if len > 0 { values.0.push_normal("<"); values.1.push_normal("<");

//         ^ elided type as this type argument was the same in both sides let type_arguments = sub1.types().zip(sub2.types()); let regions_len = sub1.regions().collect::<Vec<_>>().len(); <del> for (i, (ta1, ta2)) in type_arguments.enumerate() { </del> <ins> for (i, (ta1, ta2)) in type_arguments.take(len).enumerate() { </ins> let i = i + regions_len; if ta1 == ta2 { values.0.push_normal("_");

&mut values.0, &mut values.1, path1.clone(), <del> sub1, </del> <ins> sub_no_defaults_1, </ins> path2.clone(), &t2, ).is_some()

//     Bar<Qux> //     Foo<Bar<Qux>> //         ------- this type argument is exactly the same as the other type <del> if self.cmp_type_arg(&mut values.1, &mut values.0, path2, sub2, path1, &t1) .is_some() </del> <ins> if self.cmp_type_arg( &mut values.1, &mut values.0, path2, sub_no_defaults_2, path1, &t1, ).is_some() </ins> { return values; }

<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. trait Qux {} struct A; struct B; impl Qux for A {} impl Qux for B {} struct Foo<T, U: Qux = A, V: Qux = B>(T, U, V); struct foo; struct bar; fn want<T>(t: T) {} fn have_usize(f: usize) { want::<foo>(f); //~ ERROR mismatched types want::<bar>(f); //~ ERROR mismatched types want::<Foo<usize>>(f); //~ ERROR mismatched types want::<Foo<usize, B>>(f); //~ ERROR mismatched types want::<Foo<foo>>(f); //~ ERROR mismatched types want::<Foo<foo, B>>(f); //~ ERROR mismatched types want::<Foo<bar>>(f); //~ ERROR mismatched types want::<Foo<bar, B>>(f); //~ ERROR mismatched types } fn have_foo(f: foo) { want::<usize>(f); //~ ERROR mismatched types want::<bar>(f); //~ ERROR mismatched types want::<Foo<usize>>(f); //~ ERROR mismatched types want::<Foo<usize, B>>(f); //~ ERROR mismatched types want::<Foo<foo>>(f); //~ ERROR mismatched types want::<Foo<foo, B>>(f); //~ ERROR mismatched types want::<Foo<bar>>(f); //~ ERROR mismatched types want::<Foo<bar, B>>(f); //~ ERROR mismatched types } fn have_foo_foo(f: Foo<foo>) { want::<usize>(f); //~ ERROR mismatched types want::<foo>(f); //~ ERROR mismatched types want::<bar>(f); //~ ERROR mismatched types want::<Foo<usize>>(f); //~ ERROR mismatched types want::<Foo<usize, B>>(f); //~ ERROR mismatched types want::<Foo<foo, B>>(f); //~ ERROR mismatched types want::<Foo<bar>>(f); //~ ERROR mismatched types want::<Foo<bar, B>>(f); //~ ERROR mismatched types want::<&Foo<foo>>(f); //~ ERROR mismatched types want::<&Foo<foo, B>>(f); //~ ERROR mismatched types } fn have_foo_foo_b(f: Foo<foo, B>) { want::<usize>(f); //~ ERROR mismatched types want::<foo>(f); //~ ERROR mismatched types want::<bar>(f); //~ ERROR mismatched types want::<Foo<usize>>(f); //~ ERROR mismatched types want::<Foo<usize, B>>(f); //~ ERROR mismatched types want::<Foo<foo>>(f); //~ ERROR mismatched types want::<Foo<bar>>(f); //~ ERROR mismatched types want::<Foo<bar, B>>(f); //~ ERROR mismatched types want::<&Foo<foo>>(f); //~ ERROR mismatched types want::<&Foo<foo, B>>(f); //~ ERROR mismatched types } fn have_foo_foo_b_a(f: Foo<foo, B, A>) { want::<usize>(f); //~ ERROR mismatched types want::<foo>(f); //~ ERROR mismatched types want::<bar>(f); //~ ERROR mismatched types want::<Foo<usize>>(f); //~ ERROR mismatched types want::<Foo<usize, B>>(f); //~ ERROR mismatched types want::<Foo<foo>>(f); //~ ERROR mismatched types want::<Foo<foo, B>>(f); //~ ERROR mismatched types want::<Foo<bar>>(f); //~ ERROR mismatched types want::<Foo<bar, B>>(f); //~ ERROR mismatched types want::<&Foo<foo>>(f); //~ ERROR mismatched types want::<&Foo<foo, B>>(f); //~ ERROR mismatched types } fn main() {} </ins>

<ins> error[E0308]: mismatched types --> $DIR/type-mismatch.rs:25:17 | LL |     want::<foo>(f); //~ ERROR mismatched types |                 ^ expected struct `foo`, found usize | = note: expected type `foo` found type `usize` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:26:17 | LL |     want::<bar>(f); //~ ERROR mismatched types |                 ^ expected struct `bar`, found usize | = note: expected type `bar` found type `usize` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:27:24 | LL |     want::<Foo<usize>>(f); //~ ERROR mismatched types |                        ^ expected struct `Foo`, found usize | = note: expected type `Foo<usize>` found type `usize` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:28:27 | LL |     want::<Foo<usize, B>>(f); //~ ERROR mismatched types |                           ^ expected struct `Foo`, found usize | = note: expected type `Foo<usize, B>` found type `usize` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:29:22 | LL |     want::<Foo<foo>>(f); //~ ERROR mismatched types |                      ^ expected struct `Foo`, found usize | = note: expected type `Foo<foo>` found type `usize` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:30:25 | LL |     want::<Foo<foo, B>>(f); //~ ERROR mismatched types |                         ^ expected struct `Foo`, found usize | = note: expected type `Foo<foo, B>` found type `usize` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:31:22 | LL |     want::<Foo<bar>>(f); //~ ERROR mismatched types |                      ^ expected struct `Foo`, found usize | = note: expected type `Foo<bar>` found type `usize` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:32:25 | LL |     want::<Foo<bar, B>>(f); //~ ERROR mismatched types |                         ^ expected struct `Foo`, found usize | = note: expected type `Foo<bar, B>` found type `usize` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:36:19 | LL |     want::<usize>(f); //~ ERROR mismatched types |                   ^ expected usize, found struct `foo` | = note: expected type `usize` found type `foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:37:17 | LL |     want::<bar>(f); //~ ERROR mismatched types |                 ^ expected struct `bar`, found struct `foo` | = note: expected type `bar` found type `foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:38:24 | LL |     want::<Foo<usize>>(f); //~ ERROR mismatched types |                        ^ expected struct `Foo`, found struct `foo` | = note: expected type `Foo<usize>` found type `foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:39:27 | LL |     want::<Foo<usize, B>>(f); //~ ERROR mismatched types |                           ^ expected struct `Foo`, found struct `foo` | = note: expected type `Foo<usize, B>` found type `foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:40:22 | LL |     want::<Foo<foo>>(f); //~ ERROR mismatched types |                      ^ expected struct `Foo`, found struct `foo` | = note: expected type `Foo<foo>` found type `foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:41:25 | LL |     want::<Foo<foo, B>>(f); //~ ERROR mismatched types |                         ^ expected struct `Foo`, found struct `foo` | = note: expected type `Foo<foo, B>` found type `foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:42:22 | LL |     want::<Foo<bar>>(f); //~ ERROR mismatched types |                      ^ expected struct `Foo`, found struct `foo` | = note: expected type `Foo<bar>` found type `foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:43:25 | LL |     want::<Foo<bar, B>>(f); //~ ERROR mismatched types |                         ^ expected struct `Foo`, found struct `foo` | = note: expected type `Foo<bar, B>` found type `foo` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:47:19 | LL |     want::<usize>(f); //~ ERROR mismatched types |                   ^ expected usize, found struct `Foo` | = note: expected type `usize` found type `Foo<foo>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:48:17 | LL |     want::<foo>(f); //~ ERROR mismatched types |                 ^ expected struct `foo`, found struct `Foo` | = note: expected type `foo` found type `Foo<foo>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:49:17 | LL |     want::<bar>(f); //~ ERROR mismatched types |                 ^ expected struct `bar`, found struct `Foo` | = note: expected type `bar` found type `Foo<foo>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:50:24 | LL |     want::<Foo<usize>>(f); //~ ERROR mismatched types |                        ^ expected usize, found struct `foo` | = note: expected type `Foo<usize>` found type `Foo<foo>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:51:27 | LL |     want::<Foo<usize, B>>(f); //~ ERROR mismatched types |                           ^ expected usize, found struct `foo` | = note: expected type `Foo<usize, B>` found type `Foo<foo, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:52:25 | LL |     want::<Foo<foo, B>>(f); //~ ERROR mismatched types |                         ^ expected struct `B`, found struct `A` | = note: expected type `Foo<_, B>` found type `Foo<_, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:53:22 | LL |     want::<Foo<bar>>(f); //~ ERROR mismatched types |                      ^ expected struct `bar`, found struct `foo` | = note: expected type `Foo<bar>` found type `Foo<foo>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:54:25 | LL |     want::<Foo<bar, B>>(f); //~ ERROR mismatched types |                         ^ expected struct `bar`, found struct `foo` | = note: expected type `Foo<bar, B>` found type `Foo<foo, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:55:23 | LL |     want::<&Foo<foo>>(f); //~ ERROR mismatched types |                       ^ |                       | |                       expected &Foo<foo>, found struct `Foo` |                       help: consider borrowing here: `&f` | = note: expected type `&Foo<foo>` found type `Foo<foo>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:56:26 | LL |     want::<&Foo<foo, B>>(f); //~ ERROR mismatched types |                          ^ expected reference, found struct `Foo` | = note: expected type `&Foo<foo, B>` found type `Foo<foo>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:60:19 | LL |     want::<usize>(f); //~ ERROR mismatched types |                   ^ expected usize, found struct `Foo` | = note: expected type `usize` found type `Foo<foo, B>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:61:17 | LL |     want::<foo>(f); //~ ERROR mismatched types |                 ^ expected struct `foo`, found struct `Foo` | = note: expected type `foo` found type `Foo<foo, B>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:62:17 | LL |     want::<bar>(f); //~ ERROR mismatched types |                 ^ expected struct `bar`, found struct `Foo` | = note: expected type `bar` found type `Foo<foo, B>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:63:24 | LL |     want::<Foo<usize>>(f); //~ ERROR mismatched types |                        ^ expected usize, found struct `foo` | = note: expected type `Foo<usize, A>` found type `Foo<foo, B>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:64:27 | LL |     want::<Foo<usize, B>>(f); //~ ERROR mismatched types |                           ^ expected usize, found struct `foo` | = note: expected type `Foo<usize, _>` found type `Foo<foo, _>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:65:22 | LL |     want::<Foo<foo>>(f); //~ ERROR mismatched types |                      ^ expected struct `A`, found struct `B` | = note: expected type `Foo<_, A>` found type `Foo<_, B>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:66:22 | LL |     want::<Foo<bar>>(f); //~ ERROR mismatched types |                      ^ expected struct `bar`, found struct `foo` | = note: expected type `Foo<bar, A>` found type `Foo<foo, B>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:67:25 | LL |     want::<Foo<bar, B>>(f); //~ ERROR mismatched types |                         ^ expected struct `bar`, found struct `foo` | = note: expected type `Foo<bar, _>` found type `Foo<foo, _>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:68:23 | LL |     want::<&Foo<foo>>(f); //~ ERROR mismatched types |                       ^ expected &Foo<foo>, found struct `Foo` | = note: expected type `&Foo<foo>` found type `Foo<foo, B>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:69:26 | LL |     want::<&Foo<foo, B>>(f); //~ ERROR mismatched types |                          ^ |                          | |                          expected reference, found struct `Foo` |                          help: consider borrowing here: `&f` | = note: expected type `&Foo<foo, B>` found type `Foo<foo, B>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:73:19 | LL |     want::<usize>(f); //~ ERROR mismatched types |                   ^ expected usize, found struct `Foo` | = note: expected type `usize` found type `Foo<foo, B, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:74:17 | LL |     want::<foo>(f); //~ ERROR mismatched types |                 ^ expected struct `foo`, found struct `Foo` | = note: expected type `foo` found type `Foo<foo, B, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:75:17 | LL |     want::<bar>(f); //~ ERROR mismatched types |                 ^ expected struct `bar`, found struct `Foo` | = note: expected type `bar` found type `Foo<foo, B, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:76:24 | LL |     want::<Foo<usize>>(f); //~ ERROR mismatched types |                        ^ expected usize, found struct `foo` | = note: expected type `Foo<usize, A, B>` found type `Foo<foo, B, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:77:27 | LL |     want::<Foo<usize, B>>(f); //~ ERROR mismatched types |                           ^ expected usize, found struct `foo` | = note: expected type `Foo<usize, _, B>` found type `Foo<foo, _, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:78:22 | LL |     want::<Foo<foo>>(f); //~ ERROR mismatched types |                      ^ expected struct `A`, found struct `B` | = note: expected type `Foo<_, A, B>` found type `Foo<_, B, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:79:25 | LL |     want::<Foo<foo, B>>(f); //~ ERROR mismatched types |                         ^ expected struct `B`, found struct `A` | = note: expected type `Foo<_, _, B>` found type `Foo<_, _, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:80:22 | LL |     want::<Foo<bar>>(f); //~ ERROR mismatched types |                      ^ expected struct `bar`, found struct `foo` | = note: expected type `Foo<bar, A, B>` found type `Foo<foo, B, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:81:25 | LL |     want::<Foo<bar, B>>(f); //~ ERROR mismatched types |                         ^ expected struct `bar`, found struct `foo` | = note: expected type `Foo<bar, _, B>` found type `Foo<foo, _, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:82:23 | LL |     want::<&Foo<foo>>(f); //~ ERROR mismatched types |                       ^ expected &Foo<foo>, found struct `Foo` | = note: expected type `&Foo<foo>` found type `Foo<foo, B, A>` error[E0308]: mismatched types --> $DIR/type-mismatch.rs:83:26 | LL |     want::<&Foo<foo, B>>(f); //~ ERROR mismatched types |                          ^ expected reference, found struct `Foo` | = note: expected type `&Foo<foo, B>` found type `Foo<foo, B, A>` error: aborting due to 47 previous errors For more information about this error, try `rustc --explain E0308`. </ins>