diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 498600f1e901d..e238c96612234 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1234,8 +1234,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 = 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); + 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 77613b548cfdb..0639a70ed0c49 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(), } @@ -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); + 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 \ @@ -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); + 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/associated-types/associated-types-issue-20346.stderr b/src/test/ui/associated-types/associated-types-issue-20346.stderr index b763b82d540cc..f5053f6a1c0c8 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 8176e96d6de1f..326b84470d622 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 e4d0a731ebfe5..7cb4677a2b199 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,9 @@ 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 + | - ^^^^^^^^^^^ 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 d92c3f034e5a2..ae20a5aa88388 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 98a70f268cf72..f540d319a2797 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 3f2d0aa87adc1..67721356208c0 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 4c464e6d4f685..40093b13edfe0 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 9c53c1b86ceaf..ace5b5f72fc62 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 e0ae3ffa6240d..cc52dab02459c 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 a6ccc4835fa68..414571752904c 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 4a9afb9d2494e..39eca93f88d1c 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 b905cd1a294cc..687d610baf8cf 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 8c88cacc69e31..693ed35cbc9c6 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 a0a617fdbbc35..9e44e208f0ee4 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 b6b3795d09bfb..825766463453b 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 3397eec9e050b..78d6989a3363d 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 71fb7f380aeac..d2dce7006b763 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 a10bf4e0b7787..d2c6b7304ff3c 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 9f0fa5a0ea1fe..ec5d6372792b3 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`