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 { + fn get_parent_trait_ref( + &self, + code: &ObligationCauseCode<'tcx>, + ) -> Option<(String, Option)> { 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()); diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index 155c5cc8ea1..d6828172928 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -3,6 +3,9 @@ error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl std::future:: | LL | fn is_qux(t: T) { } | ------ --- required by this bound in `is_qux` +LL | +LL | async fn bar() { + | - within this `impl std::future::Future` ... LL | is_qux(bar()); | ^^^^^^ within `impl std::future::Future`, the trait `Qux` is not implemented for `Foo` diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index d11941fee18..20815e80acb 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -77,6 +77,9 @@ LL | fn send(_: T) {} ... LL | send(cycle2().clone()); | ^^^^ `std::rc::Rc` cannot be sent between threads safely +... +LL | fn cycle2() -> impl Clone { + | ---------- within this `impl std::clone::Clone` | = help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc` = note: required because it appears within the type `impl std::clone::Clone` diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr index d163e1dff7a..a93b3dbc71b 100644 --- a/src/test/ui/impl-trait/auto-trait-leak2.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr @@ -1,6 +1,9 @@ error[E0277]: `std::rc::Rc>` cannot be sent between threads safely --> $DIR/auto-trait-leak2.rs:13:5 | +LL | fn before() -> impl Fn(i32) { + | ------------ within this `impl std::ops::Fn<(i32,)>` +... LL | fn send(_: T) {} | ---- ---- required by this bound in `send` ... @@ -19,6 +22,9 @@ LL | fn send(_: T) {} ... LL | send(after()); | ^^^^ `std::rc::Rc>` cannot be sent between threads safely +... +LL | fn after() -> impl Fn(i32) { + | ------------ within this `impl std::ops::Fn<(i32,)>` | = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc>` = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22 p:std::rc::Rc>]` diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr index 40b67f8fe8c..39640e37399 100644 --- a/src/test/ui/kindck/kindck-nonsendable-1.stderr +++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr @@ -5,7 +5,9 @@ LL | fn bar(_: F) { } | --- ---- required by this bound in `bar` ... LL | bar(move|| foo(x)); - | ^^^ `std::rc::Rc` cannot be sent between threads safely + | ^^^ ------------- within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc]` + | | + | `std::rc::Rc` cannot be sent between threads safely | = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc` = note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc]` diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr index 8cb690a35c8..65946ee8a20 100644 --- a/src/test/ui/no-send-res-ports.stderr +++ b/src/test/ui/no-send-res-ports.stderr @@ -1,13 +1,20 @@ error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely --> $DIR/no-send-res-ports.rs:29:5 | -LL | thread::spawn(move|| { - | ^^^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely +LL | thread::spawn(move|| { + | _____^^^^^^^^^^^^^_- + | | | + | | `std::rc::Rc<()>` cannot be sent between threads safely +LL | | +LL | | let y = x; +LL | | println!("{:?}", y); +LL | | }); + | |_____- within this `[closure@$DIR/no-send-res-ports.rs:29:19: 33:6 x:main::Foo]` | ::: $SRC_DIR/libstd/thread/mod.rs:LL:COL | -LL | F: Send + 'static, - | ---- required by this bound in `std::thread::spawn` +LL | F: Send + 'static, + | ---- required by this bound in `std::thread::spawn` | = help: within `[closure@$DIR/no-send-res-ports.rs:29:19: 33:6 x:main::Foo]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` = note: required because it appears within the type `Port<()>` diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr index b66391b83b8..20c7f81cf5e 100644 --- a/src/test/ui/not-clone-closure.stderr +++ b/src/test/ui/not-clone-closure.stderr @@ -1,8 +1,14 @@ error[E0277]: the trait bound `S: std::clone::Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]` --> $DIR/not-clone-closure.rs:11:23 | -LL | let hello = hello.clone(); - | ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`, the trait `std::clone::Clone` is not implemented for `S` +LL | let hello = move || { + | _________________- +LL | | println!("Hello {}", a.0); +LL | | }; + | |_____- within this `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]` +LL | +LL | let hello = hello.clone(); + | ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`, the trait `std::clone::Clone` is not implemented for `S` | = note: required because it appears within the type `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`