about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2025-01-04 09:54:38 +0100
committerGitHub <noreply@github.com>2025-01-04 09:54:38 +0100
commitb0b54f2f8bbf62e130b5249af7e6da71a655a164 (patch)
tree8045455570d48624d7d8cee9c15d7b83f9df256e
parent8744b44e6bde053f7656a3c727c968177ee8e4b6 (diff)
parentc29838843b0573a583f6457c176d9d49873e9eb5 (diff)
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.
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs20
-rw-r--r--tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs2
-rw-r--r--tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr23
-rw-r--r--tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr22
-rw-r--r--tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs4
-rw-r--r--tests/ui/impl-trait/in-trait/mismatched-where-clauses.rs12
-rw-r--r--tests/ui/impl-trait/in-trait/mismatched-where-clauses.stderr12
-rw-r--r--tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr24
-rw-r--r--tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr21
11 files changed, 90 insertions, 54 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index a6b504de3da..4a957d5da24 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -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(
diff --git a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs
index b4df58b3c25..4dfeab9e8c3 100644
--- a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs
+++ b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs
@@ -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
     {
         ()
     }
diff --git a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr
index e6379954776..8d5cad4493e 100644
--- a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr
+++ b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr
@@ -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`.
diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
index e38e18857ef..b6e7e02f331 100644
--- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
+++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
@@ -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`
diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs
index 2987d183e04..cbe6c32b890 100644
--- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs
+++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs
@@ -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
     }
 }
diff --git a/tests/ui/impl-trait/in-trait/mismatched-where-clauses.rs b/tests/ui/impl-trait/in-trait/mismatched-where-clauses.rs
new file mode 100644
index 00000000000..a2c735cc126
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/mismatched-where-clauses.rs
@@ -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() {}
diff --git a/tests/ui/impl-trait/in-trait/mismatched-where-clauses.stderr b/tests/ui/impl-trait/in-trait/mismatched-where-clauses.stderr
new file mode 100644
index 00000000000..cc6e027cad7
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/mismatched-where-clauses.stderr
@@ -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`.
diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs
index ee47de2c732..ff265e576b9 100644
--- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs
+++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs
@@ -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
     }
 }
diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
index 663c9a7f2ae..5cb80386b35 100644
--- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
+++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
@@ -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`.
diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs
index 37b0b229776..7a3a59d37c6 100644
--- a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs
+++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs
@@ -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)
     }
diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr
index 5ace64b6903..15bef5c78b0 100644
--- a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr
+++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr
@@ -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`.