Rollup merge of #64085 - estebank:hrtb-errors, r=oli-obk
Tweak unsatisfied HRTB errors r? @oli-obk Close #35180.
This commit is contained in:
commit
3edc644751
@ -192,23 +192,28 @@ fn try_report_placeholders_trait(
|
||||
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,
|
||||
@ -295,6 +300,7 @@ fn try_report_placeholders_trait(
|
||||
expected_has_vid,
|
||||
actual_has_vid,
|
||||
any_self_ty_has_vid,
|
||||
leading_ellipsis,
|
||||
);
|
||||
|
||||
err
|
||||
@ -318,6 +324,7 @@ fn explain_actual_impl_that_was_found(
|
||||
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)]
|
||||
@ -392,13 +399,15 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
||||
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,
|
||||
)
|
||||
@ -407,20 +416,20 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
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,
|
||||
);
|
||||
},
|
||||
@ -439,13 +448,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
||||
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,
|
||||
)
|
||||
|
@ -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
|
||||
|
||||
|
16
src/test/ui/hrtb/due-to-where-clause.rs
Normal file
16
src/test/ui/hrtb/due-to-where-clause.rs
Normal 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> {}
|
17
src/test/ui/hrtb/due-to-where-clause.stderr
Normal file
17
src/test/ui/hrtb/due-to-where-clause.stderr
Normal 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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
@ -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>;
|
||||
}
|
||||
@ -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.
|
||||
|
@ -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)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
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`
|
||||
= 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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user