Add spans to E0277 for impl/trait type/fn obligation disparity

This commit is contained in:
Esteban Küber 2021-03-31 16:53:26 -07:00
parent 2375b8ae7e
commit 60c7f37f7c
3 changed files with 96 additions and 25 deletions

View File

@ -2179,19 +2179,60 @@ fn note_obligation_cause_code<T>(
) )
}); });
} }
ObligationCauseCode::CompareImplMethodObligation { .. } => { ObligationCauseCode::CompareImplMethodObligation {
err.note(&format!( item_name,
"the requirement `{}` appears on the impl method but not on the corresponding \ trait_item_def_id,
trait method", ..
predicate } => {
)); let msg = format!(
"the requirement `{}` appears on the impl method `{}` but not on the \
corresponding trait method",
predicate, item_name,
);
let sp = self
.tcx
.opt_item_name(trait_item_def_id)
.map(|i| i.span)
.unwrap_or_else(|| self.tcx.def_span(trait_item_def_id));
let mut assoc_span: MultiSpan = sp.into();
assoc_span.push_span_label(
sp,
format!("this trait method doesn't have the requirement `{}`", predicate),
);
if let Some(ident) = self
.tcx
.opt_associated_item(trait_item_def_id)
.and_then(|i| self.tcx.opt_item_name(i.container.id()))
{
assoc_span.push_span_label(ident.span, "in this trait".into());
}
err.span_note(assoc_span, &msg);
} }
ObligationCauseCode::CompareImplTypeObligation { .. } => { ObligationCauseCode::CompareImplTypeObligation {
err.note(&format!( item_name, trait_item_def_id, ..
"the requirement `{}` appears on the associated impl type but not on the \ } => {
let msg = format!(
"the requirement `{}` appears on the associated impl type `{}` but not on the \
corresponding associated trait type", corresponding associated trait type",
predicate predicate, item_name,
)); );
let sp = self.tcx.def_span(trait_item_def_id);
let mut assoc_span: MultiSpan = sp.into();
assoc_span.push_span_label(
sp,
format!(
"this trait associated type doesn't have the requirement `{}`",
predicate,
),
);
if let Some(ident) = self
.tcx
.opt_associated_item(trait_item_def_id)
.and_then(|i| self.tcx.opt_item_name(i.container.id()))
{
assoc_span.push_span_label(ident.span, "in this trait".into());
}
err.span_note(assoc_span, &msg);
} }
ObligationCauseCode::CompareImplConstObligation => { ObligationCauseCode::CompareImplConstObligation => {
err.note(&format!( err.note(&format!(

View File

@ -6,6 +6,7 @@ trait Foo {
type A<'a> where Self: 'a; type A<'a> where Self: 'a;
type B<'a, 'b> where 'a: 'b; type B<'a, 'b> where 'a: 'b;
type C where Self: Clone; type C where Self: Clone;
fn d() where Self: Clone;
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -19,6 +20,8 @@ impl<T> Foo for Fooy<T> {
//~| ERROR lifetime bound not satisfied //~| ERROR lifetime bound not satisfied
type C where Self: Copy = String; type C where Self: Copy = String;
//~^ ERROR the trait bound `T: Copy` is not satisfied //~^ ERROR the trait bound `T: Copy` is not satisfied
fn d() where Self: Copy {}
//~^ ERROR the trait bound `T: Copy` is not satisfied
} }
fn main() {} fn main() {}

View File

@ -1,5 +1,5 @@
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/impl_bounds.rs:15:5 --> $DIR/impl_bounds.rs:16:5
| |
LL | type A<'a> where Self: 'static = (&'a ()); LL | type A<'a> where Self: 'static = (&'a ());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -8,53 +8,80 @@ LL | type A<'a> where Self: 'static = (&'a ());
= note: ...so that the type `Fooy<T>` will meet its required lifetime bounds = note: ...so that the type `Fooy<T>` will meet its required lifetime bounds
error[E0478]: lifetime bound not satisfied error[E0478]: lifetime bound not satisfied
--> $DIR/impl_bounds.rs:17:5 --> $DIR/impl_bounds.rs:18:5
| |
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 17:16 note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 18:16
--> $DIR/impl_bounds.rs:17:16 --> $DIR/impl_bounds.rs:18:16
| |
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
| ^^ | ^^
note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 17:12 note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 18:12
--> $DIR/impl_bounds.rs:17:12 --> $DIR/impl_bounds.rs:18:12
| |
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
| ^^ | ^^
error[E0478]: lifetime bound not satisfied error[E0478]: lifetime bound not satisfied
--> $DIR/impl_bounds.rs:17:5 --> $DIR/impl_bounds.rs:18:5
| |
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 17:12 note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 18:12
--> $DIR/impl_bounds.rs:17:12 --> $DIR/impl_bounds.rs:18:12
| |
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
| ^^ | ^^
note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 17:16 note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 18:16
--> $DIR/impl_bounds.rs:17:16 --> $DIR/impl_bounds.rs:18:16
| |
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
| ^^ | ^^
error[E0277]: the trait bound `T: Copy` is not satisfied error[E0277]: the trait bound `T: Copy` is not satisfied
--> $DIR/impl_bounds.rs:20:5 --> $DIR/impl_bounds.rs:21:5
| |
LL | type C where Self: Copy = String; LL | type C where Self: Copy = String;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
| |
= note: required because of the requirements on the impl of `Copy` for `Fooy<T>` = note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
= note: the requirement `Fooy<T>: Copy` appears on the associated impl type but not on the corresponding associated trait type note: the requirement `Fooy<T>: Copy` appears on the associated impl type `C` but not on the corresponding associated trait type
--> $DIR/impl_bounds.rs:8:5
|
LL | trait Foo {
| --- in this trait
...
LL | type C where Self: Clone;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ this trait associated type doesn't have the requirement `Fooy<T>: Copy`
help: consider restricting type parameter `T`
|
LL | impl<T: Copy> Foo for Fooy<T> {
| ^^^^^^
error[E0277]: the trait bound `T: Copy` is not satisfied
--> $DIR/impl_bounds.rs:23:5
|
LL | fn d() where Self: Copy {}
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
|
= note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
note: the requirement `Fooy<T>: Copy` appears on the impl method `d` but not on the corresponding trait method
--> $DIR/impl_bounds.rs:9:8
|
LL | trait Foo {
| --- in this trait
...
LL | fn d() where Self: Clone;
| ^ this trait method doesn't have the requirement `Fooy<T>: Copy`
help: consider restricting type parameter `T` help: consider restricting type parameter `T`
| |
LL | impl<T: std::marker::Copy> Foo for Fooy<T> { LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors error: aborting due to 5 previous errors
Some errors have detailed explanations: E0277, E0310, E0478. Some errors have detailed explanations: E0277, E0310, E0478.
For more information about an error, try `rustc --explain E0277`. For more information about an error, try `rustc --explain E0277`.