Pull out logic from #111131, plus some new logic in EvalCtxt::normalize_opaque_type
Co-authored-by: lcnr <rust@lcnr.de>
This commit is contained in:
parent
7664dfe433
commit
4d80b8090c
13 changed files with 122 additions and 43 deletions
|
@ -113,10 +113,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
bug!()
|
||||
}
|
||||
|
||||
(_, ty::Alias(AliasKind::Projection | AliasKind::Inherent, _))
|
||||
| (ty::Alias(AliasKind::Projection | AliasKind::Inherent, _), _)
|
||||
if self.tcx.trait_solver_next() =>
|
||||
{
|
||||
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.tcx.trait_solver_next() => {
|
||||
relation.register_type_relate_obligation(a, b);
|
||||
Ok(a)
|
||||
}
|
||||
|
|
|
@ -104,7 +104,8 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
|
|||
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
|
||||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
|
||||
&& def_id.is_local() =>
|
||||
&& def_id.is_local()
|
||||
&& !self.tcx().trait_solver_next() =>
|
||||
{
|
||||
self.fields.obligations.extend(
|
||||
infcx
|
||||
|
|
|
@ -108,9 +108,12 @@ where
|
|||
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
|
||||
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
|
||||
) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b),
|
||||
|
||||
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
|
||||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if this.define_opaque_types() == DefineOpaqueTypes::Yes && def_id.is_local() =>
|
||||
if this.define_opaque_types() == DefineOpaqueTypes::Yes
|
||||
&& def_id.is_local()
|
||||
&& !this.tcx().trait_solver_next() =>
|
||||
{
|
||||
this.register_obligations(
|
||||
infcx
|
||||
|
|
|
@ -491,16 +491,22 @@ where
|
|||
(
|
||||
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
|
||||
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
|
||||
) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b).or_else(|err| {
|
||||
self.tcx().sess.delay_span_bug(
|
||||
self.delegate.span(),
|
||||
"failure to relate an opaque to itself should result in an error later on",
|
||||
);
|
||||
if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
|
||||
}),
|
||||
) if a_def_id == b_def_id || infcx.tcx.trait_solver_next() => {
|
||||
infcx.super_combine_tys(self, a, b).or_else(|err| {
|
||||
// This behavior is only there for the old solver, the new solver
|
||||
// shouldn't ever fail. Instead, it unconditionally emits an
|
||||
// alias-relate goal.
|
||||
assert!(!self.tcx().trait_solver_next());
|
||||
self.tcx().sess.delay_span_bug(
|
||||
self.delegate.span(),
|
||||
"failure to relate an opaque to itself should result in an error later on",
|
||||
);
|
||||
if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
|
||||
})
|
||||
}
|
||||
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
|
||||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if def_id.is_local() =>
|
||||
if def_id.is_local() && !self.tcx().trait_solver_next() =>
|
||||
{
|
||||
self.relate_opaques(a, b)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
|||
use super::{DefineOpaqueTypes, InferResult};
|
||||
use crate::errors::OpaqueHiddenTypeDiag;
|
||||
use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
|
||||
use crate::traits;
|
||||
use crate::traits::{self, PredicateObligation};
|
||||
use hir::def_id::{DefId, LocalDefId};
|
||||
use hir::OpaqueTyOrigin;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
|
@ -48,9 +48,15 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
span: Span,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> InferOk<'tcx, T> {
|
||||
// We handle opaque types differently in the new solver.
|
||||
if self.tcx.trait_solver_next() {
|
||||
return InferOk { value, obligations: vec![] };
|
||||
}
|
||||
|
||||
if !value.has_opaque_types() {
|
||||
return InferOk { value, obligations: vec![] };
|
||||
}
|
||||
|
||||
let mut obligations = vec![];
|
||||
let replace_opaque_type = |def_id: DefId| {
|
||||
def_id.as_local().is_some_and(|def_id| self.opaque_type_origin(def_id).is_some())
|
||||
|
@ -521,9 +527,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
origin: hir::OpaqueTyOrigin,
|
||||
a_is_expected: bool,
|
||||
) -> InferResult<'tcx, ()> {
|
||||
let tcx = self.tcx;
|
||||
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
|
||||
|
||||
// Ideally, we'd get the span where *this specific `ty` came
|
||||
// from*, but right now we just use the span from the overall
|
||||
// value being folded. In simple cases like `-> impl Foo`,
|
||||
|
@ -531,7 +534,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
// Foo, impl Bar)`.
|
||||
let span = cause.span;
|
||||
let prev = self.inner.borrow_mut().opaque_types().register(
|
||||
OpaqueTypeKey { def_id, substs },
|
||||
opaque_type_key,
|
||||
OpaqueHiddenType { ty: hidden_ty, span },
|
||||
origin,
|
||||
);
|
||||
|
@ -543,6 +546,26 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
self.add_item_bounds_for_hidden_type(
|
||||
opaque_type_key,
|
||||
cause,
|
||||
param_env,
|
||||
hidden_ty,
|
||||
&mut obligations,
|
||||
);
|
||||
|
||||
Ok(InferOk { value: (), obligations })
|
||||
}
|
||||
|
||||
pub fn add_item_bounds_for_hidden_type(
|
||||
&self,
|
||||
OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
let item_bounds = tcx.explicit_item_bounds(def_id);
|
||||
|
||||
for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
|
||||
|
@ -555,14 +578,15 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
// FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
|
||||
ty::Alias(ty::Projection, projection_ty)
|
||||
if !projection_ty.has_escaping_bound_vars()
|
||||
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id) =>
|
||||
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id)
|
||||
&& !tcx.trait_solver_next() =>
|
||||
{
|
||||
self.infer_projection(
|
||||
param_env,
|
||||
projection_ty,
|
||||
cause.clone(),
|
||||
0,
|
||||
&mut obligations,
|
||||
obligations,
|
||||
)
|
||||
}
|
||||
// Replace all other mentions of the same opaque type with the hidden type,
|
||||
|
@ -588,10 +612,10 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
predicate.kind().skip_binder()
|
||||
{
|
||||
if projection.term.references_error() {
|
||||
// No point on adding these obligations since there's a type error involved.
|
||||
return Ok(InferOk { value: (), obligations: vec![] });
|
||||
// No point on adding any obligations since there's a type error involved.
|
||||
obligations.clear();
|
||||
return;
|
||||
}
|
||||
trace!("{:#?}", projection.term);
|
||||
}
|
||||
// Require that the predicate holds for the concrete type.
|
||||
debug!(?predicate);
|
||||
|
@ -602,7 +626,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
predicate,
|
||||
));
|
||||
}
|
||||
Ok(InferOk { value: (), obligations })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,8 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
|||
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
|
||||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
|
||||
&& def_id.is_local() =>
|
||||
&& def_id.is_local()
|
||||
&& !self.tcx().trait_solver_next() =>
|
||||
{
|
||||
self.fields.obligations.extend(
|
||||
infcx
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue