Rollup merge of #125447 - oli-obk:eq_opaque_pred, r=compiler-errors

Allow constraining opaque types during subtyping in the trait system

Previous attempt: https://github.com/rust-lang/rust/pull/123979

Sometimes we don't immediately perform subtyping, but instead register a subtyping obligation and solve that obligation when its inference variables become resolved. Unlike immediate subtyping, we currently do not allow registering hidden types for opaque types. This PR also allows that.
This commit is contained in:
León Orell Valerian Liehr 2024-06-19 13:04:56 +02:00 committed by GitHub
commit 25d47fe388
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 37 additions and 87 deletions

View File

@ -878,9 +878,9 @@ impl<'tcx> InferCtxt<'tcx> {
self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| {
if a_is_expected { if a_is_expected {
Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::No, a, b)) Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b))
} else { } else {
Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::No, b, a)) Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a))
} }
}) })
} }

View File

@ -2,58 +2,23 @@
//! No hidden types are being constrained in the subtyping predicate, but type and //! No hidden types are being constrained in the subtyping predicate, but type and
//! lifetime variables get subtyped in the generic parameter list of the opaque. //! lifetime variables get subtyped in the generic parameter list of the opaque.
use std::iter; //@ check-pass
mod either { fn foo() -> impl Default + Copy {
pub enum Either<L, R> { if false {
Left(L), let x = Default::default();
Right(R), // add `Subtype(?x, ?y)` obligation
} let y = x;
impl<L: Iterator, R: Iterator<Item = L::Item>> Iterator for Either<L, R> { // Make a tuple `(?x, ?y)` and equate it with `(impl Default, u32)`.
type Item = L::Item; // For us to try and prove a `Subtype(impl Default, u32)` obligation,
fn next(&mut self) -> Option<Self::Item> { // we have to instantiate both `?x` and `?y` without any
todo!() // `select_where_possible` calls inbetween.
} let mut tup = &mut (x, y);
} let assign_tup = &mut (foo(), 1u32);
pub use self::Either::{Left, Right}; tup = assign_tup;
}
pub enum BabeConsensusLogRef<'a> {
NextEpochData(BabeNextEpochRef<'a>),
NextConfigData,
}
impl<'a> BabeConsensusLogRef<'a> {
pub fn scale_encoding(
&self,
) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
//~^ ERROR is not satisfied
//~| ERROR is not satisfied
//~| ERROR is not satisfied
match self {
BabeConsensusLogRef::NextEpochData(digest) => either::Left(either::Left(
digest.scale_encoding().map(either::Left).map(either::Left),
)),
BabeConsensusLogRef::NextConfigData => either::Right(
// The Opaque type from ``scale_encoding` gets used opaquely here, while the `R`
// generic parameter of `Either` contains type variables that get subtyped and the
// opaque type contains lifetime variables that get subtyped.
iter::once(either::Right(either::Left([1])))
.chain(std::iter::once([1]).map(either::Right).map(either::Right)),
),
}
}
}
pub struct BabeNextEpochRef<'a>(&'a ());
impl<'a> BabeNextEpochRef<'a> {
pub fn scale_encoding(
&self,
) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
std::iter::once([1])
} }
1u32
} }
fn main() {} fn main() {}

View File

