Skip to content

Commit 0dcdbae

Browse files
committed
Point at the def span of trait refs E0277
1 parent c556151 commit 0dcdbae

File tree

8 files changed

+71
-13
lines changed

8 files changed

+71
-13
lines changed

src/librustc/infer/error_reporting/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ use rustc_hir::Node;
7171
use errors::{
7272
pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticStyledString,
7373
};
74+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
7475
use rustc_error_codes::*;
7576
use rustc_span::{DesugaringKind, Pos, Span};
7677
use rustc_target::spec::abi;
@@ -1362,9 +1363,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13621363
let kind = match t.kind {
13631364
ty::Closure(..) => "closure",
13641365
ty::Opaque(..) => "opaque type",
1366+
ty::Generator(..) => "generator",
1367+
ty::Foreign(..) => "foreign type",
13651368
_ => "",
13661369
};
1367-
if let ty::Closure(def_id, _) | ty::Opaque(def_id, _) = t.kind {
1370+
if let ty::Closure(def_id, _)
1371+
| ty::Opaque(def_id, _)
1372+
| ty::Generator(def_id, ..)
1373+
| ty::Foreign(def_id) = t.kind
1374+
{
13681375
let span = self.tcx.def_span(def_id);
13691376
// Avoid cluttering the output when the "found" and error span overlap:
13701377
//

src/librustc/traits/error_reporting.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
446446
flags.push((sym::from_method, Some(method.to_string())));
447447
}
448448
}
449-
if let Some(t) = self.get_parent_trait_ref(&obligation.cause.code) {
449+
if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
450450
flags.push((sym::parent_trait, Some(t)));
451451
}
452452

@@ -665,13 +665,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
665665
}
666666

667667
/// Gets the parent trait chain start
668-
fn get_parent_trait_ref(&self, code: &ObligationCauseCode<'tcx>) -> Option<String> {
668+
fn get_parent_trait_ref(
669+
&self,
670+
code: &ObligationCauseCode<'tcx>,
671+
) -> Option<(String, Option<Span>)> {
669672
match code {
670673
&ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
671674
let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
672675
match self.get_parent_trait_ref(&data.parent_code) {
673676
Some(t) => Some(t),
674-
None => Some(parent_trait_ref.skip_binder().self_ty().to_string()),
677+
None => {
678+
let ty = parent_trait_ref.skip_binder().self_ty();
679+
let span = if let ty::Closure(def_id, _)
680+
| ty::Opaque(def_id, _)
681+
| ty::Generator(def_id, ..)
682+
| ty::Foreign(def_id) = ty.kind
683+
{
684+
Some(self.tcx.def_span(def_id))
685+
} else {
686+
None
687+
};
688+
Some((ty.to_string(), span))
689+
}
675690
}
676691
}
677692
_ => None,
@@ -719,9 +734,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
719734
return;
720735
}
721736
let trait_ref = trait_predicate.to_poly_trait_ref();
722-
let (post_message, pre_message) = self
737+
let (post_message, pre_message, type_def) = self
723738
.get_parent_trait_ref(&obligation.cause.code)
724-
.map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t)))
739+
.map(|(t, s)| {
740+
(
741+
format!(" in `{}`", t),
742+
format!("within `{}`, ", t),
743+
s.map(|s| (format!("within this `{}`", t), s)),
744+
)
745+
})
725746
.unwrap_or_default();
726747

