Skip to content

Commit

Permalink
Rollup merge of rust-lang#64085 - estebank:hrtb-errors, r=oli-obk
Browse files Browse the repository at this point in the history
Tweak unsatisfied HRTB errors

r? @oli-obk

Close rust-lang#35180.
  • Loading branch information
tmandry authored Sep 10, 2019
2 parents ed1835f + 32440cb commit 11b0ae6
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -192,23 +192,28 @@ impl NiceRegionError<'me, 'tcx> {
vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs
);

let mut err = self.tcx().sess.struct_span_err(
cause.span(self.tcx()),
&format!(
"implementation of `{}` is not general enough",
self.tcx().def_path_str(trait_def_id),
),
let span = cause.span(self.tcx());
let msg = format!(
"implementation of `{}` is not general enough",
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 {
ObligationCauseCode::ItemObligation(def_id) => {
err.note(&format!(
"Due to a where-clause on `{}`,",
self.tcx().def_path_str(def_id),
));
}
_ => (),
}
let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code {
err.span_label(span, "doesn't satisfy where-clause");
err.span_label(
self.tcx().def_span(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 {
def_id: trait_def_id,
Expand Down Expand Up @@ -295,6 +300,7 @@ impl NiceRegionError<'me, 'tcx> {
expected_has_vid,
actual_has_vid,
any_self_ty_has_vid,
leading_ellipsis,
);

err
Expand All @@ -318,6 +324,7 @@ impl NiceRegionError<'me, 'tcx> {
expected_has_vid: Option<usize>,
actual_has_vid: Option<usize>,
any_self_ty_has_vid: bool,
leading_ellipsis: bool,
) {
// HACK(eddyb) maybe move this in a more central location.
#[derive(Copy, Clone)]
Expand Down Expand Up @@ -392,13 +399,15 @@ impl NiceRegionError<'me, 'tcx> {

let mut note = if passive_voice {
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.map(|tr| tr.self_ty()),
)
} else {
format!(
"`{}` must implement `{}`",
"{}`{}` must implement `{}`",
if leading_ellipsis { "..." } else { "" },
expected_trait_ref.map(|tr| tr.self_ty()),
expected_trait_ref,
)
Expand All @@ -407,20 +416,20 @@ impl NiceRegionError<'me, 'tcx> {
match (has_sub, has_sup) {
(Some(n1), Some(n2)) => {
let _ = write!(note,
", for any two lifetimes `'{}` and `'{}`",
", for any two lifetimes `'{}` and `'{}`...",
std::cmp::min(n1, n2),
std::cmp::max(n1, n2),
);
}
(Some(n), _) | (_, Some(n)) => {
let _ = write!(note,
", for any lifetime `'{}`",
", for any lifetime `'{}`...",
n,
);
}
(None, None) => if let Some(n) = expected_has_vid {
let _ = write!(note,
", for some specific lifetime `'{}`",
", for some specific lifetime `'{}`...",
n,
);
},
Expand All @@ -439,13 +448,13 @@ impl NiceRegionError<'me, 'tcx> {

let mut note = if passive_voice {
format!(
"but `{}` is actually implemented for the type `{}`",
"...but `{}` is actually implemented for the type `{}`",
actual_trait_ref,
actual_trait_ref.map(|tr| tr.self_ty()),
)
} else {
format!(
"but `{}` actually implements `{}`",
"...but `{}` actually implements `{}`",
actual_trait_ref.map(|tr| tr.self_ty()),
actual_trait_ref,
)
Expand Down
18 changes: 12 additions & 6 deletions src/test/ui/generator/auto-trait-regions.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
error: implementation of `Foo` is not general enough
--> $DIR/auto-trait-regions.rs:30:5
|
LL | auto trait Foo {}
| ----------------- trait `Foo` defined here
...
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: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
= 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`

error: implementation of `Foo` is not general enough
--> $DIR/auto-trait-regions.rs:48:5
|
LL | auto trait Foo {}
| ----------------- trait `Foo` defined here
...
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: but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
= 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`

error: aborting due to 2 previous errors

13 changes: 13 additions & 0 deletions src/test/ui/hrtb/due-to-where-clause.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
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> {}
17 changes: 17 additions & 0 deletions src/test/ui/hrtb/due-to-where-clause.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error: implementation of `Foo` is not general enough
--> $DIR/due-to-where-clause.rs:2: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

9 changes: 6 additions & 3 deletions src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
error: implementation of `Deserialize` is not general enough
--> $DIR/hrtb-cache-issue-54302.rs:19:5
|
LL | trait Deserialize<'de> {}
| ------------------------- trait `Deserialize` defined here
...
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: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
= note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
= note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`

error: aborting due to previous error

14 changes: 10 additions & 4 deletions src/test/ui/hrtb/issue-30786.migrate.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
error: implementation of `Stream` is not general enough
--> $DIR/issue-30786.rs:108:22
|
LL | let map = source.map(|x: &_| x);
| ^^^
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);
| ^^^ 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: 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: `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`

error: aborting due to previous error

4 changes: 2 additions & 2 deletions src/test/ui/hrtb/issue-30786.nll.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: higher-ranked subtype error
--> $DIR/issue-30786.rs:112:18
--> $DIR/issue-30786.rs:113:18
|
LL | let filter = map.filter(|x: &_| true);
| ^^^^^^^^^^^^^^^^^^^^^^^^

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.
| ^^^^^^^^^^^^^^
Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/hrtb/issue-30786.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

//[nll]compile-flags: -Z borrowck=mir

pub trait Stream {
pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here
type Item;
fn next(self) -> Option<Self::Item>;
}
Expand Down Expand Up @@ -109,6 +109,7 @@ fn main() {
//[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 but `Stream` is actually implemented for the type `&'1
//[migrate]~| NOTE implementation of `Stream` is not general enough
let filter = map.filter(|x: &_| true);
//[nll]~^ ERROR higher-ranked subtype error
let count = filter.count(); // Assert that we still have a valid stream.
Expand Down
54 changes: 37 additions & 17 deletions src/test/ui/issues/issue-54302-cases.stderr
Original file line number Diff line number Diff line change
@@ -1,38 +1,58 @@
error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:63:5
|
LL | <u32 as RefFoo<u32>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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`
LL | / trait Foo<'x, T> {
LL | | fn foo(self) -> &'x T;
LL | | }
| |_- trait `Foo` defined here
...
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: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`

error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:69:5
|
LL | <i32 as RefFoo<i32>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | / trait Foo<'x, T> {
LL | | fn foo(self) -> &'x T;
LL | | }
| |_- trait `Foo` defined here
...
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: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
= 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`

error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:75:5
|
LL | <u64 as RefFoo<u64>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | / trait Foo<'x, T> {
LL | | fn foo(self) -> &'x T;
LL | | }
| |_- trait `Foo` defined here
...
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: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
= 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`

error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:81:5
|
LL | <i64 as RefFoo<i64>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | / trait Foo<'x, T> {
LL | | fn foo(self) -> &'x T;
LL | | }
| |_- trait `Foo` defined here
...
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: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
= 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`

error: aborting due to 4 previous errors

9 changes: 6 additions & 3 deletions src/test/ui/issues/issue-54302.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
error: implementation of `Deserialize` is not general enough
--> $DIR/issue-54302.rs:13:5
|
LL | trait Deserialize<'de> {}
| ------------------------- trait `Deserialize` defined here
...
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: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
= note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
= note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`

error: aborting due to previous error

13 changes: 9 additions & 4 deletions src/test/ui/issues/issue-55731.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
error: implementation of `DistributedIteratorMulti` is not general enough
--> $DIR/issue-55731.rs:48:5
|
LL | multi(Map {
| ^^^^^
LL | / trait DistributedIteratorMulti<Source> {
LL | | type Item;
LL | | }
| |_- trait `DistributedIteratorMulti` defined here
...
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: but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
= 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`

error: aborting due to previous error

0 comments on commit 11b0ae6

Please sign in to comment.