Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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`
LL | F: FnMut() + Send,
| ^^^^ 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`.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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>,
Expand Down Expand Up @@ -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`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
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
}
}
Expand Down
12 changes: 12 additions & 0 deletions tests/ui/impl-trait/in-trait/mismatched-where-clauses.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions tests/ui/impl-trait/in-trait/mismatched-where-clauses.stderr
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 1 addition & 1 deletion tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
24 changes: 11 additions & 13 deletions tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
Original file line number Diff line number Diff line change
@@ -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
|
Expand All @@ -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
|
Expand All @@ -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`.
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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