1
Fork 0

Report impl has stricter requirements even when RPITIT inference gets in the way

This commit is contained in:
Michael Goulet 2025-01-03 02:45:09 +00:00
parent 4363f9b6f6
commit c29838843b
11 changed files with 90 additions and 54 deletions

View file

@ -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(

View file

@ -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
{
()
}

View file

@ -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`.

View file

@ -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`

View file

@ -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
}

View 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() {}

View 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`.

View file

@ -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
}
}

View file

@ -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`.

View file

@ -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)
}

View file

@ -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`.