Skip to content

Commit 60c7f37

Browse files
committed
Add spans to E0277 for impl/trait type/fn obligation disparity
1 parent 2375b8a commit 60c7f37

File tree

3 files changed

+96
-25
lines changed

3 files changed

+96
-25
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,19 +2179,60 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
21792179
)
21802180
});
21812181
}
2182-
ObligationCauseCode::CompareImplMethodObligation { .. } => {
2183-
err.note(&format!(
2184-
"the requirement `{}` appears on the impl method but not on the corresponding \
2185-
trait method",
2186-
predicate
2187-
));
2182+
ObligationCauseCode::CompareImplMethodObligation {
2183+
item_name,
2184+
trait_item_def_id,
2185+
..
2186+
} => {
2187+
let msg = format!(
2188+
"the requirement `{}` appears on the impl method `{}` but not on the \
2189+
corresponding trait method",
2190+
predicate, item_name,
2191+
);
2192+
let sp = self
2193+
.tcx
2194+
.opt_item_name(trait_item_def_id)
2195+
.map(|i| i.span)
2196+
.unwrap_or_else(|| self.tcx.def_span(trait_item_def_id));
2197+
let mut assoc_span: MultiSpan = sp.into();
2198+
assoc_span.push_span_label(
2199+
sp,
2200+
format!("this trait method doesn't have the requirement `{}`", predicate),
2201+
);
2202+
if let Some(ident) = self
2203+
.tcx
2204+
.opt_associated_item(trait_item_def_id)
2205+
.and_then(|i| self.tcx.opt_item_name(i.container.id()))
2206+
{
2207+
assoc_span.push_span_label(ident.span, "in this trait".into());
2208+
}
2209+
err.span_note(assoc_span, &msg);
21882210
}
2189-
ObligationCauseCode::CompareImplTypeObligation { .. } => {
2190-
err.note(&format!(
2191-
"the requirement `{}` appears on the associated impl type but not on the \
2211+
ObligationCauseCode::CompareImplTypeObligation {
2212+
item_name, trait_item_def_id, ..
2213+
} => {
2214+
let msg = format!(
2215+
"the requirement `{}` appears on the associated impl type `{}` but not on the \
21922216
corresponding associated trait type",
2193-
predicate
2194-
));
2217+
predicate, item_name,
2218+
);
2219+
let sp = self.tcx.def_span(trait_item_def_id);
2220+
let mut assoc_span: MultiSpan = sp.into();
2221+
assoc_span.push_span_label(
2222+
sp,
2223+
format!(
2224+
"this trait associated type doesn't have the requirement `{}`",
2225+
predicate,
2226+
),
2227+
);
2228+
if let Some(ident) = self
2229+
.tcx
2230+
.opt_associated_item(trait_item_def_id)
2231+
.and_then(|i| self.tcx.opt_item_name(i.container.id()))
2232+
{
2233+
assoc_span.push_span_label(ident.span, "in this trait".into());
2234+
}
2235+
err.span_note(assoc_span, &msg);
21952236
}
21962237
ObligationCauseCode::CompareImplConstObligation => {
21972238
err.note(&format!(

src/test/ui/generic-associated-types/impl_bounds.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ trait Foo {
66
type A<'a> where Self: 'a;
77
type B<'a, 'b> where 'a: 'b;
88
type C where Self: Clone;
9+
fn d() where Self: Clone;
910
}
1011

1112
#[derive(Copy, Clone)]
@@ -19,6 +20,8 @@ impl<T> Foo for Fooy<T> {
1920
//~| ERROR lifetime bound not satisfied
2021
type C where Self: Copy = String;
2122
//~^ ERROR the trait bound `T: Copy` is not satisfied
23+
fn d() where Self: Copy {}
24+
//~^ ERROR the trait bound `T: Copy` is not satisfied
2225
}
2326

2427
fn main() {}
Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0310]: the parameter type `T` may not live long enough
2-
--> $DIR/impl_bounds.rs:15:5
2+
--> $DIR/impl_bounds.rs:16:5
33
|
44
LL | type A<'a> where Self: 'static = (&'a ());
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,53 +8,80 @@ LL | type A<'a> where Self: 'static = (&'a ());
88
= note: ...so that the type `Fooy<T>` will meet its required lifetime bounds
99

1010
error[E0478]: lifetime bound not satisfied
11-
--> $DIR/impl_bounds.rs:17:5
11+
--> $DIR/impl_bounds.rs:18:5
1212
|
1313
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1515
|
16-
note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 17:16
17-
--> $DIR/impl_bounds.rs:17:16
16+
note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 18:16
17+
--> $DIR/impl_bounds.rs:18:16
1818
|
1919
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
2020
| ^^
21-
note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 17:12
22-
--> $DIR/impl_bounds.rs:17:12
21+
note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 18:12
22+
--> $DIR/impl_bounds.rs:18:12
2323
|
2424
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
2525
| ^^
2626

2727
error[E0478]: lifetime bound not satisfied
28-
--> $DIR/impl_bounds.rs:17:5
28+
--> $DIR/impl_bounds.rs:18:5
2929
|
3030
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
3131
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3232
|
33-
note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 17:12
34-
--> $DIR/impl_bounds.rs:17:12
33+
note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 18:12
34+
--> $DIR/impl_bounds.rs:18:12
3535
|
3636
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
3737
| ^^
38-
note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 17:16
39-
--> $DIR/impl_bounds.rs:17:16
38+
note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 18:16
39+
--> $DIR/impl_bounds.rs:18:16
4040
|
4141
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
4242
| ^^
4343

4444
error[E0277]: the trait bound `T: Copy` is not satisfied
45-
--> $DIR/impl_bounds.rs:20:5
45+
--> $DIR/impl_bounds.rs:21:5
4646
|
4747
LL | type C where Self: Copy = String;
4848
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
4949
|
5050
= note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
51-
= note: the requirement `Fooy<T>: Copy` appears on the associated impl type but not on the corresponding associated trait type
51+
note: the requirement `Fooy<T>: Copy` appears on the associated impl type `C` but not on the corresponding associated trait type
52+
--> $DIR/impl_bounds.rs:8:5
53+
|
54+
LL | trait Foo {
55+
| --- in this trait
56+
...
57+
LL | type C where Self: Clone;
58+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ this trait associated type doesn't have the requirement `Fooy<T>: Copy`
59+
help: consider restricting type parameter `T`
60+
|
61+
LL | impl<T: Copy> Foo for Fooy<T> {
62+
| ^^^^^^
63+
64+
error[E0277]: the trait bound `T: Copy` is not satisfied
65+
--> $DIR/impl_bounds.rs:23:5
66+
|
67+
LL | fn d() where Self: Copy {}
68+
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
69+
|
70+
= note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
71+
note: the requirement `Fooy<T>: Copy` appears on the impl method `d` but not on the corresponding trait method
72+
--> $DIR/impl_bounds.rs:9:8
73+
|
74+
LL | trait Foo {
75+
| --- in this trait
76+
...
77+
LL | fn d() where Self: Clone;
78+
| ^ this trait method doesn't have the requirement `Fooy<T>: Copy`
5279
help: consider restricting type parameter `T`
5380
|
5481
LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
5582
| ^^^^^^^^^^^^^^^^^^^
5683

57-
error: aborting due to 4 previous errors
84+
error: aborting due to 5 previous errors
5885

5986
Some errors have detailed explanations: E0277, E0310, E0478.
6087
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)