Skip to content

Commit c298388

Browse files
Report impl has stricter requirements even when RPITIT inference gets in the way
1 parent 4363f9b commit c298388

11 files changed

+90
-54
lines changed

Diff for: compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+20
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,26 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
529529
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
530530
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
531531

532+
// Check that the where clauses of the impl are satisfied by the hybrid param env.
533+
// You might ask -- what does this have to do with RPITIT inference? Nothing.
534+
// We check these because if the where clauses of the signatures do not match
535+
// up, then we don't want to give spurious other errors that point at the RPITITs.
536+
// They're not necessary to check, though, because we already check them in
537+
// `compare_method_predicate_entailment`.
538+
let impl_m_own_bounds = tcx.predicates_of(impl_m_def_id).instantiate_own_identity();
539+
for (predicate, span) in impl_m_own_bounds {
540+
let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
541+
let predicate = ocx.normalize(&normalize_cause, param_env, predicate);
542+
543+
let cause =
544+
ObligationCause::new(span, impl_m_def_id, ObligationCauseCode::CompareImplItem {
545+
impl_item_def_id: impl_m_def_id,
546+
trait_item_def_id: trait_m.def_id,
547+
kind: impl_m.kind,
548+
});
549+
ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
550+
}
551+
532552
// Normalize the impl signature with fresh variables for lifetime inference.
533553
let misc_cause = ObligationCause::misc(return_span, impl_m_def_id);
534554
let impl_sig = ocx.normalize(

Diff for: tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ struct Baz {}
1111

1212
impl Foo for Baz {
1313
async fn bar<F>(&mut self, _func: F) -> ()
14-
//~^ ERROR `F` cannot be sent between threads safely
1514
where
1615
F: FnMut() + Send,
16+
//~^ impl has stricter requirements than trait
1717
{
1818
()
1919
}
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
1-
error[E0277]: `F` cannot be sent between threads safely
2-
--> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:13:5
1+
error[E0276]: impl has stricter requirements than trait
2+
--> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:15:22
33
|
4-
LL | / async fn bar<F>(&mut self, _func: F) -> ()
5-
LL | |
4+
LL | / fn bar<F>(&mut self, func: F) -> impl std::future::Future<Output = ()> + Send
65
LL | | where
7-
LL | | F: FnMut() + Send,
8-
| |__________________________^ `F` cannot be sent between threads safely
9-
|
10-
note: required by a bound in `<Baz as Foo>::bar`
11-
--> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:16:22
12-
|
13-
LL | async fn bar<F>(&mut self, _func: F) -> ()
14-
| --- required by a bound in this associated function
6+
LL | | F: FnMut();
7+
| |___________________- definition of `bar` from trait
158
...
16-
LL | F: FnMut() + Send,
17-
| ^^^^ required by this bound in `<Baz as Foo>::bar`
9+
LL | F: FnMut() + Send,
10+
| ^^^^ impl has extra requirement `F: Send`
1811

1912
error: aborting due to 1 previous error
2013

21-
For more information about this error, try `rustc --explain E0277`.
14+
For more information about this error, try `rustc --explain E0276`.

Diff for: tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr

+11-11
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ help: consider further restricting type parameter `F` with trait `MyFn`
1919
LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
2020
| +++++++++++
2121

22-
error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
23-
--> $DIR/false-positive-predicate-entailment-error.rs:36:30
22+
error[E0277]: the trait bound `F: Callback<i32>` is not satisfied
23+
--> $DIR/false-positive-predicate-entailment-error.rs:42:12
2424
|
25-
LL | fn autobatch<F>(self) -> impl Trait
26-
| ^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
25+
LL | F: Callback<Self::CallbackArg>,
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
2727
|
2828
note: required for `F` to implement `Callback<i32>`
2929
--> $DIR/false-positive-predicate-entailment-error.rs:14:21
@@ -32,14 +32,14 @@ LL | impl<A, F: MyFn<A>> Callback<A> for F {
3232
| ------- ^^^^^^^^^^^ ^
3333
| |
3434
| unsatisfied trait bound introduced here
35-
note: required by a bound in `<Sender as ChannelSender>::autobatch`
36-
--> $DIR/false-positive-predicate-entailment-error.rs:43:12
35+
note: the requirement `F: Callback<i32>` appears on the `impl`'s method `autobatch` but not on the corresponding trait's method
36+
--> $DIR/false-positive-predicate-entailment-error.rs:25:8
3737
|
38-
LL | fn autobatch<F>(self) -> impl Trait
39-
| --------- required by a bound in this associated function
38+
LL | trait ChannelSender {
39+
| ------------- in this trait
4040
...
41-
LL | F: Callback<Self::CallbackArg>,
42-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<Sender as ChannelSender>::autobatch`
41+
LL | fn autobatch<F>(self) -> impl Trait
42+
| ^^^^^^^^^ this trait's method doesn't have the requirement `F: Callback<i32>`
4343
help: consider further restricting type parameter `F` with trait `MyFn`
4444
|
4545
LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
@@ -118,7 +118,7 @@ LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
118118
| +++++++++++
119119

120120
error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
121-
--> $DIR/false-positive-predicate-entailment-error.rs:43:12
121+
--> $DIR/false-positive-predicate-entailment-error.rs:42:12
122122
|
123123
LL | F: Callback<Self::CallbackArg>,
124124
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`

Diff for: tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ impl ChannelSender for Sender {
3838
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
3939
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
4040
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
41-
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
4241
where
4342
F: Callback<Self::CallbackArg>,
4443
//[current]~^ ERROR the trait bound `F: MyFn<i32>` is not satisfied
45-
{
44+
//[current]~| ERROR the trait bound `F: Callback<i32>` is not satisfied
45+
{
4646
Thing
4747
}
4848
}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
trait Foo {
2+
fn foo<S>(s: S) -> impl Sized;
3+
}
4+
5+
trait Bar {}
6+
7+
impl Foo for () {
8+
fn foo<S>(s: S) -> impl Sized where S: Bar {}
9+
//~^ ERROR impl has stricter requirements than trait
10+
}
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0276]: impl has stricter requirements than trait
2+
--> $DIR/mismatched-where-clauses.rs:8:44
3+
|
4+
LL | fn foo<S>(s: S) -> impl Sized;
5+
| ------------------------------ definition of `foo` from trait
6+
...
7+
LL | fn foo<S>(s: S) -> impl Sized where S: Bar {}
8+
| ^^^ impl has extra requirement `S: Bar`
9+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0276`.

Diff for: tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ impl Foo<char> for Bar {
88
fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
99
//~^ ERROR: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied [E0277]
1010
//~| ERROR: the trait bound `Bar: Foo<u8>` is not satisfied [E0277]
11-
//~| ERROR: the trait bound `F2: Foo<u8>` is not satisfied
11+
//~| ERROR: impl has stricter requirements than trait
1212
self
1313
}
1414
}

Diff for: tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr

+11-13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
error[E0276]: impl has stricter requirements than trait
2+
--> $DIR/return-dont-satisfy-bounds.rs:8:16
3+
|
4+
LL | fn foo<F2>(self) -> impl Foo<T>;
5+
| -------------------------------- definition of `foo` from trait
6+
...
7+
LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
8+
| ^^^^^^^ impl has extra requirement `F2: Foo<u8>`
9+
110
error[E0277]: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied
211
--> $DIR/return-dont-satisfy-bounds.rs:8:34
312
|
@@ -11,18 +20,6 @@ note: required by a bound in `Foo::{synthetic#0}`
1120
LL | fn foo<F2>(self) -> impl Foo<T>;
1221
| ^^^^^^ required by this bound in `Foo::{synthetic#0}`
1322

14-
error[E0277]: the trait bound `F2: Foo<u8>` is not satisfied
15-
--> $DIR/return-dont-satisfy-bounds.rs:8:34
16-
|
17-
LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
18-
| ^^^^^^^^^^^^ the trait `Foo<u8>` is not implemented for `F2`
19-
|
20-
note: required by a bound in `<Bar as Foo<char>>::foo`
21-
--> $DIR/return-dont-satisfy-bounds.rs:8:16
22-
|
23-
LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
24-
| ^^^^^^^ required by this bound in `<Bar as Foo<char>>::foo`
25-
2623
error[E0277]: the trait bound `Bar: Foo<u8>` is not satisfied
2724
--> $DIR/return-dont-satisfy-bounds.rs:8:34
2825
|
@@ -38,4 +35,5 @@ LL | self
3835

3936
error: aborting due to 3 previous errors
4037

41-
For more information about this error, try `rustc --explain E0277`.
38+
Some errors have detailed explanations: E0276, E0277.
39+
For more information about an error, try `rustc --explain E0276`.

Diff for: tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ trait Extend {
44

55
impl Extend for () {
66
fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str)
7-
//~^ ERROR in type `&'static &'a ()`, reference has a longer lifetime than the data it references
87
where
98
'a: 'static,
9+
//~^ impl has stricter requirements than trait
1010
{
1111
(None, s)
1212
}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references
2-
--> $DIR/rpitit-hidden-types-self-implied-wf-via-param.rs:6:38
1+
error[E0276]: impl has stricter requirements than trait
2+
--> $DIR/rpitit-hidden-types-self-implied-wf-via-param.rs:8:13
33
|
4-
LL | fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str)
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | fn extend<'a: 'a>(_: &'a str) -> (impl Sized + 'a, &'static str);
5+
| ----------------------------------------------------------------- definition of `extend` from trait
6+
...
7+
LL | 'a: 'static,
8+
| ^^^^^^^ impl has extra requirement `'a: 'static`
69
|
7-
= note: the pointer is valid for the static lifetime
8-
note: but the referenced data is only valid for the lifetime `'a` as defined here
9-
--> $DIR/rpitit-hidden-types-self-implied-wf-via-param.rs:6:15
10+
help: copy the `where` clause predicates from the trait
11+
|
12+
LL | where 'a: 'a
1013
|
11-
LL | fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str)
12-
| ^^
1314

1415
error: aborting due to 1 previous error
1516

16-
For more information about this error, try `rustc --explain E0491`.
17+
For more information about this error, try `rustc --explain E0276`.

0 commit comments

Comments
 (0)