@ -1,21 +0,0 @@
error[E0277]: the trait bound `Either<Either<Map<Map<impl Iterator<Item = impl AsRef<[u8]> + Clone + '_> + Clone + '_, fn(impl AsRef<[u8]> + Clone + '_) -> Either<impl AsRef<[u8]> + Clone + '_, _> {Either::<impl AsRef<[u8]> + Clone + '_, _>::Left}>, fn(Either<impl AsRef<[u8]> + Clone + '_, _>) -> Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either::<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Left}>, _>, std::iter::Chain<std::iter::Once<Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>>, Map<Map<std::iter::Once<[{integer}; 1]>, fn([{integer}; 1]) -> Either<[{integer}; 1], [{integer}; 1]> {Either::<[{integer}; 1], [{integer}; 1]>::Right}>, fn(Either<[{integer}; 1], [{integer}; 1]>) -> Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either::<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Right}>>>: Clone` is not satisfied
--> $DIR/lazy_subtyping_of_opaques.rs:30:10
|
LL | ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Either<Either<Map<Map<impl Iterator<Item = impl AsRef<[u8]> + Clone + '_> + Clone + '_, fn(impl AsRef<[u8]> + Clone + '_) -> Either<impl AsRef<[u8]> + Clone + '_, _> {Either::<impl AsRef<[u8]> + Clone + '_, _>::Left}>, fn(Either<impl AsRef<[u8]> + Clone + '_, _>) -> Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either::<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Left}>, _>, std::iter::Chain<std::iter::Once<Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>>, Map<Map<std::iter::Once<[{integer}; 1]>, fn([{integer}; 1]) -> Either<[{integer}; 1], [{integer}; 1]> {Either::<[{integer}; 1], [{integer}; 1]>::Right}>, fn(Either<[{integer}; 1], [{integer}; 1]>) -> Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either::<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Right}>>>`
error[E0277]: the trait bound `Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>: AsRef<[u8]>` is not satisfied
--> $DIR/lazy_subtyping_of_opaques.rs:30:31
|
LL | ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsRef<[u8]>` is not implemented for `Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>`
error[E0277]: the trait bound `Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>: Clone` is not satisfied
--> $DIR/lazy_subtyping_of_opaques.rs:30:31
|
LL | ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -7,9 +7,10 @@
type Tait = impl FnOnce() -> (); type Tait = impl FnOnce() -> ();
fn reify_as_tait() -> Thunk<Tait> { fn reify_as_tait() -> Thunk<Tait> {
//~^ ERROR: expected a `FnOnce()` closure, found `()`
Thunk::new(|cont| cont) Thunk::new(|cont| cont)
//~^ ERROR: mismatched types //~^ ERROR: mismatched types
//~| ERROR: mismatched types //~| ERROR: expected a `FnOnce()` closure, found `()`
} }
struct Thunk<F>(F); struct Thunk<F>(F);

View File

@ -1,26 +1,31 @@
error[E0308]: mismatched types error[E0277]: expected a `FnOnce()` closure, found `()`
--> $DIR/lazy_subtyping_of_opaques.rs:10:23 --> $DIR/lazy_subtyping_of_opaques.rs:11:23
| |
LL | type Tait = impl FnOnce() -> ();
| ------------------- the found opaque type
...
LL | Thunk::new(|cont| cont) LL | Thunk::new(|cont| cont)
| ^^^^ expected `()`, found opaque type | ^^^^ expected an `FnOnce()` closure, found `()`
| |
= note: expected unit type `()` = help: the trait `FnOnce()` is not implemented for `()`
found opaque type `Tait` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
error[E0308]: mismatched types error[E0277]: expected a `FnOnce()` closure, found `()`
--> $DIR/lazy_subtyping_of_opaques.rs:10:5 --> $DIR/lazy_subtyping_of_opaques.rs:9:23
| |
LL | fn reify_as_tait() -> Thunk<Tait> { LL | fn reify_as_tait() -> Thunk<Tait> {
| ----------- expected `Thunk<_>` because of return type | ^^^^^^^^^^^ expected an `FnOnce()` closure, found `()`
|
= help: the trait `FnOnce()` is not implemented for `()`
= note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
error[E0308]: mismatched types
--> $DIR/lazy_subtyping_of_opaques.rs:11:5
|
LL | Thunk::new(|cont| cont) LL | Thunk::new(|cont| cont)
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `Thunk<_>`, found `()` | ^^^^^^^^^^^^^^^^^^^^^^^ expected `Thunk<_>`, found `()`
| |
= note: expected struct `Thunk<_>` = note: expected struct `Thunk<_>`
found unit type `()` found unit type `()`
error: aborting due to 2 previous errors error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`. Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.