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:
commit
25d47fe388
@ -878,9 +878,9 @@ pub fn subtype_predicate(
|
||||
|
||||
self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| {
|
||||
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 {
|
||||
Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::No, b, a))
|
||||
Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -2,58 +2,23 @@
|
||||
//! 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.
|
||||
|
||||
use std::iter;
|
||||
//@ check-pass
|
||||
|
||||
mod either {
|
||||
pub enum Either<L, R> {
|
||||
Left(L),
|
||||
Right(R),
|
||||
}
|
||||
|
||||
impl<L: Iterator, R: Iterator<Item = L::Item>> Iterator for Either<L, R> {
|
||||
type Item = L::Item;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
pub use self::Either::{Left, Right};
|
||||
}
|
||||
|
||||
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])
|
||||
fn foo() -> impl Default + Copy {
|
||||
if false {
|
||||
let x = Default::default();
|
||||
// add `Subtype(?x, ?y)` obligation
|
||||
let y = x;
|
||||
|
||||
// Make a tuple `(?x, ?y)` and equate it with `(impl Default, u32)`.
|
||||
// For us to try and prove a `Subtype(impl Default, u32)` obligation,
|
||||
// we have to instantiate both `?x` and `?y` without any
|
||||
// `select_where_possible` calls inbetween.
|
||||
let mut tup = &mut (x, y);
|
||||
let assign_tup = &mut (foo(), 1u32);
|
||||
tup = assign_tup;
|
||||
}
|
||||
1u32
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -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`.
|
@ -7,9 +7,10 @@
|
||||
type Tait = impl FnOnce() -> ();
|
||||
|
||||
fn reify_as_tait() -> Thunk<Tait> {
|
||||
//~^ ERROR: expected a `FnOnce()` closure, found `()`
|
||||
Thunk::new(|cont| cont)
|
||||
//~^ ERROR: mismatched types
|
||||
//~| ERROR: mismatched types
|
||||
//~| ERROR: expected a `FnOnce()` closure, found `()`
|
||||
}
|
||||
|
||||
struct Thunk<F>(F);
|
||||
|
@ -1,26 +1,31 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/lazy_subtyping_of_opaques.rs:10:23
|
||||
error[E0277]: expected a `FnOnce()` closure, found `()`
|
||||
--> $DIR/lazy_subtyping_of_opaques.rs:11:23
|
||||
|
|
||||
LL | type Tait = impl FnOnce() -> ();
|
||||
| ------------------- the found opaque type
|
||||
...
|
||||
LL | Thunk::new(|cont| cont)
|
||||
| ^^^^ expected `()`, found opaque type
|
||||
| ^^^^ expected an `FnOnce()` closure, found `()`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found opaque type `Tait`
|
||||
= 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:10:5
|
||||
error[E0277]: expected a `FnOnce()` closure, found `()`
|
||||
--> $DIR/lazy_subtyping_of_opaques.rs:9:23
|
||||
|
|
||||
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)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `Thunk<_>`, found `()`
|
||||
|
|
||||
= note: expected struct `Thunk<_>`
|
||||
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`.
|
||||
|
Loading…
Reference in New Issue
Block a user