727748
let OnUnimplementedNote { message, label, note, enclosing_scope } =
@@ -795,6 +816,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
795816
} else {
796817
err.span_label(span, explanation);
797818
}
819+
if let Some((msg, span)) = type_def {
820+
err.span_label(span, &msg);
821+
}
798822
if let Some(ref s) = note {
799823
// If it has a custom `#[rustc_on_unimplemented]` note, let's display it
800824
err.note(s.as_str());

src/test/ui/async-await/issue-64130-3-other.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl std::future::
33
|
44
LL | fn is_qux<T: Qux>(t: T) { }
55
| ------ --- required by this bound in `is_qux`
6+
LL |
7+
LL | async fn bar() {
8+
| - within this `impl std::future::Future`
69
...
710
LL | is_qux(bar());
811
| ^^^^^^ within `impl std::future::Future`, the trait `Qux` is not implemented for `Foo`

src/test/ui/impl-trait/auto-trait-leak.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ LL | fn send<T: Send>(_: T) {}
7777
...
7878
LL | send(cycle2().clone());
7979
| ^^^^ `std::rc::Rc<std::string::String>` cannot be sent between threads safely
80+
...
81+
LL | fn cycle2() -> impl Clone {
82+
| ---------- within this `impl std::clone::Clone`
8083
|
8184
= help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::string::String>`
8285
= note: required because it appears within the type `impl std::clone::Clone`

src/test/ui/impl-trait/auto-trait-leak2.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0277]: `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
22
--> $DIR/auto-trait-leak2.rs:13:5
33
|
4+
LL | fn before() -> impl Fn(i32) {
5+
| ------------ within this `impl std::ops::Fn<(i32,)>`
6+
...
47
LL | fn send<T: Send>(_: T) {}
58
| ---- ---- required by this bound in `send`
69
...
@@ -19,6 +22,9 @@ LL | fn send<T: Send>(_: T) {}
1922
...
2023
LL | send(after());
2124
| ^^^^ `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
25+
...
26+
LL | fn after() -> impl Fn(i32) {
27+
| ------------ within this `impl std::ops::Fn<(i32,)>`
2228
|
2329
= help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
2430
= note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22 p:std::rc::Rc<std::cell::Cell<i32>>]`

src/test/ui/kindck/kindck-nonsendable-1.stderr

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ LL | fn bar<F:FnOnce() + Send>(_: F) { }
55
| --- ---- required by this bound in `bar`
66
...
77
LL | bar(move|| foo(x));
8-
| ^^^ `std::rc::Rc<usize>` cannot be sent between threads safely
8+
| ^^^ ------------- within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc<usize>]`
9+
| |
10+
| `std::rc::Rc<usize>` cannot be sent between threads safely
911
|
1012
= help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc<usize>]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<usize>`
1113
= note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc<usize>]`

src/test/ui/no-send-res-ports.stderr

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
22
--> $DIR/no-send-res-ports.rs:29:5
33
|
4-
LL | thread::spawn(move|| {
5-
| ^^^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
4+
LL | thread::spawn(move|| {
5+
| _____^^^^^^^^^^^^^_-
6+
| | |
7+
| | `std::rc::Rc<()>` cannot be sent between threads safely
8+
LL | |
9+
LL | | let y = x;
10+
LL | | println!("{:?}", y);
11+
LL | | });
12+
| |_____- within this `[closure@$DIR/no-send-res-ports.rs:29:19: 33:6 x:main::Foo]`
613
|
714
::: $SRC_DIR/libstd/thread/mod.rs:LL:COL
815
|
9-
LL | F: Send + 'static,
10-
| ---- required by this bound in `std::thread::spawn`
16+
LL | F: Send + 'static,
17+
| ---- required by this bound in `std::thread::spawn`
1118
|
1219
= 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<()>`
1320
= note: required because it appears within the type `Port<()>`

src/test/ui/not-clone-closure.stderr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
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]`
22
--> $DIR/not-clone-closure.rs:11:23
33
|
4-
LL | let hello = hello.clone();
5-
| ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`, the trait `std::clone::Clone` is not implemented for `S`
4+
LL | let hello = move || {
5+
| _________________-
6+
LL | | println!("Hello {}", a.0);
7+
LL | | };
8+
| |_____- within this `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`
9+
LL |
10+
LL | let hello = hello.clone();
11+
| ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`, the trait `std::clone::Clone` is not implemented for `S`
612
|
713
= note: required because it appears within the type `[closure@$DIR/not-clone-closure.rs:7:17: 9:6 a:S]`
814

0 commit comments

Comments
 (0)