about summary refs log tree commit diff
path: root/src/librustc
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-12-15 22:20:30 -0800
committerEsteban Küber <esteban@kuber.com.ar>2020-01-08 09:30:27 -0800
commit0dcdbaec0b49a149316719b32241d8975bd192c9 (patch)
treeb27c7c6580e22fe4acc7d4b4b64f95ac0b9613e9 /src/librustc
parentc55615155d161c8abb307db0019ab58545cd246b (diff)
downloadrust-0dcdbaec0b49a149316719b32241d8975bd192c9.tar.gz
rust-0dcdbaec0b49a149316719b32241d8975bd192c9.zip
Point at the def span of trait refs E0277
Diffstat (limited to 'src/librustc')
-rw-r--r--src/librustc/infer/error_reporting/mod.rs9
-rw-r--r--src/librustc/traits/error_reporting.rs34
2 files changed, 37 insertions, 6 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index d0243dad700..d736d45a5a4 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -71,6 +71,7 @@ use rustc_hir::Node;
 use errors::{
     pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticStyledString,
 };
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_error_codes::*;
 use rustc_span::{DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
@@ -1362,9 +1363,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 let kind = match t.kind {
                     ty::Closure(..) => "closure",
                     ty::Opaque(..) => "opaque type",
+                    ty::Generator(..) => "generator",
+                    ty::Foreign(..) => "foreign type",
                     _ => "",
                 };
-                if let ty::Closure(def_id, _) | ty::Opaque(def_id, _) = t.kind {
+                if let ty::Closure(def_id, _)
+                | ty::Opaque(def_id, _)
+                | ty::Generator(def_id, ..)
+                | ty::Foreign(def_id) = t.kind
+                {
                     let span = self.tcx.def_span(def_id);
                     // Avoid cluttering the output when the "found" and error span overlap:
                     //
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 00251d55706..8c2cc412a48 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -446,7 +446,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 flags.push((sym::from_method, Some(method.to_string())));
             }
         }
-        if let Some(t) = self.get_parent_trait_ref(&obligation.cause.code) {
+        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
             flags.push((sym::parent_trait, Some(t)));
         }
 
@@ -665,13 +665,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     /// Gets the parent trait chain start
-    fn get_parent_trait_ref(&self, code: &ObligationCauseCode<'tcx>) -> Option<String> {
+    fn get_parent_trait_ref(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+    ) -> Option<(String, Option<Span>)> {
         match code {
             &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
                 let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
                 match self.get_parent_trait_ref(&data.parent_code) {
                     Some(t) => Some(t),
-                    None => Some(parent_trait_ref.skip_binder().self_ty().to_string()),
+                    None => {
+                        let ty = parent_trait_ref.skip_binder().self_ty();
+                        let span = if let ty::Closure(def_id, _)
+                        | ty::Opaque(def_id, _)
+                        | ty::Generator(def_id, ..)
+                        | ty::Foreign(def_id) = ty.kind
+                        {
+                            Some(self.tcx.def_span(def_id))
+                        } else {
+                            None
+                        };
+                        Some((ty.to_string(), span))
+                    }
                 }
             }
             _ => None,
@@ -719,9 +734,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                             return;
                         }
                         let trait_ref = trait_predicate.to_poly_trait_ref();
-                        let (post_message, pre_message) = self
+                        let (post_message, pre_message, type_def) = self
                             .get_parent_trait_ref(&obligation.cause.code)
-                            .map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t)))
+                            .map(|(t, s)| {
+                                (
+                                    format!(" in `{}`", t),
+                                    format!("within `{}`, ", t),
+                                    s.map(|s| (format!("within this `{}`", t), s)),
+                                )
+                            })
                             .unwrap_or_default();
 
                         let OnUnimplementedNote { message, label, note, enclosing_scope } =
@@ -795,6 +816,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         } else {
                             err.span_label(span, explanation);
                         }
+                        if let Some((msg, span)) = type_def {
+                            err.span_label(span, &msg);
+                        }
                         if let Some(ref s) = note {
                             // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
                             err.note(s.as_str());