From 6a30ce639f9eeba7d085721d219553635f32c280 Mon Sep 17 00:00:00 2001 From: Dmitry Kadashev Date: Thu, 31 Oct 2019 16:57:29 +0700 Subject: [PATCH 1/4] Add type parameter name to type mismatch error messages Part of #47319. This just adds type parameter name to type mismatch error message, so e.g. the following: ``` expected enum `std::option::Option`, found type parameter ``` becomes ``` expected enum `std::option::Option`, found type parameter `T` ``` --- src/librustc/ty/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 77613b548cf..4ef6a162c8b 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -241,7 +241,7 @@ impl<'tcx> ty::TyS<'tcx> { ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(), ty::Projection(_) => "associated type".into(), ty::UnnormalizedProjection(_) => "non-normalized associated type".into(), - ty::Param(_) => "type parameter".into(), + ty::Param(p) => format!("type parameter `{}`", p).into(), ty::Opaque(..) => "opaque type".into(), ty::Error => "type error".into(), } From 036f1828041c80842129b28695b60ba31a74403a Mon Sep 17 00:00:00 2001 From: Dmitry Kadashev Date: Thu, 31 Oct 2019 17:20:33 +0700 Subject: [PATCH 2/4] Show type param definitions in type mismatch errors Fixes #47319. Shows the type parameter definition(s) on type mismatch errors so the context is clearer. Pretty much changes the following: ``` LL | bar1(t); | ^ | | | expected enum `std::option::Option`, found type parameter `T` ``` into: ``` LL | fn foo1(t: T) { | - this type parameter LL | bar1(t); | ^ | | | expected enum `std::option::Option`, found type parameter `T` ``` --- src/librustc/infer/error_reporting/mod.rs | 10 +++++++++- src/librustc/ty/error.rs | 19 +++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index a50cc86862e..57cb9564f71 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1190,8 +1190,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + // In some (most?) cases cause.body_id points to actual body, but in some cases + // it's a actual definition. According to the comments (e.g. in + // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter + // is relied upon by some other code. This might (or might not) need cleanup. + let body_owner_def_id = match self.tcx.hir().opt_local_def_id(cause.body_id) { + Some(def_id) => def_id, + None => self.tcx.hir().body_owner_def_id(hir::BodyId{hir_id: cause.body_id}), + }; self.check_and_note_conflicting_crates(diag, terr, span); - self.tcx.note_and_explain_type_err(diag, terr, span); + self.tcx.note_and_explain_type_err(diag, terr, span, body_owner_def_id); // It reads better to have the error origin as the final // thing. diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 4ef6a162c8b..768487fb162 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -254,6 +254,7 @@ impl<'tcx> TyCtxt<'tcx> { db: &mut DiagnosticBuilder<'_>, err: &TypeError<'tcx>, sp: Span, + body_owner_def_id: DefId, ) { use self::TypeError::*; @@ -288,7 +289,16 @@ impl<'tcx> TyCtxt<'tcx> { ); } }, - (ty::Param(_), ty::Param(_)) => { + (ty::Param(expected), ty::Param(found)) => { + let generics = self.generics_of(body_owner_def_id); + db.span_label( + self.def_span(generics.type_param(expected, self).def_id), + "expected type parameter" + ); + db.span_label( + self.def_span(generics.type_param(found, self).def_id), + "found type parameter" + ); db.note("a type parameter was expected, but a different one was found; \ you might be missing a type parameter or trait bound"); db.note("for more information, visit \ @@ -301,7 +311,12 @@ impl<'tcx> TyCtxt<'tcx> { (ty::Param(_), ty::Projection(_)) | (ty::Projection(_), ty::Param(_)) => { db.note("you might be missing a type parameter or trait bound"); } - (ty::Param(_), _) | (_, ty::Param(_)) => { + (ty::Param(p), _) | (_, ty::Param(p)) => { + let generics = self.generics_of(body_owner_def_id); + db.span_label( + self.def_span(generics.type_param(p, self).def_id), + "this type parameter" + ); db.help("type parameters must be constrained to match other types"); if self.sess.teach(&db.get_code().unwrap()) { db.help("given a type parameter `T` and a method `foo`: From 4e10b75951e5ab7975952826a7591f8eca77e423 Mon Sep 17 00:00:00 2001 From: Dmitry Kadashev Date: Fri, 1 Nov 2019 10:58:37 +0700 Subject: [PATCH 3/4] Update tests Update the tests to reflect changes to how type mismatch errors are reported (two previous commits). --- .../associated-types-issue-20346.stderr | 5 +++- .../reordered-type-param.stderr | 5 +++- .../impl-generic-mismatch-ab.stderr | 6 +++- .../universal-mismatched-type.stderr | 6 ++-- .../universal-two-impl-traits.stderr | 11 +++++-- src/test/ui/issues/issue-13853.stderr | 4 +-- src/test/ui/issues/issue-20225.stderr | 13 ++++++-- src/test/ui/issues/issue-24204.stderr | 2 +- src/test/ui/issues/issue-2951.rs | 2 +- src/test/ui/issues/issue-2951.stderr | 7 ++++- .../ui/mismatched_types/issue-35030.stderr | 7 +++-- .../struct-path-self-type-mismatch.stderr | 15 ++++++++-- src/test/ui/structs/struct-path-self.stderr | 6 ++-- .../enum-variant-generic-args.stderr | 30 +++++++++++++++---- src/test/ui/type/type-parameter-names.rs | 2 +- src/test/ui/type/type-parameter-names.stderr | 7 +++-- .../type/type-params-in-different-spaces-1.rs | 2 +- .../type-params-in-different-spaces-1.stderr | 12 ++++++-- .../type-params-in-different-spaces-3.stderr | 14 ++++++--- 19 files changed, 116 insertions(+), 40 deletions(-) diff --git a/src/test/ui/associated-types/associated-types-issue-20346.stderr b/src/test/ui/associated-types/associated-types-issue-20346.stderr index b763b82d540..f5053f6a1c0 100644 --- a/src/test/ui/associated-types/associated-types-issue-20346.stderr +++ b/src/test/ui/associated-types/associated-types-issue-20346.stderr @@ -4,8 +4,11 @@ error[E0271]: type mismatch resolving ` as Iterator>::Item == std::op LL | fn is_iterator_of>(_: &I) {} | -------------- ------ required by this bound in `is_iterator_of` ... +LL | fn test_adapter>>(it: I) { + | - this type parameter +... LL | is_iterator_of::, _>(&adapter); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found type parameter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found type parameter `T` | = note: expected type `std::option::Option` found type `T` diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr index 8176e96d6de..326b84470d6 100644 --- a/src/test/ui/compare-method/reordered-type-param.stderr +++ b/src/test/ui/compare-method/reordered-type-param.stderr @@ -5,7 +5,10 @@ LL | fn b(&self, x: C) -> C; | - type in trait ... LL | fn b(&self, _x: G) -> G { panic!() } - | ^ expected type parameter, found a different type parameter + | - - ^ expected type parameter `F`, found type parameter `G` + | | | + | | found type parameter + | expected type parameter | = note: expected type `fn(&E, F) -> F` found type `fn(&E, G) -> G` diff --git a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr index e4d0a731ebf..84fc66bb94c 100644 --- a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr +++ b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr @@ -5,7 +5,11 @@ LL | fn foo(&self, a: &A, b: &impl Debug); | -- type in trait ... LL | fn foo(&self, a: &impl Debug, b: &B) { } - | ^^^^^^^^^^^ expected type parameter, found a different type parameter + | - ^---------- + | | || + | | |found type parameter + | | expected type parameter `B`, found type parameter `impl Debug` + | expected type parameter | = note: expected type `fn(&(), &B, &impl Debug)` found type `fn(&(), &impl Debug, &B)` diff --git a/src/test/ui/impl-trait/universal-mismatched-type.stderr b/src/test/ui/impl-trait/universal-mismatched-type.stderr index d92c3f034e5..ae20a5aa883 100644 --- a/src/test/ui/impl-trait/universal-mismatched-type.stderr +++ b/src/test/ui/impl-trait/universal-mismatched-type.stderr @@ -2,9 +2,11 @@ error[E0308]: mismatched types --> $DIR/universal-mismatched-type.rs:4:5 | LL | fn foo(x: impl Debug) -> String { - | ------ expected `std::string::String` because of return type + | ---------- ------ expected `std::string::String` because of return type + | | + | this type parameter LL | x - | ^ expected struct `std::string::String`, found type parameter + | ^ expected struct `std::string::String`, found type parameter `impl Debug` | = note: expected type `std::string::String` found type `impl Debug` diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.stderr b/src/test/ui/impl-trait/universal-two-impl-traits.stderr index 98a70f268cf..f540d319a27 100644 --- a/src/test/ui/impl-trait/universal-two-impl-traits.stderr +++ b/src/test/ui/impl-trait/universal-two-impl-traits.stderr @@ -1,11 +1,16 @@ error[E0308]: mismatched types --> $DIR/universal-two-impl-traits.rs:5:9 | +LL | fn foo(x: impl Debug, y: impl Debug) -> String { + | ---------- ---------- found type parameter + | | + | expected type parameter +LL | let mut a = x; LL | a = y; - | ^ expected type parameter, found a different type parameter + | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` | - = note: expected type `impl Debug` (type parameter) - found type `impl Debug` (type parameter) + = note: expected type `impl Debug` (type parameter `impl Debug`) + found type `impl Debug` (type parameter `impl Debug`) = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters diff --git a/src/test/ui/issues/issue-13853.stderr b/src/test/ui/issues/issue-13853.stderr index 3f2d0aa87ad..67721356208 100644 --- a/src/test/ui/issues/issue-13853.stderr +++ b/src/test/ui/issues/issue-13853.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/issue-13853.rs:14:9 | LL | fn nodes<'a, I: Iterator>(&self) -> I - | - expected `I` because of return type + | - this type parameter - expected `I` because of return type ... LL | self.iter() - | ^^^^^^^^^^^ expected type parameter, found struct `std::slice::Iter` + | ^^^^^^^^^^^ expected type parameter `I`, found struct `std::slice::Iter` | = note: expected type `I` found type `std::slice::Iter<'_, N>` diff --git a/src/test/ui/issues/issue-20225.stderr b/src/test/ui/issues/issue-20225.stderr index 4c464e6d4f6..40093b13edf 100644 --- a/src/test/ui/issues/issue-20225.stderr +++ b/src/test/ui/issues/issue-20225.stderr @@ -1,8 +1,10 @@ error[E0053]: method `call` has an incompatible type for trait --> $DIR/issue-20225.rs:6:3 | +LL | impl<'a, T> Fn<(&'a T,)> for Foo { + | - this type parameter LL | extern "rust-call" fn call(&self, (_,): (T,)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found type parameter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found type parameter `T` | = note: expected type `extern "rust-call" fn(&Foo, (&'a T,))` found type `extern "rust-call" fn(&Foo, (T,))` @@ -12,8 +14,10 @@ LL | extern "rust-call" fn call(&self, (_,): (T,)) {} error[E0053]: method `call_mut` has an incompatible type for trait --> $DIR/issue-20225.rs:12:3 | +LL | impl<'a, T> FnMut<(&'a T,)> for Foo { + | - this type parameter LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found type parameter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found type parameter `T` | = note: expected type `extern "rust-call" fn(&mut Foo, (&'a T,))` found type `extern "rust-call" fn(&mut Foo, (T,))` @@ -23,8 +27,11 @@ LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} error[E0053]: method `call_once` has an incompatible type for trait --> $DIR/issue-20225.rs:20:3 | +LL | impl<'a, T> FnOnce<(&'a T,)> for Foo { + | - this type parameter +... LL | extern "rust-call" fn call_once(self, (_,): (T,)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found type parameter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found type parameter `T` | = note: expected type `extern "rust-call" fn(Foo, (&'a T,))` found type `extern "rust-call" fn(Foo, (T,))` diff --git a/src/test/ui/issues/issue-24204.stderr b/src/test/ui/issues/issue-24204.stderr index 9c53c1b86ce..ace5b5f72fc 100644 --- a/src/test/ui/issues/issue-24204.stderr +++ b/src/test/ui/issues/issue-24204.stderr @@ -5,7 +5,7 @@ LL | trait Trait: Sized { | ------------------ required by `Trait` ... LL | fn test>(b: i32) -> T where T::A: MultiDispatch { T::new(b) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found associated type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type | = note: expected type `T` found type `<::A as MultiDispatch>::O` diff --git a/src/test/ui/issues/issue-2951.rs b/src/test/ui/issues/issue-2951.rs index e0ae3ffa624..cc52dab0245 100644 --- a/src/test/ui/issues/issue-2951.rs +++ b/src/test/ui/issues/issue-2951.rs @@ -4,7 +4,7 @@ fn foo(x: T, y: U) { //~^ ERROR mismatched types //~| expected type `T` //~| found type `U` - //~| expected type parameter, found a different type parameter + //~| expected type parameter `T`, found type parameter `U` } fn main() { diff --git a/src/test/ui/issues/issue-2951.stderr b/src/test/ui/issues/issue-2951.stderr index a6ccc4835fa..41457175290 100644 --- a/src/test/ui/issues/issue-2951.stderr +++ b/src/test/ui/issues/issue-2951.stderr @@ -1,8 +1,13 @@ error[E0308]: mismatched types --> $DIR/issue-2951.rs:3:10 | +LL | fn foo(x: T, y: U) { + | - - found type parameter + | | + | expected type parameter +LL | let mut xx = x; LL | xx = y; - | ^ expected type parameter, found a different type parameter + | ^ expected type parameter `T`, found type parameter `U` | = note: expected type `T` found type `U` diff --git a/src/test/ui/mismatched_types/issue-35030.stderr b/src/test/ui/mismatched_types/issue-35030.stderr index 4a9afb9d249..39eca93f88d 100644 --- a/src/test/ui/mismatched_types/issue-35030.stderr +++ b/src/test/ui/mismatched_types/issue-35030.stderr @@ -1,10 +1,13 @@ error[E0308]: mismatched types --> $DIR/issue-35030.rs:9:14 | +LL | impl Parser for bool { + | ---- this type parameter +LL | fn parse(text: &str) -> Option { LL | Some(true) - | ^^^^ expected type parameter, found bool + | ^^^^ expected type parameter `bool`, found bool | - = note: expected type `bool` (type parameter) + = note: expected type `bool` (type parameter `bool`) found type `bool` (bool) = help: type parameters must be constrained to match other types = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters diff --git a/src/test/ui/structs/struct-path-self-type-mismatch.stderr b/src/test/ui/structs/struct-path-self-type-mismatch.stderr index b905cd1a294..687d610baf8 100644 --- a/src/test/ui/structs/struct-path-self-type-mismatch.stderr +++ b/src/test/ui/structs/struct-path-self-type-mismatch.stderr @@ -7,8 +7,13 @@ LL | Self { inner: 1.5f32 }; error[E0308]: mismatched types --> $DIR/struct-path-self-type-mismatch.rs:15:20 | +LL | impl Foo { + | - expected type parameter +LL | fn new(u: U) -> Foo { + | - found type parameter +... LL | inner: u - | ^ expected type parameter, found a different type parameter + | ^ expected type parameter `T`, found type parameter `U` | = note: expected type `T` found type `U` @@ -18,14 +23,18 @@ LL | inner: u error[E0308]: mismatched types --> $DIR/struct-path-self-type-mismatch.rs:13:9 | +LL | impl Foo { + | - found type parameter LL | fn new(u: U) -> Foo { - | ------ expected `Foo` because of return type + | - ------ expected `Foo` because of return type + | | + | expected type parameter LL | / Self { LL | | LL | | inner: u LL | | LL | | } - | |_________^ expected type parameter, found a different type parameter + | |_________^ expected type parameter `U`, found type parameter `T` | = note: expected type `Foo` found type `Foo` diff --git a/src/test/ui/structs/struct-path-self.stderr b/src/test/ui/structs/struct-path-self.stderr index 8c88cacc69e..693ed35cbc9 100644 --- a/src/test/ui/structs/struct-path-self.stderr +++ b/src/test/ui/structs/struct-path-self.stderr @@ -1,4 +1,4 @@ -error[E0071]: expected struct, variant or union type, found type parameter +error[E0071]: expected struct, variant or union type, found type parameter `Self` --> $DIR/struct-path-self.rs:5:17 | LL | let s = Self {}; @@ -10,13 +10,13 @@ error[E0109]: type arguments are not allowed for this type LL | let z = Self:: {}; | ^^ type argument not allowed -error[E0071]: expected struct, variant or union type, found type parameter +error[E0071]: expected struct, variant or union type, found type parameter `Self` --> $DIR/struct-path-self.rs:7:17 | LL | let z = Self:: {}; | ^^^^^^^^^^ not a struct -error[E0071]: expected struct, variant or union type, found type parameter +error[E0071]: expected struct, variant or union type, found type parameter `Self` --> $DIR/struct-path-self.rs:11:13 | LL | Self { .. } => {} diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr index a0a617fdbbc..9e44e208f0e 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr +++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr @@ -1,8 +1,11 @@ error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:13:25 | +LL | impl Enum { + | - this type parameter +LL | fn ts_variant() { LL | Self::TSVariant(()); - | ^^ expected type parameter, found () + | ^^ expected type parameter `T`, found () | = note: expected type `T` found type `()` @@ -24,8 +27,11 @@ LL | Self::<()>::TSVariant(()); error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:17:31 | +LL | impl Enum { + | - this type parameter +... LL | Self::<()>::TSVariant(()); - | ^^ expected type parameter, found () + | ^^ expected type parameter `T`, found () | = note: expected type `T` found type `()` @@ -47,8 +53,11 @@ LL | Self::<()>::TSVariant::<()>(()); error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:26:29 | +LL | impl Enum { + | - this type parameter +... LL | Self::SVariant { v: () }; - | ^^ expected type parameter, found () + | ^^ expected type parameter `T`, found () | = note: expected type `T` found type `()` @@ -64,8 +73,11 @@ LL | Self::SVariant::<()> { v: () }; error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:28:35 | +LL | impl Enum { + | - this type parameter +... LL | Self::SVariant::<()> { v: () }; - | ^^ expected type parameter, found () + | ^^ expected type parameter `T`, found () | = note: expected type `T` found type `()` @@ -81,8 +93,11 @@ LL | Self::<()>::SVariant { v: () }; error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:31:35 | +LL | impl Enum { + | - this type parameter +... LL | Self::<()>::SVariant { v: () }; - | ^^ expected type parameter, found () + | ^^ expected type parameter `T`, found () | = note: expected type `T` found type `()` @@ -104,8 +119,11 @@ LL | Self::<()>::SVariant::<()> { v: () }; error[E0308]: mismatched types --> $DIR/enum-variant-generic-args.rs:34:41 | +LL | impl Enum { + | - this type parameter +... LL | Self::<()>::SVariant::<()> { v: () }; - | ^^ expected type parameter, found () + | ^^ expected type parameter `T`, found () | = note: expected type `T` found type `()` diff --git a/src/test/ui/type/type-parameter-names.rs b/src/test/ui/type/type-parameter-names.rs index b6b3795d09b..82576646345 100644 --- a/src/test/ui/type/type-parameter-names.rs +++ b/src/test/ui/type/type-parameter-names.rs @@ -6,7 +6,7 @@ fn foo(x: Foo) -> Bar { //~^ ERROR mismatched types //~| expected type `Bar` //~| found type `Foo` -//~| expected type parameter, found a different type parameter +//~| expected type parameter `Bar`, found type parameter `Foo` } fn main() {} diff --git a/src/test/ui/type/type-parameter-names.stderr b/src/test/ui/type/type-parameter-names.stderr index 3397eec9e05..78d6989a336 100644 --- a/src/test/ui/type/type-parameter-names.stderr +++ b/src/test/ui/type/type-parameter-names.stderr @@ -2,9 +2,12 @@ error[E0308]: mismatched types --> $DIR/type-parameter-names.rs:5:5 | LL | fn foo(x: Foo) -> Bar { - | --- expected `Bar` because of return type + | --- --- --- expected `Bar` because of return type + | | | + | | expected type parameter + | found type parameter LL | x - | ^ expected type parameter, found a different type parameter + | ^ expected type parameter `Bar`, found type parameter `Foo` | = note: expected type `Bar` found type `Foo` diff --git a/src/test/ui/type/type-params-in-different-spaces-1.rs b/src/test/ui/type/type-params-in-different-spaces-1.rs index 71fb7f380ae..d2dce7006b7 100644 --- a/src/test/ui/type/type-params-in-different-spaces-1.rs +++ b/src/test/ui/type/type-params-in-different-spaces-1.rs @@ -5,7 +5,7 @@ trait BrokenAdd: Copy + Add { *self + rhs //~ ERROR mismatched types //~| expected type `Self` //~| found type `T` - //~| expected type parameter, found a different type parameter + //~| expected type parameter `Self`, found type parameter `T` } } diff --git a/src/test/ui/type/type-params-in-different-spaces-1.stderr b/src/test/ui/type/type-params-in-different-spaces-1.stderr index a10bf4e0b77..d2c6b7304ff 100644 --- a/src/test/ui/type/type-params-in-different-spaces-1.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-1.stderr @@ -1,8 +1,16 @@ error[E0308]: mismatched types --> $DIR/type-params-in-different-spaces-1.rs:5:17 | -LL | *self + rhs - | ^^^ expected type parameter, found a different type parameter +LL | / trait BrokenAdd: Copy + Add { +LL | | fn broken_add(&self, rhs: T) -> Self { + | | - found type parameter +LL | | *self + rhs + | | ^^^ expected type parameter `Self`, found type parameter `T` +LL | | +... | +LL | | } +LL | | } + | |_- expected type parameter | = note: expected type `Self` found type `T` diff --git a/src/test/ui/type/type-params-in-different-spaces-3.stderr b/src/test/ui/type/type-params-in-different-spaces-3.stderr index 9f0fa5a0ea1..ec5d6372792 100644 --- a/src/test/ui/type/type-params-in-different-spaces-3.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-3.stderr @@ -1,10 +1,16 @@ error[E0308]: mismatched types --> $DIR/type-params-in-different-spaces-3.rs:3:9 | -LL | fn test(u: X) -> Self { - | ---- expected `Self` because of return type -LL | u - | ^ expected type parameter, found a different type parameter +LL | / trait Tr : Sized { +LL | | fn test(u: X) -> Self { + | | - ---- expected `Self` because of return type + | | | + | | found type parameter +LL | | u + | | ^ expected type parameter `Self`, found type parameter `X` +LL | | } +LL | | } + | |_- expected type parameter | = note: expected type `Self` found type `X` From 774e60b0c16d234d247978b92db27869d6ab45fa Mon Sep 17 00:00:00 2001 From: Dmitry Kadashev Date: Sat, 2 Nov 2019 14:51:10 +0700 Subject: [PATCH 4/4] Prettify mismatched types error message in a special case Type parameters are referenced in the error message after the previous few commits (using span label). But when the main error message already references the very same type parameter it becomes clumsy. Do not show the additional label in this case as per code review comment by @estebank. Also this contains a small style fix. --- src/librustc/infer/error_reporting/mod.rs | 8 +++---- src/librustc/ty/error.rs | 24 +++++++++---------- .../impl-generic-mismatch-ab.stderr | 6 ++--- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 57cb9564f71..3c4db5e0e25 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1194,10 +1194,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // it's a actual definition. According to the comments (e.g. in // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter // is relied upon by some other code. This might (or might not) need cleanup. - let body_owner_def_id = match self.tcx.hir().opt_local_def_id(cause.body_id) { - Some(def_id) => def_id, - None => self.tcx.hir().body_owner_def_id(hir::BodyId{hir_id: cause.body_id}), - }; + let body_owner_def_id = self.tcx.hir().opt_local_def_id(cause.body_id) + .unwrap_or_else(|| { + self.tcx.hir().body_owner_def_id(hir::BodyId { hir_id: cause.body_id }) + }); self.check_and_note_conflicting_crates(diag, terr, span); self.tcx.note_and_explain_type_err(diag, terr, span, body_owner_def_id); diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 768487fb162..0639a70ed0c 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -291,14 +291,14 @@ impl<'tcx> TyCtxt<'tcx> { }, (ty::Param(expected), ty::Param(found)) => { let generics = self.generics_of(body_owner_def_id); - db.span_label( - self.def_span(generics.type_param(expected, self).def_id), - "expected type parameter" - ); - db.span_label( - self.def_span(generics.type_param(found, self).def_id), - "found type parameter" - ); + let e_span = self.def_span(generics.type_param(expected, self).def_id); + if !sp.contains(e_span) { + db.span_label(e_span, "expected type parameter"); + } + let f_span = self.def_span(generics.type_param(found, self).def_id); + if !sp.contains(f_span) { + db.span_label(f_span, "found type parameter"); + } db.note("a type parameter was expected, but a different one was found; \ you might be missing a type parameter or trait bound"); db.note("for more information, visit \ @@ -313,10 +313,10 @@ impl<'tcx> TyCtxt<'tcx> { } (ty::Param(p), _) | (_, ty::Param(p)) => { let generics = self.generics_of(body_owner_def_id); - db.span_label( - self.def_span(generics.type_param(p, self).def_id), - "this type parameter" - ); + let p_span = self.def_span(generics.type_param(p, self).def_id); + if !sp.contains(p_span) { + db.span_label(p_span, "this type parameter"); + } db.help("type parameters must be constrained to match other types"); if self.sess.teach(&db.get_code().unwrap()) { db.help("given a type parameter `T` and a method `foo`: diff --git a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr index 84fc66bb94c..7cb4677a2b1 100644 --- a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr +++ b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr @@ -5,10 +5,8 @@ LL | fn foo(&self, a: &A, b: &impl Debug); | -- type in trait ... LL | fn foo(&self, a: &impl Debug, b: &B) { } - | - ^---------- - | | || - | | |found type parameter - | | expected type parameter `B`, found type parameter `impl Debug` + | - ^^^^^^^^^^^ expected type parameter `B`, found type parameter `impl Debug` + | | | expected type parameter | = note: expected type `fn(&(), &B, &impl Debug)`