diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index a50cc86862e5..57cb9564f71b 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 4ef6a162c8b6..768487fb1626 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`: