1
Fork 0

Rollup merge of #135055 - compiler-errors:rpitit-infer-in-stricter-impl, r=estebank

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

See the comment I added in the code. Fixes #122506.
This commit is contained in:
Matthias Krüger 2025-01-04 09:54:38 +01:00 committed by GitHub
commit b0b54f2f8b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
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 infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(infcx); 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. // Normalize the impl signature with fresh variables for lifetime inference.
let misc_cause = ObligationCause::misc(return_span, impl_m_def_id); let misc_cause = ObligationCause::misc(return_span, impl_m_def_id);
let impl_sig = ocx.normalize( let impl_sig = ocx.normalize(

View file

@ -11,9 +11,9 @@ struct Baz {}
impl Foo for Baz { impl Foo for Baz {
async fn bar<F>(&mut self, _func: F) -> () async fn bar<F>(&mut self, _func: F) -> ()
//~^ ERROR `F` cannot be sent between threads safely
where where
F: FnMut() + Send, F: FnMut() + Send,
//~^ impl has stricter requirements than trait
{ {
() ()
} }

View file

@ -1,21 +1,14 @@
error[E0277]: `F` cannot be sent between threads safely error[E0276]: impl has stricter requirements than trait
--> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:13:5 --> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:15:22
| |
LL | / async fn bar<F>(&mut self, _func: F) -> () LL | / fn bar<F>(&mut self, func: F) -> impl std::future::Future<Output = ()> + Send
LL | |
LL | | where LL | | where
LL | | F: FnMut() + Send, LL | | F: FnMut();
| |__________________________^ `F` cannot be sent between threads safely | |___________________- definition of `bar` from trait
|
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() + Send, 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 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>, LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
| +++++++++++ | +++++++++++
error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied error[E0277]: the trait bound `F: Callback<i32>` is not satisfied
--> $DIR/false-positive-predicate-entailment-error.rs:36:30 --> $DIR/false-positive-predicate-entailment-error.rs:42:12
| |
LL | fn autobatch<F>(self) -> impl Trait LL | F: Callback<Self::CallbackArg>,
| ^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
| |
note: required for `F` to implement `Callback<i32>` note: required for `F` to implement `Callback<i32>`
--> $DIR/false-positive-predicate-entailment-error.rs:14:21 --> $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 | unsatisfied trait bound introduced here
note: required by a bound in `<Sender as ChannelSender>::autobatch` 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:43:12 --> $DIR/false-positive-predicate-entailment-error.rs:25:8
| |
LL | fn autobatch<F>(self) -> impl Trait LL | trait ChannelSender {
| --------- required by a bound in this associated function | ------------- in this trait
... ...
LL | F: Callback<Self::CallbackArg>, LL | fn autobatch<F>(self) -> impl Trait
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<Sender as ChannelSender>::autobatch` | ^^^^^^^^^ this trait's method doesn't have the requirement `F: Callback<i32>`
help: consider further restricting type parameter `F` with trait `MyFn` help: consider further restricting type parameter `F` with trait `MyFn`
| |
LL | F: Callback<Self::CallbackArg> + MyFn<i32>, 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 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>, LL | F: Callback<Self::CallbackArg>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`

View file

@ -38,11 +38,11 @@ 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
//[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 where
F: Callback<Self::CallbackArg>, F: Callback<Self::CallbackArg>,
//[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: Callback<i32>` is not satisfied
{
Thing 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> { 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 `impl Foo<u8>: Foo<char>` is not satisfied [E0277]
//~| ERROR: the trait bound `Bar: Foo<u8>` 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 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 error[E0277]: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied
--> $DIR/return-dont-satisfy-bounds.rs:8:34 --> $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>; LL | fn foo<F2>(self) -> impl Foo<T>;
| ^^^^^^ required by this bound in `Foo::{synthetic#0}` | ^^^^^^ 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 error[E0277]: the trait bound `Bar: Foo<u8>` is not satisfied
--> $DIR/return-dont-satisfy-bounds.rs:8:34 --> $DIR/return-dont-satisfy-bounds.rs:8:34
| |
@ -38,4 +35,5 @@ LL | self
error: aborting due to 3 previous errors 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 () { impl Extend for () {
fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str) 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 where
'a: 'static, 'a: 'static,
//~^ impl has stricter requirements than trait
{ {
(None, s) (None, s)
} }

View file

@ -1,16 +1,17 @@
error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references error[E0276]: impl has stricter requirements than trait
--> $DIR/rpitit-hidden-types-self-implied-wf-via-param.rs:6:38 --> $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 help: copy the `where` clause predicates from the trait
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 LL | where 'a: 'a
| |
LL | fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str)
| ^^
error: aborting due to 1 previous error 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`.