Bubble up opaque <eq> opaque operations instead of picking an order
This commit is contained in:
parent
ad4dd759d8
commit
930affa39d
@ -328,19 +328,26 @@ fn check_opaque_type_well_formed<'tcx>(
|
||||
|
||||
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
|
||||
// the bounds that the function supplies.
|
||||
let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args);
|
||||
ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty)
|
||||
.map_err(|err| {
|
||||
infcx
|
||||
.err_ctxt()
|
||||
.report_mismatched_types(
|
||||
&ObligationCause::misc(definition_span, def_id),
|
||||
opaque_ty,
|
||||
definition_ty,
|
||||
err,
|
||||
)
|
||||
.emit()
|
||||
})?;
|
||||
let mut obligations = vec![];
|
||||
infcx
|
||||
.insert_hidden_type(
|
||||
OpaqueTypeKey { def_id, args: identity_args },
|
||||
&ObligationCause::misc(definition_span, def_id),
|
||||
param_env,
|
||||
definition_ty,
|
||||
true,
|
||||
&mut obligations,
|
||||
)
|
||||
.unwrap();
|
||||
infcx.add_item_bounds_for_hidden_type(
|
||||
def_id.to_def_id(),
|
||||
identity_args,
|
||||
ObligationCause::misc(definition_span, def_id),
|
||||
param_env,
|
||||
definition_ty,
|
||||
&mut obligations,
|
||||
);
|
||||
ocx.register_obligations(obligations);
|
||||
|
||||
// Require the hidden type to be well-formed with only the generics of the opaque type.
|
||||
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
|
||||
|
@ -145,7 +145,25 @@ pub fn handle_opaque_type(
|
||||
return None;
|
||||
}
|
||||
}
|
||||
DefiningAnchor::Bubble => {}
|
||||
DefiningAnchor::Bubble => {
|
||||
if let ty::Alias(ty::Opaque, _) = b.kind() {
|
||||
// In bubble mode we don't know which of the two opaque types is supposed to have the other
|
||||
// as a hidden type (both, none or either one of them could be in its defining scope).
|
||||
let predicate = ty::PredicateKind::AliasRelate(
|
||||
a.into(),
|
||||
b.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
);
|
||||
let obligation = traits::Obligation::new(
|
||||
self.tcx,
|
||||
cause.clone(),
|
||||
param_env,
|
||||
predicate,
|
||||
);
|
||||
let obligations = vec![obligation];
|
||||
return Some(Ok(InferOk { value: (), obligations }));
|
||||
}
|
||||
}
|
||||
DefiningAnchor::Error => return None,
|
||||
};
|
||||
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
|
||||
|
@ -6,6 +6,7 @@
|
||||
use rustc_infer::traits::ProjectionCacheKey;
|
||||
use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::traits::DefiningAnchor;
|
||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
@ -623,9 +624,27 @@ fn process_obligation(
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
|
||||
ty::PredicateKind::AliasRelate(..) => {
|
||||
bug!("AliasRelate is only used for new solver")
|
||||
ty::PredicateKind::AliasRelate(..)
|
||||
if matches!(self.selcx.infcx.defining_use_anchor, DefiningAnchor::Bubble) =>
|
||||
{
|
||||
ProcessResult::Unchanged
|
||||
}
|
||||
ty::PredicateKind::AliasRelate(a, b, relate) => match relate {
|
||||
ty::AliasRelationDirection::Equate => match self
|
||||
.selcx
|
||||
.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, a, b)
|
||||
{
|
||||
Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
|
||||
Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError(
|
||||
SelectionError::Unimplemented,
|
||||
)),
|
||||
},
|
||||
ty::AliasRelationDirection::Subtype => {
|
||||
bug!("AliasRelate with subtyping is only used for new solver")
|
||||
}
|
||||
},
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
||||
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
|
||||
DefineOpaqueTypes::No,
|
||||
|
@ -37,6 +37,7 @@
|
||||
use rustc_infer::traits::TraitObligation;
|
||||
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::traits::DefiningAnchor;
|
||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::relate::TypeRelation;
|
||||
@ -960,9 +961,27 @@ fn evaluate_predicate_recursively<'o>(
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::AliasRelate(..) => {
|
||||
bug!("AliasRelate is only used for new solver")
|
||||
ty::PredicateKind::AliasRelate(..)
|
||||
if matches!(self.infcx.defining_use_anchor, DefiningAnchor::Bubble) =>
|
||||
{
|
||||
Ok(EvaluatedToAmbig)
|
||||
}
|
||||
ty::PredicateKind::AliasRelate(a, b, relate) => match relate {
|
||||
ty::AliasRelationDirection::Equate => match self
|
||||
.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, a, b)
|
||||
{
|
||||
Ok(inf_ok) => self.evaluate_predicates_recursively(
|
||||
previous_stack,
|
||||
inf_ok.into_obligations(),
|
||||
),
|
||||
Err(_) => Ok(EvaluatedToErr),
|
||||
},
|
||||
ty::AliasRelationDirection::Subtype => {
|
||||
bug!("AliasRelate subtyping is only used for new solver")
|
||||
}
|
||||
},
|
||||
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
||||
match self.infcx.at(&obligation.cause, obligation.param_env).eq(
|
||||
|
@ -1,6 +1,7 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
// edition:2021
|
||||
// check-pass
|
||||
//[rpit] check-pass
|
||||
// revisions: tait rpit
|
||||
|
||||
struct Pending {}
|
||||
|
||||
@ -12,15 +13,23 @@ impl AsyncRead for i32 {}
|
||||
|
||||
type PendingReader<'a> = impl AsyncRead + 'a;
|
||||
|
||||
type OpeningReadFuture<'a> =
|
||||
impl std::future::Future<Output = Result<PendingReader<'a>, CantOpen>>;
|
||||
#[cfg(tait)]
|
||||
type OpeningReadFuture<'a> = impl std::future::Future<Output = Result<PendingReader<'a>, CantOpen>>;
|
||||
|
||||
impl Pending {
|
||||
async fn read(&mut self) -> Result<impl AsyncRead + '_, CantOpen> {
|
||||
Ok(42)
|
||||
}
|
||||
|
||||
#[cfg(tait)]
|
||||
fn read_fut(&mut self) -> OpeningReadFuture<'_> {
|
||||
self.read() //[tait]~ ERROR: cannot satisfy `impl AsyncRead + 'a == PendingReader<'a>`
|
||||
}
|
||||
|
||||
#[cfg(rpit)]
|
||||
fn read_fut(
|
||||
&mut self,
|
||||
) -> impl std::future::Future<Output = Result<PendingReader<'_>, CantOpen>> {
|
||||
self.read()
|
||||
}
|
||||
}
|
||||
|
9
tests/ui/impl-trait/async_scope_creep.tait.stderr
Normal file
9
tests/ui/impl-trait/async_scope_creep.tait.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
error[E0284]: type annotations needed: cannot satisfy `impl AsyncRead + 'a == PendingReader<'a>`
|
||||
--> $DIR/async_scope_creep.rs:26:9
|
||||
|
|
||||
LL | self.read()
|
||||
| ^^^^^^^^^^^ cannot satisfy `impl AsyncRead + 'a == PendingReader<'a>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
@ -0,0 +1,25 @@
|
||||
//! This tries to prove the APIT's bounds in a canonical query,
|
||||
//! which doesn't know anything about the defining scope of either
|
||||
//! opaque type and thus makes a random choice as to which opaque type
|
||||
//! becomes the hidden type of the other. When we leave the canonical
|
||||
//! query, we attempt to actually check the defining anchor, but now we
|
||||
//! have a situation where the RPIT gets constrained outside its anchor.
|
||||
|
||||
// revisions: current next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
// check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type Opaque = impl Sized;
|
||||
|
||||
fn get_rpit() -> impl Clone {}
|
||||
|
||||
fn query(_: impl FnOnce() -> Opaque) {}
|
||||
|
||||
fn test() -> Opaque {
|
||||
query(get_rpit);
|
||||
get_rpit()
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user