Report impl has stricter requirements even when RPITIT inference gets in the way
This commit is contained in:
parent
4363f9b6f6
commit
c29838843b
11 changed files with 90 additions and 54 deletions
|
@ -529,6 +529,26 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
|
||||
|
||||
// Check that the where clauses of the impl are satisfied by the hybrid param env.
|
||||
// You might ask -- what does this have to do with RPITIT inference? Nothing.
|
||||
// We check these because if the where clauses of the signatures do not match
|
||||
// up, then we don't want to give spurious other errors that point at the RPITITs.
|
||||
// They're not necessary to check, though, because we already check them in
|
||||
// `compare_method_predicate_entailment`.
|
||||
let impl_m_own_bounds = tcx.predicates_of(impl_m_def_id).instantiate_own_identity();
|
||||
for (predicate, span) in impl_m_own_bounds {
|
||||
let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
|
||||
let predicate = ocx.normalize(&normalize_cause, param_env, predicate);
|
||||
|
||||
let cause =
|
||||
ObligationCause::new(span, impl_m_def_id, ObligationCauseCode::CompareImplItem {
|
||||
impl_item_def_id: impl_m_def_id,
|
||||
trait_item_def_id: trait_m.def_id,
|
||||
kind: impl_m.kind,
|
||||
});
|
||||
ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
|
||||
}
|
||||
|
||||
// Normalize the impl signature with fresh variables for lifetime inference.
|
||||
let misc_cause = ObligationCause::misc(return_span, impl_m_def_id);
|
||||
let impl_sig = ocx.normalize(
|
||||
|
|
|
@ -11,9 +11,9 @@ struct Baz {}
|
|||
|
||||
impl Foo for Baz {
|
||||
async fn bar<F>(&mut self, _func: F) -> ()
|
||||
//~^ ERROR `F` cannot be sent between threads safely
|
||||
where
|
||||
F: FnMut() + Send,
|
||||
//~^ impl has stricter requirements than trait
|
||||
{
|
||||
()
|
||||
}
|
||||
|
|
|
@ -1,21 +1,14 @@
|
|||
error[E0277]: `F` cannot be sent between threads safely
|
||||
--> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:13:5
|
||||
error[E0276]: impl has stricter requirements than trait
|
||||
--> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:15:22
|
||||
|
|
||||
LL | / async fn bar<F>(&mut self, _func: F) -> ()
|
||||
LL | |
|
||||
LL | / fn bar<F>(&mut self, func: F) -> impl std::future::Future<Output = ()> + Send
|
||||
LL | | where
|
||||
LL | | F: FnMut() + Send,
|
||||
| |__________________________^ `F` cannot be sent between threads safely
|
||||
|
|
||||
note: required by a bound in `<Baz as Foo>::bar`
|
||||
--> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:16:22
|
||||
|
|
||||
LL | async fn bar<F>(&mut self, _func: F) -> ()
|
||||
| --- required by a bound in this associated function
|
||||
LL | | F: FnMut();
|
||||
| |___________________- definition of `bar` from trait
|
||||
...
|
||||
LL | F: FnMut() + Send,
|
||||
| ^^^^ required by this bound in `<Baz as Foo>::bar`
|
||||
| ^^^^ impl has extra requirement `F: Send`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
For more information about this error, try `rustc --explain E0276`.
|
||||
|
|
|
@ -19,11 +19,11 @@ help: consider further restricting type parameter `F` with trait `MyFn`
|
|||
LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
|
||||
| +++++++++++
|
||||
|
||||
error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
|
||||
--> $DIR/false-positive-predicate-entailment-error.rs:36:30
|
||||
error[E0277]: the trait bound `F: Callback<i32>` is not satisfied
|
||||
--> $DIR/false-positive-predicate-entailment-error.rs:42:12
|
||||
|
|
||||
LL | fn autobatch<F>(self) -> impl Trait
|
||||
| ^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
|
||||
LL | F: Callback<Self::CallbackArg>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
|
||||
|
|
||||
note: required for `F` to implement `Callback<i32>`
|
||||
--> $DIR/false-positive-predicate-entailment-error.rs:14:21
|
||||
|
@ -32,14 +32,14 @@ LL | impl<A, F: MyFn<A>> Callback<A> for F {
|
|||
| ------- ^^^^^^^^^^^ ^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: required by a bound in `<Sender as ChannelSender>::autobatch`
|
||||
--> $DIR/false-positive-predicate-entailment-error.rs:43:12
|
||||
note: the requirement `F: Callback<i32>` appears on the `impl`'s method `autobatch` but not on the corresponding trait's method
|
||||
--> $DIR/false-positive-predicate-entailment-error.rs:25:8
|
||||
|
|
||||
LL | fn autobatch<F>(self) -> impl Trait
|
||||
| --------- required by a bound in this associated function
|
||||
LL | trait ChannelSender {
|
||||
| ------------- in this trait
|
||||
...
|
||||
LL | F: Callback<Self::CallbackArg>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<Sender as ChannelSender>::autobatch`
|
||||
LL | fn autobatch<F>(self) -> impl Trait
|
||||
| ^^^^^^^^^ this trait's method doesn't have the requirement `F: Callback<i32>`
|
||||
help: consider further restricting type parameter `F` with trait `MyFn`
|
||||
|
|
||||
LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
|
||||
|
@ -118,7 +118,7 @@ LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
|
|||
| +++++++++++
|
||||
|
||||
error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
|
||||
--> $DIR/false-positive-predicate-entailment-error.rs:43:12
|
||||
--> $DIR/false-positive-predicate-entailment-error.rs:42:12
|
||||
|
|
||||
LL | F: Callback<Self::CallbackArg>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
|
||||
|
|
|
@ -38,10 +38,10 @@ impl ChannelSender for Sender {
|
|||
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
|
||||
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
|
||||
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
|
||||
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
|
||||
where
|
||||
F: Callback<Self::CallbackArg>,
|
||||
//[current]~^ ERROR the trait bound `F: MyFn<i32>` is not satisfied
|
||||
//[current]~| ERROR the trait bound `F: Callback<i32>` is not satisfied
|
||||
{
|
||||
Thing
|
||||
}
|
||||
|
|
12
tests/ui/impl-trait/in-trait/mismatched-where-clauses.rs
Normal file
12
tests/ui/impl-trait/in-trait/mismatched-where-clauses.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
trait Foo {
|
||||
fn foo<S>(s: S) -> impl Sized;
|
||||
}
|
||||
|
||||
trait Bar {}
|
||||
|
||||
impl Foo for () {
|
||||
fn foo<S>(s: S) -> impl Sized where S: Bar {}
|
||||
//~^ ERROR impl has stricter requirements than trait
|
||||
}
|
||||
|
||||
fn main() {}
|
12
tests/ui/impl-trait/in-trait/mismatched-where-clauses.stderr
Normal file
12
tests/ui/impl-trait/in-trait/mismatched-where-clauses.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0276]: impl has stricter requirements than trait
|
||||
--> $DIR/mismatched-where-clauses.rs:8:44
|
||||
|
|
||||
LL | fn foo<S>(s: S) -> impl Sized;
|
||||
| ------------------------------ definition of `foo` from trait
|
||||
...
|
||||
LL | fn foo<S>(s: S) -> impl Sized where S: Bar {}
|
||||
| ^^^ impl has extra requirement `S: Bar`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0276`.
|
|
@ -8,7 +8,7 @@ impl Foo<char> for Bar {
|
|||
fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
|
||||
//~^ ERROR: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied [E0277]
|
||||
//~| ERROR: the trait bound `Bar: Foo<u8>` is not satisfied [E0277]
|
||||
//~| ERROR: the trait bound `F2: Foo<u8>` is not satisfied
|
||||
//~| ERROR: impl has stricter requirements than trait
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
error[E0276]: impl has stricter requirements than trait
|
||||
--> $DIR/return-dont-satisfy-bounds.rs:8:16
|
||||
|
|
||||
LL | fn foo<F2>(self) -> impl Foo<T>;
|
||||
| -------------------------------- definition of `foo` from trait
|
||||
...
|
||||
LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
|
||||
| ^^^^^^^ impl has extra requirement `F2: Foo<u8>`
|
||||
|
||||
error[E0277]: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied
|
||||
--> $DIR/return-dont-satisfy-bounds.rs:8:34
|
||||
|
|
||||
|
@ -11,18 +20,6 @@ note: required by a bound in `Foo::{synthetic#0}`
|
|||
LL | fn foo<F2>(self) -> impl Foo<T>;
|
||||
| ^^^^^^ required by this bound in `Foo::{synthetic#0}`
|
||||
|
||||
error[E0277]: the trait bound `F2: Foo<u8>` is not satisfied
|
||||
--> $DIR/return-dont-satisfy-bounds.rs:8:34
|
||||
|
|
||||
LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
|
||||
| ^^^^^^^^^^^^ the trait `Foo<u8>` is not implemented for `F2`
|
||||
|
|
||||
note: required by a bound in `<Bar as Foo<char>>::foo`
|
||||
--> $DIR/return-dont-satisfy-bounds.rs:8:16
|
||||
|
|
||||
LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
|
||||
| ^^^^^^^ required by this bound in `<Bar as Foo<char>>::foo`
|
||||
|
||||
error[E0277]: the trait bound `Bar: Foo<u8>` is not satisfied
|
||||
--> $DIR/return-dont-satisfy-bounds.rs:8:34
|
||||
|
|
||||
|
@ -38,4 +35,5 @@ LL | self
|
|||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Some errors have detailed explanations: E0276, E0277.
|
||||
For more information about an error, try `rustc --explain E0276`.
|
||||
|
|
|
@ -4,9 +4,9 @@ trait Extend {
|
|||
|
||||
impl Extend for () {
|
||||
fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str)
|
||||
//~^ ERROR in type `&'static &'a ()`, reference has a longer lifetime than the data it references
|
||||
where
|
||||
'a: 'static,
|
||||
//~^ impl has stricter requirements than trait
|
||||
{
|
||||
(None, s)
|
||||
}
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references
|
||||
--> $DIR/rpitit-hidden-types-self-implied-wf-via-param.rs:6:38
|
||||
error[E0276]: impl has stricter requirements than trait
|
||||
--> $DIR/rpitit-hidden-types-self-implied-wf-via-param.rs:8:13
|
||||
|
|
||||
LL | fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | fn extend<'a: 'a>(_: &'a str) -> (impl Sized + 'a, &'static str);
|
||||
| ----------------------------------------------------------------- definition of `extend` from trait
|
||||
...
|
||||
LL | 'a: 'static,
|
||||
| ^^^^^^^ impl has extra requirement `'a: 'static`
|
||||
|
|
||||
= note: the pointer is valid for the static lifetime
|
||||
note: but the referenced data is only valid for the lifetime `'a` as defined here
|
||||
--> $DIR/rpitit-hidden-types-self-implied-wf-via-param.rs:6:15
|
||||
help: copy the `where` clause predicates from the trait
|
||||
|
|
||||
LL | where 'a: 'a
|
||||
|
|
||||
LL | fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str)
|
||||
| ^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0491`.
|
||||
For more information about this error, try `rustc --explain E0276`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue