about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDmitry Kadashev <dkadashev@gmail.com>2019-10-31 17:20:33 +0700
committerDmitry Kadashev <dkadashev@gmail.com>2019-11-02 12:48:24 +0700
commit036f1828041c80842129b28695b60ba31a74403a (patch)
treeb16d33d70b01ca1b19abd29a8116fc612cdb4e8c /src
parent6a30ce639f9eeba7d085721d219553635f32c280 (diff)
downloadrust-036f1828041c80842129b28695b60ba31a74403a.tar.gz
rust-036f1828041c80842129b28695b60ba31a74403a.zip
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: T) {
   |         - this type parameter
LL |     bar1(t);
   |          ^
   |          |
   |          expected enum `std::option::Option`, found type parameter `T`
```
Diffstat (limited to 'src')
-rw-r--r--src/librustc/infer/error_reporting/mod.rs10
-rw-r--r--src/librustc/ty/error.rs19
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`: