Tweak unsatisfied HRTB errors

This commit is contained in:
Esteban Küber 2019-09-01 21:51:16 -07:00
parent a44881d892
commit 0a985f2c86
11 changed files with 147 additions and 61 deletions

View file

@ -192,23 +192,28 @@ impl NiceRegionError<'me, 'tcx> {
vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs
); );
let mut err = self.tcx().sess.struct_span_err( let span = cause.span(self.tcx());
cause.span(self.tcx()), let msg = format!(
&format!(
"implementation of `{}` is not general enough", "implementation of `{}` is not general enough",
self.tcx().def_path_str(trait_def_id), self.tcx().def_path_str(trait_def_id),
), );
let mut err = self.tcx().sess.struct_span_err(span, &msg);
err.span_label(
self.tcx().def_span(trait_def_id),
format!("trait `{}` defined here", self.tcx().def_path_str(trait_def_id)),
); );
match cause.code { let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code {
ObligationCauseCode::ItemObligation(def_id) => { err.span_label(span, "doesn't satisfy where-clause");
err.note(&format!( err.span_label(
"Due to a where-clause on `{}`,", self.tcx().def_span(def_id),
self.tcx().def_path_str(def_id), &format!("due to a where-clause on `{}`...", self.tcx().def_path_str(def_id)),
)); );
} true
_ => (), } else {
} err.span_label(span, &msg);
false
};
let expected_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef { let expected_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef {
def_id: trait_def_id, def_id: trait_def_id,
@ -295,6 +300,7 @@ impl NiceRegionError<'me, 'tcx> {
expected_has_vid, expected_has_vid,
actual_has_vid, actual_has_vid,
any_self_ty_has_vid, any_self_ty_has_vid,
leading_ellipsis,
); );
err err
@ -318,6 +324,7 @@ impl NiceRegionError<'me, 'tcx> {
expected_has_vid: Option<usize>, expected_has_vid: Option<usize>,
actual_has_vid: Option<usize>, actual_has_vid: Option<usize>,
any_self_ty_has_vid: bool, any_self_ty_has_vid: bool,
leading_ellipsis: bool,
) { ) {
// HACK(eddyb) maybe move this in a more central location. // HACK(eddyb) maybe move this in a more central location.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -392,13 +399,15 @@ impl NiceRegionError<'me, 'tcx> {
let mut note = if passive_voice { let mut note = if passive_voice {
format!( format!(
"`{}` would have to be implemented for the type `{}`", "{}`{}` would have to be implemented for the type `{}`",
if leading_ellipsis { "..." } else { "" },
expected_trait_ref, expected_trait_ref,
expected_trait_ref.map(|tr| tr.self_ty()), expected_trait_ref.map(|tr| tr.self_ty()),
) )
} else { } else {
format!( format!(
"`{}` must implement `{}`", "{}`{}` must implement `{}`",
if leading_ellipsis { "..." } else { "" },
expected_trait_ref.map(|tr| tr.self_ty()), expected_trait_ref.map(|tr| tr.self_ty()),
expected_trait_ref, expected_trait_ref,
) )
@ -407,20 +416,20 @@ impl NiceRegionError<'me, 'tcx> {
match (has_sub, has_sup) { match (has_sub, has_sup) {
(Some(n1), Some(n2)) => { (Some(n1), Some(n2)) => {
let _ = write!(note, let _ = write!(note,
", for any two lifetimes `'{}` and `'{}`", ", for any two lifetimes `'{}` and `'{}`...",
std::cmp::min(n1, n2), std::cmp::min(n1, n2),
std::cmp::max(n1, n2), std::cmp::max(n1, n2),
); );
} }
(Some(n), _) | (_, Some(n)) => { (Some(n), _) | (_, Some(n)) => {
let _ = write!(note, let _ = write!(note,
", for any lifetime `'{}`", ", for any lifetime `'{}`...",
n, n,
); );
} }
(None, None) => if let Some(n) = expected_has_vid { (None, None) => if let Some(n) = expected_has_vid {
let _ = write!(note, let _ = write!(note,
", for some specific lifetime `'{}`", ", for some specific lifetime `'{}`...",
n, n,
); );
}, },
@ -439,13 +448,13 @@ impl NiceRegionError<'me, 'tcx> {
let mut note = if passive_voice { let mut note = if passive_voice {
format!( format!(
"but `{}` is actually implemented for the type `{}`", "...but `{}` is actually implemented for the type `{}`",
actual_trait_ref, actual_trait_ref,
actual_trait_ref.map(|tr| tr.self_ty()), actual_trait_ref.map(|tr| tr.self_ty()),
) )
} else { } else {
format!( format!(
"but `{}` actually implements `{}`", "...but `{}` actually implements `{}`",
actual_trait_ref.map(|tr| tr.self_ty()), actual_trait_ref.map(|tr| tr.self_ty()),
actual_trait_ref, actual_trait_ref,
) )

View file

@ -1,20 +1,26 @@
error: implementation of `Foo` is not general enough error: implementation of `Foo` is not general enough
--> $DIR/auto-trait-regions.rs:30:5 --> $DIR/auto-trait-regions.rs:30:5
| |
LL | auto trait Foo {}
| ----------------- trait `Foo` defined here
...
LL | assert_foo(gen); LL | assert_foo(gen);
| ^^^^^^^^^^ | ^^^^^^^^^^ implementation of `Foo` is not general enough
| |
= note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0` = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`...
= note: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1` = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
error: implementation of `Foo` is not general enough error: implementation of `Foo` is not general enough
--> $DIR/auto-trait-regions.rs:48:5 --> $DIR/auto-trait-regions.rs:48:5
| |
LL | auto trait Foo {}
| ----------------- trait `Foo` defined here
...
LL | assert_foo(gen); LL | assert_foo(gen);
| ^^^^^^^^^^ | ^^^^^^^^^^ implementation of `Foo` is not general enough
| |
= note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1` = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
= note: but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -0,0 +1,16 @@
// ignore-compare-mode-nll
// ^ This code works in nll mode.
fn main() {
test::<FooS>(&mut 42); //~ ERROR implementation of `Foo` is not general enough
}
trait Foo<'a> {}
struct FooS<'a> {
data: &'a mut u32,
}
impl<'a, 'b: 'a> Foo<'b> for FooS<'a> {}
fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {}

View file

@ -0,0 +1,17 @@
error: implementation of `Foo` is not general enough
--> $DIR/due-to-where-clause.rs:5:5
|
LL | test::<FooS>(&mut 42);
| ^^^^^^^^^^^^ doesn't satisfy where-clause
...
LL | trait Foo<'a> {}
| ---------------- trait `Foo` defined here
...
LL | fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {}
| ------------------------------------------------------------- due to a where-clause on `test`...
|
= note: ...`FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`...
= note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1`
error: aborting due to previous error

View file

@ -1,11 +1,14 @@
error: implementation of `Deserialize` is not general enough error: implementation of `Deserialize` is not general enough
--> $DIR/hrtb-cache-issue-54302.rs:19:5 --> $DIR/hrtb-cache-issue-54302.rs:19:5
| |
LL | trait Deserialize<'de> {}
| ------------------------- trait `Deserialize` defined here
...
LL | assert_deserialize_owned::<&'static str>(); LL | assert_deserialize_owned::<&'static str>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
| |
= note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0` = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
= note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,11 +1,17 @@
error: implementation of `Stream` is not general enough error: implementation of `Stream` is not general enough
--> $DIR/issue-30786.rs:108:22 --> $DIR/issue-30786.rs:108:22
| |
LL | / pub trait Stream {
LL | | type Item;
LL | | fn next(self) -> Option<Self::Item>;
LL | | }
| |_- trait `Stream` defined here
...
LL | let map = source.map(|x: &_| x); LL | let map = source.map(|x: &_| x);
| ^^^ | ^^^ implementation of `Stream` is not general enough
| |
= note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0` = note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0`...
= note: but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1` = note: ...but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1`
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,11 +1,11 @@
error: higher-ranked subtype error error: higher-ranked subtype error
--> $DIR/issue-30786.rs:112:18 --> $DIR/issue-30786.rs:113:18
| |
LL | let filter = map.filter(|x: &_| true); LL | let filter = map.filter(|x: &_| true);
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
error: higher-ranked subtype error error: higher-ranked subtype error
--> $DIR/issue-30786.rs:114:17 --> $DIR/issue-30786.rs:115:17
| |
LL | let count = filter.count(); // Assert that we still have a valid stream. LL | let count = filter.count(); // Assert that we still have a valid stream.
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^

View file

@ -16,7 +16,7 @@
//[nll]compile-flags: -Z borrowck=mir //[nll]compile-flags: -Z borrowck=mir
pub trait Stream { pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here
type Item; type Item;
fn next(self) -> Option<Self::Item>; fn next(self) -> Option<Self::Item>;
} }
@ -109,6 +109,7 @@ fn main() {
//[migrate]~^ ERROR implementation of `Stream` is not general enough //[migrate]~^ ERROR implementation of `Stream` is not general enough
//[migrate]~| NOTE `Stream` would have to be implemented for the type `&'0 mut Map //[migrate]~| NOTE `Stream` would have to be implemented for the type `&'0 mut Map
//[migrate]~| NOTE but `Stream` is actually implemented for the type `&'1 //[migrate]~| NOTE but `Stream` is actually implemented for the type `&'1
//[migrate]~| NOTE implementation of `Stream` is not general enough
let filter = map.filter(|x: &_| true); let filter = map.filter(|x: &_| true);
//[nll]~^ ERROR higher-ranked subtype error //[nll]~^ ERROR higher-ranked subtype error
let count = filter.count(); // Assert that we still have a valid stream. let count = filter.count(); // Assert that we still have a valid stream.

View file

@ -1,38 +1,58 @@
error: implementation of `Foo` is not general enough error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:63:5 --> $DIR/issue-54302-cases.rs:63:5
| |
LL | / trait Foo<'x, T> {
LL | | fn foo(self) -> &'x T;
LL | | }
| |_- trait `Foo` defined here
...
LL | <u32 as RefFoo<u32>>::ref_foo(a) LL | <u32 as RefFoo<u32>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
| |
= note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0` = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
= note: but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: implementation of `Foo` is not general enough error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:69:5 --> $DIR/issue-54302-cases.rs:69:5
| |
LL | / trait Foo<'x, T> {
LL | | fn foo(self) -> &'x T;
LL | | }
| |_- trait `Foo` defined here
...
LL | <i32 as RefFoo<i32>>::ref_foo(a) LL | <i32 as RefFoo<i32>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
| |
= note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0` = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`...
= note: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
error: implementation of `Foo` is not general enough error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:75:5 --> $DIR/issue-54302-cases.rs:75:5
| |
LL | / trait Foo<'x, T> {
LL | | fn foo(self) -> &'x T;
LL | | }
| |_- trait `Foo` defined here
...
LL | <u64 as RefFoo<u64>>::ref_foo(a) LL | <u64 as RefFoo<u64>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
| |
= note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0` = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`...
= note: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
error: implementation of `Foo` is not general enough error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:81:5 --> $DIR/issue-54302-cases.rs:81:5
| |
LL | / trait Foo<'x, T> {
LL | | fn foo(self) -> &'x T;
LL | | }
| |_- trait `Foo` defined here
...
LL | <i64 as RefFoo<i64>>::ref_foo(a) LL | <i64 as RefFoo<i64>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
| |
= note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0` = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`...
= note: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
error: aborting due to 4 previous errors error: aborting due to 4 previous errors

View file

@ -1,11 +1,14 @@
error: implementation of `Deserialize` is not general enough error: implementation of `Deserialize` is not general enough
--> $DIR/issue-54302.rs:13:5 --> $DIR/issue-54302.rs:13:5
| |
LL | trait Deserialize<'de> {}
| ------------------------- trait `Deserialize` defined here
...
LL | assert_deserialize_owned::<&'static str>(); LL | assert_deserialize_owned::<&'static str>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
| |
= note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0` = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
= note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,11 +1,16 @@
error: implementation of `DistributedIteratorMulti` is not general enough error: implementation of `DistributedIteratorMulti` is not general enough
--> $DIR/issue-55731.rs:48:5 --> $DIR/issue-55731.rs:48:5
| |
LL | / trait DistributedIteratorMulti<Source> {
LL | | type Item;
LL | | }
| |_- trait `DistributedIteratorMulti` defined here
...
LL | multi(Map { LL | multi(Map {
| ^^^^^ | ^^^^^ implementation of `DistributedIteratorMulti` is not general enough
| |
= note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0` = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`...
= note: but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
error: aborting due to previous error error: aborting due to previous error