Auto merge of #118725 - lcnr:normalizes-to-projection-split-3, r=BoxyUwU
split `NormalizesTo` out of `Projection` 3 third attempt at #112658. Rebasing #116262 is very annoying, so I am doing it again from scratch. We should now be able to merge it without regressing anything as we handle occurs check failures involving aliases correctly since #117088. see https://hackmd.io/ktEL8knTSYmtdfrMMnA-Hg fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/1 r? `@compiler-errors`
This commit is contained in:
commit
21982a4383
39 changed files with 310 additions and 189 deletions
|
@ -657,19 +657,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
|
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
|
||||||
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
|
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
|
||||||
| ty::PredicateKind::ObjectSafe(..)
|
| ty::PredicateKind::ObjectSafe(..)
|
||||||
|
| ty::PredicateKind::NormalizesTo(..)
|
||||||
| ty::PredicateKind::AliasRelate(..)
|
| ty::PredicateKind::AliasRelate(..)
|
||||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
||||||
| ty::PredicateKind::ConstEquate(..)
|
| ty::PredicateKind::ConstEquate(..)
|
||||||
// N.B., this predicate is created by breaking down a
|
| ty::PredicateKind::Ambiguous => None,
|
||||||
// `ClosureType: FnFoo()` predicate, where
|
|
||||||
// `ClosureType` represents some `Closure`. It can't
|
|
||||||
// possibly be referring to the current closure,
|
|
||||||
// because we haven't produced the `Closure` for
|
|
||||||
// this closure yet; this is exactly why the other
|
|
||||||
// code is looking for a self type of an unresolved
|
|
||||||
// inference variable.
|
|
||||||
| ty::PredicateKind::Ambiguous
|
|
||||||
=> None,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
|
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
|
||||||
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
|
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
|
||||||
|
use rustc_middle::ty::{AliasRelationDirection, TyVar};
|
||||||
use rustc_middle::ty::{IntType, UintType};
|
use rustc_middle::ty::{IntType, UintType};
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
|
|
||||||
|
@ -459,7 +460,12 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
||||||
ambient_variance,
|
ambient_variance,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
|
// Constrain `b_vid` to the generalized type `b_ty`.
|
||||||
|
if let &ty::Infer(TyVar(b_ty_vid)) = b_ty.kind() {
|
||||||
|
self.infcx.inner.borrow_mut().type_variables().equate(b_vid, b_ty_vid);
|
||||||
|
} else {
|
||||||
|
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
|
||||||
|
}
|
||||||
|
|
||||||
if needs_wf {
|
if needs_wf {
|
||||||
self.obligations.push(Obligation::new(
|
self.obligations.push(Obligation::new(
|
||||||
|
@ -484,31 +490,46 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
||||||
// cyclic type. We instead delay the unification in case
|
// cyclic type. We instead delay the unification in case
|
||||||
// the alias can be normalized to something which does not
|
// the alias can be normalized to something which does not
|
||||||
// mention `?0`.
|
// mention `?0`.
|
||||||
|
if self.infcx.next_trait_solver() {
|
||||||
// FIXME(-Ztrait-solver=next): replace this with `AliasRelate`
|
let (lhs, rhs, direction) = match ambient_variance {
|
||||||
let &ty::Alias(kind, data) = a_ty.kind() else {
|
ty::Variance::Invariant => {
|
||||||
bug!("generalization should only result in infer vars for aliases");
|
(a_ty.into(), b_ty.into(), AliasRelationDirection::Equate)
|
||||||
};
|
|
||||||
if !self.infcx.next_trait_solver() {
|
|
||||||
// The old solver only accepts projection predicates for associated types.
|
|
||||||
match kind {
|
|
||||||
ty::AliasKind::Projection => {}
|
|
||||||
ty::AliasKind::Inherent | ty::AliasKind::Weak | ty::AliasKind::Opaque => {
|
|
||||||
return Err(TypeError::CyclicTy(a_ty));
|
|
||||||
}
|
}
|
||||||
|
ty::Variance::Covariant => {
|
||||||
|
(a_ty.into(), b_ty.into(), AliasRelationDirection::Subtype)
|
||||||
|
}
|
||||||
|
ty::Variance::Contravariant => {
|
||||||
|
(b_ty.into(), a_ty.into(), AliasRelationDirection::Subtype)
|
||||||
|
}
|
||||||
|
ty::Variance::Bivariant => unreachable!("bivariant generalization"),
|
||||||
|
};
|
||||||
|
self.obligations.push(Obligation::new(
|
||||||
|
self.tcx(),
|
||||||
|
self.trace.cause.clone(),
|
||||||
|
self.param_env,
|
||||||
|
ty::PredicateKind::AliasRelate(lhs, rhs, direction),
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
match a_ty.kind() {
|
||||||
|
&ty::Alias(ty::AliasKind::Projection, data) => {
|
||||||
|
// FIXME: This does not handle subtyping correctly, we could
|
||||||
|
// instead create a new inference variable for `a_ty`, emitting
|
||||||
|
// `Projection(a_ty, a_infer)` and `a_infer <: b_ty`.
|
||||||
|
self.obligations.push(Obligation::new(
|
||||||
|
self.tcx(),
|
||||||
|
self.trace.cause.clone(),
|
||||||
|
self.param_env,
|
||||||
|
ty::ProjectionPredicate { projection_ty: data, term: b_ty.into() },
|
||||||
|
))
|
||||||
|
}
|
||||||
|
// The old solver only accepts projection predicates for associated types.
|
||||||
|
ty::Alias(
|
||||||
|
ty::AliasKind::Inherent | ty::AliasKind::Weak | ty::AliasKind::Opaque,
|
||||||
|
_,
|
||||||
|
) => return Err(TypeError::CyclicTy(a_ty)),
|
||||||
|
_ => bug!("generalizated `{a_ty:?} to infer, not an alias"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This does not handle subtyping correctly, we should switch to
|
|
||||||
// alias-relate in the new solver and could instead create a new inference
|
|
||||||
// variable for `a_ty`, emitting `Projection(a_ty, a_infer)` and
|
|
||||||
// `a_infer <: b_ty`.
|
|
||||||
self.obligations.push(Obligation::new(
|
|
||||||
self.tcx(),
|
|
||||||
self.trace.cause.clone(),
|
|
||||||
self.param_env,
|
|
||||||
ty::ProjectionPredicate { projection_ty: data, term: b_ty.into() },
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
match ambient_variance {
|
match ambient_variance {
|
||||||
ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
|
ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
|
||||||
|
@ -519,9 +540,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
||||||
a_ty,
|
a_ty,
|
||||||
b_ty,
|
b_ty,
|
||||||
),
|
),
|
||||||
ty::Variance::Bivariant => {
|
ty::Variance::Bivariant => unreachable!("bivariant generalization"),
|
||||||
unreachable!("no code should be generalizing bivariantly (currently)")
|
|
||||||
}
|
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,12 +229,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||||
/// Precondition: `vid` must not have been previously instantiated.
|
/// Precondition: `vid` must not have been previously instantiated.
|
||||||
pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) {
|
pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) {
|
||||||
let vid = self.root_var(vid);
|
let vid = self.root_var(vid);
|
||||||
|
debug_assert!(!ty.is_ty_var(), "instantiating ty var with var: {vid:?} {ty:?}");
|
||||||
debug_assert!(self.probe(vid).is_unknown());
|
debug_assert!(self.probe(vid).is_unknown());
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
self.eq_relations().probe_value(vid).is_unknown(),
|
self.eq_relations().probe_value(vid).is_unknown(),
|
||||||
"instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}",
|
"instantiating type variable `{vid:?}` twice: new-value = {ty:?}, old-value={:?}",
|
||||||
vid,
|
|
||||||
ty,
|
|
||||||
self.eq_relations().probe_value(vid)
|
self.eq_relations().probe_value(vid)
|
||||||
);
|
);
|
||||||
self.eq_relations().union_value(vid, TypeVariableValue::Known { value: ty });
|
self.eq_relations().union_value(vid, TypeVariableValue::Known { value: ty });
|
||||||
|
|
|
@ -261,9 +261,14 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
||||||
fn elaborate(&mut self, elaboratable: &O) {
|
fn elaborate(&mut self, elaboratable: &O) {
|
||||||
let tcx = self.visited.tcx;
|
let tcx = self.visited.tcx;
|
||||||
|
|
||||||
let bound_predicate = elaboratable.predicate().kind();
|
// We only elaborate clauses.
|
||||||
match bound_predicate.skip_binder() {
|
let Some(clause) = elaboratable.predicate().as_clause() else {
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let bound_clause = clause.kind();
|
||||||
|
match bound_clause.skip_binder() {
|
||||||
|
ty::ClauseKind::Trait(data) => {
|
||||||
// Negative trait bounds do not imply any supertrait bounds
|
// Negative trait bounds do not imply any supertrait bounds
|
||||||
if data.polarity == ty::ImplPolarity::Negative {
|
if data.polarity == ty::ImplPolarity::Negative {
|
||||||
return;
|
return;
|
||||||
|
@ -280,49 +285,16 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
||||||
let obligations =
|
let obligations =
|
||||||
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
|
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
|
||||||
elaboratable.child_with_derived_cause(
|
elaboratable.child_with_derived_cause(
|
||||||
clause.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
|
clause.subst_supertrait(tcx, &bound_clause.rebind(data.trait_ref)),
|
||||||
span,
|
span,
|
||||||
bound_predicate.rebind(data),
|
bound_clause.rebind(data),
|
||||||
index,
|
index,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
debug!(?data, ?obligations, "super_predicates");
|
debug!(?data, ?obligations, "super_predicates");
|
||||||
self.extend_deduped(obligations);
|
self.extend_deduped(obligations);
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) => {
|
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
|
||||||
// Currently, we do not elaborate WF predicates,
|
|
||||||
// although we easily could.
|
|
||||||
}
|
|
||||||
ty::PredicateKind::ObjectSafe(..) => {
|
|
||||||
// Currently, we do not elaborate object-safe
|
|
||||||
// predicates.
|
|
||||||
}
|
|
||||||
ty::PredicateKind::Subtype(..) => {
|
|
||||||
// Currently, we do not "elaborate" predicates like `X <: Y`,
|
|
||||||
// though conceivably we might.
|
|
||||||
}
|
|
||||||
ty::PredicateKind::Coerce(..) => {
|
|
||||||
// Currently, we do not "elaborate" predicates like `X -> Y`,
|
|
||||||
// though conceivably we might.
|
|
||||||
}
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => {
|
|
||||||
// Nothing to elaborate in a projection predicate.
|
|
||||||
}
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
|
|
||||||
// Currently, we do not elaborate const-evaluatable
|
|
||||||
// predicates.
|
|
||||||
}
|
|
||||||
ty::PredicateKind::ConstEquate(..) => {
|
|
||||||
// Currently, we do not elaborate const-equate
|
|
||||||
// predicates.
|
|
||||||
}
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {
|
|
||||||
// Nothing to elaborate from `'a: 'b`.
|
|
||||||
}
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
|
|
||||||
ty_max,
|
|
||||||
r_min,
|
|
||||||
))) => {
|
|
||||||
// We know that `T: 'a` for some type `T`. We can
|
// We know that `T: 'a` for some type `T`. We can
|
||||||
// often elaborate this. For example, if we know that
|
// often elaborate this. For example, if we know that
|
||||||
// `[U]: 'a`, that implies that `U: 'a`. Similarly, if
|
// `[U]: 'a`, that implies that `U: 'a`. Similarly, if
|
||||||
|
@ -385,15 +357,25 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map(|clause| {
|
.map(|clause| {
|
||||||
elaboratable.child(bound_predicate.rebind(clause).to_predicate(tcx))
|
elaboratable.child(bound_clause.rebind(clause).to_predicate(tcx))
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Ambiguous => {}
|
ty::ClauseKind::RegionOutlives(..) => {
|
||||||
ty::PredicateKind::AliasRelate(..) => {
|
// Nothing to elaborate from `'a: 'b`.
|
||||||
// No
|
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => {
|
ty::ClauseKind::WellFormed(..) => {
|
||||||
|
// Currently, we do not elaborate WF predicates,
|
||||||
|
// although we easily could.
|
||||||
|
}
|
||||||
|
ty::ClauseKind::Projection(..) => {
|
||||||
|
// Nothing to elaborate in a projection predicate.
|
||||||
|
}
|
||||||
|
ty::ClauseKind::ConstEvaluatable(..) => {
|
||||||
|
// Currently, we do not elaborate const-evaluatable
|
||||||
|
// predicates.
|
||||||
|
}
|
||||||
|
ty::ClauseKind::ConstArgHasType(..) => {
|
||||||
// Nothing to elaborate
|
// Nothing to elaborate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||||
type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>;
|
type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>;
|
||||||
type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>;
|
type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>;
|
||||||
type ProjectionPredicate = ty::ProjectionPredicate<'tcx>;
|
type ProjectionPredicate = ty::ProjectionPredicate<'tcx>;
|
||||||
|
type NormalizesTo = ty::NormalizesTo<'tcx>;
|
||||||
type SubtypePredicate = ty::SubtypePredicate<'tcx>;
|
type SubtypePredicate = ty::SubtypePredicate<'tcx>;
|
||||||
type CoercePredicate = ty::CoercePredicate<'tcx>;
|
type CoercePredicate = ty::CoercePredicate<'tcx>;
|
||||||
type ClosureKind = ty::ClosureKind;
|
type ClosureKind = ty::ClosureKind;
|
||||||
|
|
|
@ -272,6 +272,10 @@ impl FlagComputation {
|
||||||
self.add_const(found);
|
self.add_const(found);
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Ambiguous => {}
|
ty::PredicateKind::Ambiguous => {}
|
||||||
|
ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => {
|
||||||
|
self.add_alias_ty(alias);
|
||||||
|
self.add_term(term);
|
||||||
|
}
|
||||||
ty::PredicateKind::AliasRelate(t1, t2, _) => {
|
ty::PredicateKind::AliasRelate(t1, t2, _) => {
|
||||||
self.add_term(t1);
|
self.add_term(t1);
|
||||||
self.add_term(t2);
|
self.add_term(t2);
|
||||||
|
|
|
@ -553,6 +553,10 @@ impl<'tcx> Predicate<'tcx> {
|
||||||
pub fn allow_normalization(self) -> bool {
|
pub fn allow_normalization(self) -> bool {
|
||||||
match self.kind().skip_binder() {
|
match self.kind().skip_binder() {
|
||||||
PredicateKind::Clause(ClauseKind::WellFormed(_)) => false,
|
PredicateKind::Clause(ClauseKind::WellFormed(_)) => false,
|
||||||
|
// `NormalizesTo` is only used in the new solver, so this shouldn't
|
||||||
|
// matter. Normalizing `term` would be 'wrong' however, as it changes whether
|
||||||
|
// `normalizes-to(<T as Trait>::Assoc, <T as Trait>::Assoc)` holds.
|
||||||
|
PredicateKind::NormalizesTo(..) => false,
|
||||||
PredicateKind::Clause(ClauseKind::Trait(_))
|
PredicateKind::Clause(ClauseKind::Trait(_))
|
||||||
| PredicateKind::Clause(ClauseKind::RegionOutlives(_))
|
| PredicateKind::Clause(ClauseKind::RegionOutlives(_))
|
||||||
| PredicateKind::Clause(ClauseKind::TypeOutlives(_))
|
| PredicateKind::Clause(ClauseKind::TypeOutlives(_))
|
||||||
|
@ -1093,6 +1097,33 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be
|
||||||
|
/// proven by actually normalizing `alias`.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||||
|
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||||
|
pub struct NormalizesTo<'tcx> {
|
||||||
|
pub alias: AliasTy<'tcx>,
|
||||||
|
pub term: Term<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> NormalizesTo<'tcx> {
|
||||||
|
pub fn self_ty(self) -> Ty<'tcx> {
|
||||||
|
self.alias.self_ty()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> {
|
||||||
|
Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
|
||||||
|
self.alias.trait_def_id(tcx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn def_id(self) -> DefId {
|
||||||
|
self.alias.def_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ToPolyTraitRef<'tcx> {
|
pub trait ToPolyTraitRef<'tcx> {
|
||||||
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
|
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
|
||||||
}
|
}
|
||||||
|
@ -1274,6 +1305,12 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> {
|
||||||
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||||
|
PredicateKind::NormalizesTo(self).to_predicate(tcx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Predicate<'tcx> {
|
impl<'tcx> Predicate<'tcx> {
|
||||||
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
|
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
|
||||||
let predicate = self.kind();
|
let predicate = self.kind();
|
||||||
|
@ -1281,6 +1318,7 @@ impl<'tcx> Predicate<'tcx> {
|
||||||
PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
|
PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
|
||||||
PredicateKind::Clause(ClauseKind::Projection(..))
|
PredicateKind::Clause(ClauseKind::Projection(..))
|
||||||
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
|
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
|
||||||
|
| PredicateKind::NormalizesTo(..)
|
||||||
| PredicateKind::AliasRelate(..)
|
| PredicateKind::AliasRelate(..)
|
||||||
| PredicateKind::Subtype(..)
|
| PredicateKind::Subtype(..)
|
||||||
| PredicateKind::Coerce(..)
|
| PredicateKind::Coerce(..)
|
||||||
|
@ -1300,6 +1338,7 @@ impl<'tcx> Predicate<'tcx> {
|
||||||
PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
|
PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
|
||||||
PredicateKind::Clause(ClauseKind::Trait(..))
|
PredicateKind::Clause(ClauseKind::Trait(..))
|
||||||
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
|
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
|
||||||
|
| PredicateKind::NormalizesTo(..)
|
||||||
| PredicateKind::AliasRelate(..)
|
| PredicateKind::AliasRelate(..)
|
||||||
| PredicateKind::Subtype(..)
|
| PredicateKind::Subtype(..)
|
||||||
| PredicateKind::Coerce(..)
|
| PredicateKind::Coerce(..)
|
||||||
|
|
|
@ -2814,6 +2814,7 @@ define_print! {
|
||||||
p!("the constant `", print(c1), "` equals `", print(c2), "`")
|
p!("the constant `", print(c1), "` equals `", print(c2), "`")
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Ambiguous => p!("ambiguous"),
|
ty::PredicateKind::Ambiguous => p!("ambiguous"),
|
||||||
|
ty::PredicateKind::NormalizesTo(data) => p!(print(data)),
|
||||||
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
|
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2945,6 +2946,12 @@ define_print_and_forward_display! {
|
||||||
p!(print(self.term))
|
p!(print(self.term))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ty::NormalizesTo<'tcx> {
|
||||||
|
p!(print(self.alias), " normalizes-to ");
|
||||||
|
cx.reset_type_limit();
|
||||||
|
p!(print(self.term))
|
||||||
|
}
|
||||||
|
|
||||||
ty::Term<'tcx> {
|
ty::Term<'tcx> {
|
||||||
match self.unpack() {
|
match self.unpack() {
|
||||||
ty::TermKind::Ty(ty) => p!(print(ty)),
|
ty::TermKind::Ty(ty) => p!(print(ty)),
|
||||||
|
|
|
@ -173,6 +173,12 @@ impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> fmt::Debug for ty::NormalizesTo<'tcx> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
|
impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{:?}", self.kind())
|
write!(f, "{:?}", self.kind())
|
||||||
|
|
|
@ -601,6 +601,7 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
|
||||||
stable_mir::ty::PredicateKind::ConstEquate(a.stable(tables), b.stable(tables))
|
stable_mir::ty::PredicateKind::ConstEquate(a.stable(tables), b.stable(tables))
|
||||||
}
|
}
|
||||||
PredicateKind::Ambiguous => stable_mir::ty::PredicateKind::Ambiguous,
|
PredicateKind::Ambiguous => stable_mir::ty::PredicateKind::Ambiguous,
|
||||||
|
PredicateKind::NormalizesTo(_pred) => unimplemented!(),
|
||||||
PredicateKind::AliasRelate(a, b, alias_relation_direction) => {
|
PredicateKind::AliasRelate(a, b, alias_relation_direction) => {
|
||||||
stable_mir::ty::PredicateKind::AliasRelate(
|
stable_mir::ty::PredicateKind::AliasRelate(
|
||||||
a.unpack().stable(tables),
|
a.unpack().stable(tables),
|
||||||
|
|
|
@ -92,7 +92,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
self.add_goal(Goal::new(
|
self.add_goal(Goal::new(
|
||||||
self.tcx(),
|
self.tcx(),
|
||||||
param_env,
|
param_env,
|
||||||
ty::ProjectionPredicate { projection_ty: alias, term },
|
ty::NormalizesTo { alias, term },
|
||||||
));
|
));
|
||||||
self.try_evaluate_added_goals()?;
|
self.try_evaluate_added_goals()?;
|
||||||
Ok(Some(self.resolve_vars_if_possible(term)))
|
Ok(Some(self.resolve_vars_if_possible(term)))
|
||||||
|
@ -109,11 +109,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
opaque: ty::AliasTy<'tcx>,
|
opaque: ty::AliasTy<'tcx>,
|
||||||
term: ty::Term<'tcx>,
|
term: ty::Term<'tcx>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
self.add_goal(Goal::new(
|
self.add_goal(Goal::new(self.tcx(), param_env, ty::NormalizesTo { alias: opaque, term }));
|
||||||
self.tcx(),
|
|
||||||
param_env,
|
|
||||||
ty::ProjectionPredicate { projection_ty: opaque, term },
|
|
||||||
));
|
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -352,15 +352,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
num_steps: usize,
|
num_steps: usize,
|
||||||
) {
|
) {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else { return };
|
let &ty::Alias(_, alias) = goal.predicate.self_ty().kind() else { return };
|
||||||
|
|
||||||
candidates.extend(self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
|
candidates.extend(self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
|
||||||
if tcx.recursion_limit().value_within_limit(num_steps) {
|
if tcx.recursion_limit().value_within_limit(num_steps) {
|
||||||
let normalized_ty = ecx.next_ty_infer();
|
let normalized_ty = ecx.next_ty_infer();
|
||||||
let normalizes_to_goal = goal.with(
|
let normalizes_to_goal =
|
||||||
tcx,
|
goal.with(tcx, ty::NormalizesTo { alias, term: normalized_ty.into() });
|
||||||
ty::ProjectionPredicate { projection_ty, term: normalized_ty.into() },
|
|
||||||
);
|
|
||||||
ecx.add_goal(normalizes_to_goal);
|
ecx.add_goal(normalizes_to_goal);
|
||||||
if let Err(NoSolution) = ecx.try_evaluate_added_goals() {
|
if let Err(NoSolution) = ecx.try_evaluate_added_goals() {
|
||||||
debug!("self type normalization failed");
|
debug!("self type normalization failed");
|
||||||
|
|
|
@ -69,8 +69,8 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let value = value.fold_with(&mut canonicalizer);
|
let value = value.fold_with(&mut canonicalizer);
|
||||||
assert!(!value.has_infer());
|
assert!(!value.has_infer(), "unexpected infer in {value:?}");
|
||||||
assert!(!value.has_placeholders());
|
assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
|
||||||
|
|
||||||
let (max_universe, variables) = canonicalizer.finalize();
|
let (max_universe, variables) = canonicalizer.finalize();
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ pub(super) struct NestedGoals<'tcx> {
|
||||||
/// with a fresh inference variable when we evaluate this goal. That can result
|
/// with a fresh inference variable when we evaluate this goal. That can result
|
||||||
/// in a trait solver cycle. This would currently result in overflow but can be
|
/// in a trait solver cycle. This would currently result in overflow but can be
|
||||||
/// can be unsound with more powerful coinduction in the future.
|
/// can be unsound with more powerful coinduction in the future.
|
||||||
pub(super) normalizes_to_hack_goal: Option<Goal<'tcx, ty::ProjectionPredicate<'tcx>>>,
|
pub(super) normalizes_to_hack_goal: Option<Goal<'tcx, ty::NormalizesTo<'tcx>>>,
|
||||||
/// The rest of the goals which have not yet processed or remain ambiguous.
|
/// The rest of the goals which have not yet processed or remain ambiguous.
|
||||||
pub(super) goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
pub(super) goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
||||||
}
|
}
|
||||||
|
@ -423,6 +423,9 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||||
ty::PredicateKind::ConstEquate(_, _) => {
|
ty::PredicateKind::ConstEquate(_, _) => {
|
||||||
bug!("ConstEquate should not be emitted when `-Ztrait-solver=next` is active")
|
bug!("ConstEquate should not be emitted when `-Ztrait-solver=next` is active")
|
||||||
}
|
}
|
||||||
|
ty::PredicateKind::NormalizesTo(predicate) => {
|
||||||
|
self.compute_normalizes_to_goal(Goal { param_env, predicate })
|
||||||
|
}
|
||||||
ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self
|
ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self
|
||||||
.compute_alias_relate_goal(Goal {
|
.compute_alias_relate_goal(Goal {
|
||||||
param_env,
|
param_env,
|
||||||
|
@ -492,10 +495,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||||
let unconstrained_rhs = self.next_term_infer_of_kind(goal.predicate.term);
|
let unconstrained_rhs = self.next_term_infer_of_kind(goal.predicate.term);
|
||||||
let unconstrained_goal = goal.with(
|
let unconstrained_goal = goal.with(
|
||||||
tcx,
|
tcx,
|
||||||
ty::ProjectionPredicate {
|
ty::NormalizesTo { alias: goal.predicate.alias, term: unconstrained_rhs },
|
||||||
projection_ty: goal.predicate.projection_ty,
|
|
||||||
term: unconstrained_rhs,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let (_, certainty, instantiate_goals) = self.evaluate_goal(
|
let (_, certainty, instantiate_goals) = self.evaluate_goal(
|
||||||
|
@ -517,9 +517,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||||
// looking at the "has changed" return from evaluate_goal,
|
// looking at the "has changed" return from evaluate_goal,
|
||||||
// because we expect the `unconstrained_rhs` part of the predicate
|
// because we expect the `unconstrained_rhs` part of the predicate
|
||||||
// to have changed -- that means we actually normalized successfully!
|
// to have changed -- that means we actually normalized successfully!
|
||||||
if goal.predicate.projection_ty
|
if goal.predicate.alias != self.resolve_vars_if_possible(goal.predicate.alias) {
|
||||||
!= self.resolve_vars_if_possible(goal.predicate.projection_ty)
|
|
||||||
{
|
|
||||||
unchanged_certainty = None;
|
unchanged_certainty = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,9 +587,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
///
|
///
|
||||||
/// This is the case if the `term` is an inference variable in the innermost universe
|
/// This is the case if the `term` is an inference variable in the innermost universe
|
||||||
/// and does not occur in any other part of the predicate.
|
/// and does not occur in any other part of the predicate.
|
||||||
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
pub(super) fn term_is_fully_unconstrained(
|
pub(super) fn term_is_fully_unconstrained(
|
||||||
&self,
|
&self,
|
||||||
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
|
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let term_is_infer = match goal.predicate.term.unpack() {
|
let term_is_infer = match goal.predicate.term.unpack() {
|
||||||
ty::TermKind::Ty(ty) => {
|
ty::TermKind::Ty(ty) => {
|
||||||
|
@ -655,7 +654,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
let mut visitor = ContainsTerm { infcx: self.infcx, term: goal.predicate.term };
|
let mut visitor = ContainsTerm { infcx: self.infcx, term: goal.predicate.term };
|
||||||
|
|
||||||
term_is_infer
|
term_is_infer
|
||||||
&& goal.predicate.projection_ty.visit_with(&mut visitor).is_continue()
|
&& goal.predicate.alias.visit_with(&mut visitor).is_continue()
|
||||||
&& goal.param_env.visit_with(&mut visitor).is_continue()
|
&& goal.param_env.visit_with(&mut visitor).is_continue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,11 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
|
||||||
MismatchedProjectionTypes { err: TypeError::Mismatch },
|
MismatchedProjectionTypes { err: TypeError::Mismatch },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
ty::PredicateKind::NormalizesTo(..) => {
|
||||||
|
FulfillmentErrorCode::CodeProjectionError(
|
||||||
|
MismatchedProjectionTypes { err: TypeError::Mismatch },
|
||||||
|
)
|
||||||
|
}
|
||||||
ty::PredicateKind::AliasRelate(_, _, _) => {
|
ty::PredicateKind::AliasRelate(_, _, _) => {
|
||||||
FulfillmentErrorCode::CodeProjectionError(
|
FulfillmentErrorCode::CodeProjectionError(
|
||||||
MismatchedProjectionTypes { err: TypeError::Mismatch },
|
MismatchedProjectionTypes { err: TypeError::Mismatch },
|
||||||
|
|
|
@ -35,6 +35,7 @@ mod eval_ctxt;
|
||||||
mod fulfill;
|
mod fulfill;
|
||||||
pub mod inspect;
|
pub mod inspect;
|
||||||
mod normalize;
|
mod normalize;
|
||||||
|
mod normalizes_to;
|
||||||
mod project_goals;
|
mod project_goals;
|
||||||
mod search_graph;
|
mod search_graph;
|
||||||
mod trait_goals;
|
mod trait_goals;
|
||||||
|
@ -216,7 +217,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn set_normalizes_to_hack_goal(&mut self, goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>) {
|
fn set_normalizes_to_hack_goal(&mut self, goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) {
|
||||||
assert!(
|
assert!(
|
||||||
self.nested_goals.normalizes_to_hack_goal.is_none(),
|
self.nested_goals.normalizes_to_hack_goal.is_none(),
|
||||||
"attempted to set the projection eq hack goal when one already exists"
|
"attempted to set the projection eq hack goal when one already exists"
|
||||||
|
@ -310,17 +311,17 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty::Alias(kind, projection_ty) = *ty.kind() else {
|
let ty::Alias(kind, alias) = *ty.kind() else {
|
||||||
return Some(ty);
|
return Some(ty);
|
||||||
};
|
};
|
||||||
|
|
||||||
// We do no always define opaque types eagerly to allow non-defining uses in the defining scope.
|
// We do no always define opaque types eagerly to allow non-defining uses in the defining scope.
|
||||||
if let (DefineOpaqueTypes::No, ty::AliasKind::Opaque) = (define_opaque_types, kind) {
|
if let (DefineOpaqueTypes::No, ty::AliasKind::Opaque) = (define_opaque_types, kind) {
|
||||||
if let Some(def_id) = projection_ty.def_id.as_local() {
|
if let Some(def_id) = alias.def_id.as_local() {
|
||||||
if self
|
if self
|
||||||
.unify_existing_opaque_tys(
|
.unify_existing_opaque_tys(
|
||||||
param_env,
|
param_env,
|
||||||
OpaqueTypeKey { def_id, args: projection_ty.args },
|
OpaqueTypeKey { def_id, args: alias.args },
|
||||||
self.next_ty_infer(),
|
self.next_ty_infer(),
|
||||||
)
|
)
|
||||||
.is_empty()
|
.is_empty()
|
||||||
|
@ -335,7 +336,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
let normalizes_to_goal = Goal::new(
|
let normalizes_to_goal = Goal::new(
|
||||||
this.tcx(),
|
this.tcx(),
|
||||||
param_env,
|
param_env,
|
||||||
ty::ProjectionPredicate { projection_ty, term: normalized_ty.into() },
|
ty::NormalizesTo { alias, term: normalized_ty.into() },
|
||||||
);
|
);
|
||||||
this.add_goal(normalizes_to_goal);
|
this.add_goal(normalizes_to_goal);
|
||||||
this.try_evaluate_added_goals()?;
|
this.try_evaluate_added_goals()?;
|
||||||
|
|
|
@ -76,7 +76,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
|
||||||
tcx,
|
tcx,
|
||||||
self.at.cause.clone(),
|
self.at.cause.clone(),
|
||||||
self.at.param_env,
|
self.at.param_env,
|
||||||
ty::ProjectionPredicate { projection_ty: alias, term: new_infer_ty.into() },
|
ty::NormalizesTo { alias, term: new_infer_ty.into() },
|
||||||
);
|
);
|
||||||
|
|
||||||
// Do not emit an error if normalization is known to fail but instead
|
// Do not emit an error if normalization is known to fail but instead
|
||||||
|
@ -129,8 +129,8 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
|
||||||
tcx,
|
tcx,
|
||||||
self.at.cause.clone(),
|
self.at.cause.clone(),
|
||||||
self.at.param_env,
|
self.at.param_env,
|
||||||
ty::ProjectionPredicate {
|
ty::NormalizesTo {
|
||||||
projection_ty: AliasTy::new(tcx, uv.def, uv.args),
|
alias: AliasTy::new(tcx, uv.def, uv.args),
|
||||||
term: new_infer_ct.into(),
|
term: new_infer_ct.into(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,10 +12,10 @@ use super::EvalCtxt;
|
||||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
pub(super) fn normalize_inherent_associated_type(
|
pub(super) fn normalize_inherent_associated_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
|
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let inherent = goal.predicate.projection_ty;
|
let inherent = goal.predicate.alias;
|
||||||
let expected = goal.predicate.term.ty().expect("inherent consts are treated separately");
|
let expected = goal.predicate.term.ty().expect("inherent consts are treated separately");
|
||||||
|
|
||||||
let impl_def_id = tcx.parent(inherent.def_id);
|
let impl_def_id = tcx.parent(inherent.def_id);
|
|
@ -13,20 +13,20 @@ use rustc_middle::traits::solve::{
|
||||||
};
|
};
|
||||||
use rustc_middle::traits::BuiltinImplSource;
|
use rustc_middle::traits::BuiltinImplSource;
|
||||||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
||||||
use rustc_middle::ty::ProjectionPredicate;
|
use rustc_middle::ty::NormalizesTo;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
|
use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
|
||||||
use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP};
|
use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP};
|
||||||
|
|
||||||
mod inherent_projection;
|
mod inherent;
|
||||||
mod opaques;
|
mod opaques;
|
||||||
mod weak_types;
|
mod weak_types;
|
||||||
|
|
||||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
#[instrument(level = "debug", skip(self), ret)]
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
pub(super) fn compute_projection_goal(
|
pub(super) fn compute_normalizes_to_goal(
|
||||||
&mut self,
|
&mut self,
|
||||||
goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
|
goal: Goal<'tcx, NormalizesTo<'tcx>>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
let def_id = goal.predicate.def_id();
|
let def_id = goal.predicate.def_id();
|
||||||
match self.tcx().def_kind(def_id) {
|
match self.tcx().def_kind(def_id) {
|
||||||
|
@ -71,16 +71,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
#[instrument(level = "debug", skip(self), ret)]
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
fn normalize_anon_const(
|
fn normalize_anon_const(
|
||||||
&mut self,
|
&mut self,
|
||||||
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
|
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if let Some(normalized_const) = self.try_const_eval_resolve(
|
if let Some(normalized_const) = self.try_const_eval_resolve(
|
||||||
goal.param_env,
|
goal.param_env,
|
||||||
ty::UnevaluatedConst::new(
|
ty::UnevaluatedConst::new(goal.predicate.alias.def_id, goal.predicate.alias.args),
|
||||||
goal.predicate.projection_ty.def_id,
|
|
||||||
goal.predicate.projection_ty.args,
|
|
||||||
),
|
|
||||||
self.tcx()
|
self.tcx()
|
||||||
.type_of(goal.predicate.projection_ty.def_id)
|
.type_of(goal.predicate.alias.def_id)
|
||||||
.no_bound_vars()
|
.no_bound_vars()
|
||||||
.expect("const ty should not rely on other generics"),
|
.expect("const ty should not rely on other generics"),
|
||||||
) {
|
) {
|
||||||
|
@ -92,13 +89,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||||
fn self_ty(self) -> Ty<'tcx> {
|
fn self_ty(self) -> Ty<'tcx> {
|
||||||
self.self_ty()
|
self.self_ty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
|
fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
|
||||||
self.projection_ty.trait_ref(tcx)
|
self.alias.trait_ref(tcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
|
fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
|
||||||
|
@ -123,7 +120,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||||
ecx.instantiate_binder_with_infer(projection_pred);
|
ecx.instantiate_binder_with_infer(projection_pred);
|
||||||
ecx.eq(
|
ecx.eq(
|
||||||
goal.param_env,
|
goal.param_env,
|
||||||
goal.predicate.projection_ty,
|
goal.predicate.alias,
|
||||||
assumption_projection_pred.projection_ty,
|
assumption_projection_pred.projection_ty,
|
||||||
)?;
|
)?;
|
||||||
ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
|
ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
|
||||||
|
@ -132,7 +129,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||||
// Add GAT where clauses from the trait's definition
|
// Add GAT where clauses from the trait's definition
|
||||||
ecx.add_goals(
|
ecx.add_goals(
|
||||||
tcx.predicates_of(goal.predicate.def_id())
|
tcx.predicates_of(goal.predicate.def_id())
|
||||||
.instantiate_own(tcx, goal.predicate.projection_ty.args)
|
.instantiate_own(tcx, goal.predicate.alias.args)
|
||||||
.map(|(pred, _)| goal.with(tcx, pred)),
|
.map(|(pred, _)| goal.with(tcx, pred)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -148,12 +145,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||||
|
|
||||||
fn consider_impl_candidate(
|
fn consider_impl_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
|
goal: Goal<'tcx, NormalizesTo<'tcx>>,
|
||||||
impl_def_id: DefId,
|
impl_def_id: DefId,
|
||||||
) -> Result<Candidate<'tcx>, NoSolution> {
|
) -> Result<Candidate<'tcx>, NoSolution> {
|
||||||
let tcx = ecx.tcx();
|
let tcx = ecx.tcx();
|
||||||
|
|
||||||
let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx);
|
let goal_trait_ref = goal.predicate.alias.trait_ref(tcx);
|
||||||
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
|
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
|
||||||
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
|
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
|
||||||
if !drcx.args_may_unify(goal_trait_ref.args, impl_trait_ref.skip_binder().args) {
|
if !drcx.args_may_unify(goal_trait_ref.args, impl_trait_ref.skip_binder().args) {
|
||||||
|
@ -177,7 +174,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||||
// Add GAT where clauses from the trait's definition
|
// Add GAT where clauses from the trait's definition
|
||||||
ecx.add_goals(
|
ecx.add_goals(
|
||||||
tcx.predicates_of(goal.predicate.def_id())
|
tcx.predicates_of(goal.predicate.def_id())
|
||||||
.instantiate_own(tcx, goal.predicate.projection_ty.args)
|
.instantiate_own(tcx, goal.predicate.alias.args)
|
||||||
.map(|(pred, _)| goal.with(tcx, pred)),
|
.map(|(pred, _)| goal.with(tcx, pred)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -202,7 +199,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||||
tcx,
|
tcx,
|
||||||
guar,
|
guar,
|
||||||
tcx.type_of(goal.predicate.def_id())
|
tcx.type_of(goal.predicate.def_id())
|
||||||
.instantiate(tcx, goal.predicate.projection_ty.args),
|
.instantiate(tcx, goal.predicate.alias.args),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
ty::AssocKind::Type => Ty::new_error(tcx, guar).into(),
|
ty::AssocKind::Type => Ty::new_error(tcx, guar).into(),
|
||||||
|
@ -227,11 +224,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||||
//
|
//
|
||||||
// And then map these args to the args of the defining impl of `Assoc`, going
|
// And then map these args to the args of the defining impl of `Assoc`, going
|
||||||
// from `[u32, u64]` to `[u32, i32, u64]`.
|
// from `[u32, u64]` to `[u32, i32, u64]`.
|
||||||
let impl_args_with_gat = goal.predicate.projection_ty.args.rebase_onto(
|
let impl_args_with_gat =
|
||||||
tcx,
|
goal.predicate.alias.args.rebase_onto(tcx, goal_trait_ref.def_id, impl_args);
|
||||||
goal_trait_ref.def_id,
|
|
||||||
impl_args,
|
|
||||||
);
|
|
||||||
let args = ecx.translate_args(
|
let args = ecx.translate_args(
|
||||||
goal.param_env,
|
goal.param_env,
|
||||||
impl_def_id,
|
impl_def_id,
|
|
@ -12,10 +12,10 @@ use crate::solve::{EvalCtxt, SolverMode};
|
||||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
pub(super) fn normalize_opaque_type(
|
pub(super) fn normalize_opaque_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
|
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let opaque_ty = goal.predicate.projection_ty;
|
let opaque_ty = goal.predicate.alias;
|
||||||
let expected = goal.predicate.term.ty().expect("no such thing as an opaque const");
|
let expected = goal.predicate.term.ty().expect("no such thing as an opaque const");
|
||||||
|
|
||||||
match (goal.param_env.reveal(), self.solver_mode()) {
|
match (goal.param_env.reveal(), self.solver_mode()) {
|
|
@ -11,10 +11,10 @@ use super::EvalCtxt;
|
||||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
pub(super) fn normalize_weak_type(
|
pub(super) fn normalize_weak_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
|
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let weak_ty = goal.predicate.projection_ty;
|
let weak_ty = goal.predicate.alias;
|
||||||
let expected = goal.predicate.term.ty().expect("no such thing as a const alias");
|
let expected = goal.predicate.term.ty().expect("no such thing as a const alias");
|
||||||
|
|
||||||
let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);
|
let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);
|
23
compiler/rustc_trait_selection/src/solve/project_goals.rs
Normal file
23
compiler/rustc_trait_selection/src/solve/project_goals.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use super::EvalCtxt;
|
||||||
|
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||||
|
use rustc_middle::ty::{self, ProjectionPredicate};
|
||||||
|
|
||||||
|
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
|
pub(super) fn compute_projection_goal(
|
||||||
|
&mut self,
|
||||||
|
goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
|
||||||
|
) -> QueryResult<'tcx> {
|
||||||
|
match goal.predicate.term.unpack() {
|
||||||
|
ty::TermKind::Ty(term) => {
|
||||||
|
let alias = goal.predicate.projection_ty.to_ty(self.tcx());
|
||||||
|
self.eq(goal.param_env, alias, term)?;
|
||||||
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
|
}
|
||||||
|
// FIXME(associated_const_equality): actually do something here.
|
||||||
|
ty::TermKind::Const(_) => {
|
||||||
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -820,6 +820,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||||
// the `ParamEnv`.
|
// the `ParamEnv`.
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
|
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
|
||||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
|
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
|
||||||
|
| ty::PredicateKind::NormalizesTo(..)
|
||||||
| ty::PredicateKind::AliasRelate(..)
|
| ty::PredicateKind::AliasRelate(..)
|
||||||
| ty::PredicateKind::ObjectSafe(..)
|
| ty::PredicateKind::ObjectSafe(..)
|
||||||
| ty::PredicateKind::Subtype(..)
|
| ty::PredicateKind::Subtype(..)
|
||||||
|
|
|
@ -854,6 +854,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
|
|
||||||
ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"),
|
ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"),
|
||||||
|
|
||||||
|
ty::PredicateKind::NormalizesTo(..) => span_bug!(
|
||||||
|
span,
|
||||||
|
"NormalizesTo predicate should never be the predicate cause of a SelectionError"
|
||||||
|
),
|
||||||
|
|
||||||
ty::PredicateKind::AliasRelate(..) => span_bug!(
|
ty::PredicateKind::AliasRelate(..) => span_bug!(
|
||||||
span,
|
span,
|
||||||
"AliasRelate predicate should never be the predicate cause of a SelectionError"
|
"AliasRelate predicate should never be the predicate cause of a SelectionError"
|
||||||
|
|
|
@ -360,8 +360,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||||
ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)]))
|
ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)]))
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
|
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
|
||||||
|
ty::PredicateKind::NormalizesTo(..) => {
|
||||||
|
bug!("NormalizesTo is only used by the new solver")
|
||||||
|
}
|
||||||
ty::PredicateKind::AliasRelate(..) => {
|
ty::PredicateKind::AliasRelate(..) => {
|
||||||
bug!("AliasRelate is only used for new solver")
|
bug!("AliasRelate is only used by the new solver")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(pred) => match pred {
|
Some(pred) => match pred {
|
||||||
|
@ -412,8 +415,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
|
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
|
||||||
|
ty::PredicateKind::NormalizesTo(..) => {
|
||||||
|
bug!("NormalizesTo is only used by the new solver")
|
||||||
|
}
|
||||||
ty::PredicateKind::AliasRelate(..) => {
|
ty::PredicateKind::AliasRelate(..) => {
|
||||||
bug!("AliasRelate is only used for new solver")
|
bug!("AliasRelate is only used by the new solver")
|
||||||
}
|
}
|
||||||
|
|
||||||
// General case overflow check. Allow `process_trait_obligation`
|
// General case overflow check. Allow `process_trait_obligation`
|
||||||
|
|
|
@ -123,9 +123,9 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
|
||||||
Some(pred) => pred,
|
Some(pred) => pred,
|
||||||
};
|
};
|
||||||
match pred {
|
match pred {
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
|
|
||||||
// FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
|
// FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
|
||||||
// if we ever support that
|
// if we ever support that
|
||||||
|
ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
|
||||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
|
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
|
||||||
| ty::PredicateKind::Subtype(..)
|
| ty::PredicateKind::Subtype(..)
|
||||||
| ty::PredicateKind::Coerce(..)
|
| ty::PredicateKind::Coerce(..)
|
||||||
|
@ -134,8 +134,8 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
|
||||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
||||||
| ty::PredicateKind::ConstEquate(..)
|
| ty::PredicateKind::ConstEquate(..)
|
||||||
| ty::PredicateKind::Ambiguous
|
| ty::PredicateKind::Ambiguous
|
||||||
| ty::PredicateKind::AliasRelate(..)
|
| ty::PredicateKind::NormalizesTo(..)
|
||||||
=> {}
|
| ty::PredicateKind::AliasRelate(..) => {}
|
||||||
|
|
||||||
// We need to search through *all* WellFormed predicates
|
// We need to search through *all* WellFormed predicates
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||||
|
@ -143,10 +143,9 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to register region relationships
|
// We need to register region relationships
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
|
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
|
||||||
r_a,
|
ty::OutlivesPredicate(r_a, r_b),
|
||||||
r_b,
|
)) => outlives_bounds.push(ty::OutlivesPredicate(r_a.into(), r_b)),
|
||||||
))) => outlives_bounds.push(ty::OutlivesPredicate(r_a.into(), r_b)),
|
|
||||||
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
|
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
|
||||||
ty_a,
|
ty_a,
|
||||||
|
|
|
@ -990,8 +990,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ty::PredicateKind::NormalizesTo(..) => {
|
||||||
|
bug!("NormalizesTo is only used by the new solver")
|
||||||
|
}
|
||||||
ty::PredicateKind::AliasRelate(..) => {
|
ty::PredicateKind::AliasRelate(..) => {
|
||||||
bug!("AliasRelate is only used for new solver")
|
bug!("AliasRelate is only used by the new solver")
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
|
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
||||||
|
|
|
@ -25,8 +25,7 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
|
||||||
// FIXME(-Ztrait-solver=next): correctly handle
|
// FIXME(-Ztrait-solver=next): correctly handle
|
||||||
// overflow here.
|
// overflow here.
|
||||||
for _ in 0..256 {
|
for _ in 0..256 {
|
||||||
let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, projection_ty) = *ty.kind()
|
let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, alias) = *ty.kind() else {
|
||||||
else {
|
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,10 +37,7 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
|
||||||
self.infcx.tcx,
|
self.infcx.tcx,
|
||||||
self.cause.clone(),
|
self.cause.clone(),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
ty::Binder::dummy(ty::ProjectionPredicate {
|
ty::NormalizesTo { alias, term: new_infer_ty.into() },
|
||||||
projection_ty,
|
|
||||||
term: new_infer_ty.into(),
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
if self.infcx.predicate_may_hold(&obligation) {
|
if self.infcx.predicate_may_hold(&obligation) {
|
||||||
fulfill_cx.register_predicate_obligation(self.infcx, obligation);
|
fulfill_cx.register_predicate_obligation(self.infcx, obligation);
|
||||||
|
|
|
@ -55,6 +55,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
|
ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
|
||||||
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
|
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
|
||||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
|
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
|
||||||
|
| ty::PredicateKind::NormalizesTo(..)
|
||||||
| ty::PredicateKind::AliasRelate(..)
|
| ty::PredicateKind::AliasRelate(..)
|
||||||
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
|
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
|
||||||
| ty::PredicateKind::ObjectSafe(..)
|
| ty::PredicateKind::ObjectSafe(..)
|
||||||
|
|
|
@ -57,6 +57,7 @@ pub trait Interner: Sized {
|
||||||
type RegionOutlivesPredicate: Clone + Debug + Hash + Eq;
|
type RegionOutlivesPredicate: Clone + Debug + Hash + Eq;
|
||||||
type TypeOutlivesPredicate: Clone + Debug + Hash + Eq;
|
type TypeOutlivesPredicate: Clone + Debug + Hash + Eq;
|
||||||
type ProjectionPredicate: Clone + Debug + Hash + Eq;
|
type ProjectionPredicate: Clone + Debug + Hash + Eq;
|
||||||
|
type NormalizesTo: Clone + Debug + Hash + Eq;
|
||||||
type SubtypePredicate: Clone + Debug + Hash + Eq;
|
type SubtypePredicate: Clone + Debug + Hash + Eq;
|
||||||
type CoercePredicate: Clone + Debug + Hash + Eq;
|
type CoercePredicate: Clone + Debug + Hash + Eq;
|
||||||
type ClosureKind: Clone + Debug + Hash + Eq;
|
type ClosureKind: Clone + Debug + Hash + Eq;
|
||||||
|
|
|
@ -120,7 +120,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(derivative::Derivative)]
|
#[derive(derivative::Derivative)]
|
||||||
#[derivative(Clone(bound = ""), Hash(bound = ""))]
|
#[derivative(Clone(bound = ""), Hash(bound = ""), PartialEq(bound = ""), Eq(bound = ""))]
|
||||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||||
pub enum PredicateKind<I: Interner> {
|
pub enum PredicateKind<I: Interner> {
|
||||||
/// Prove a clause
|
/// Prove a clause
|
||||||
|
@ -153,6 +153,15 @@ pub enum PredicateKind<I: Interner> {
|
||||||
/// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
|
/// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
|
||||||
Ambiguous,
|
Ambiguous,
|
||||||
|
|
||||||
|
/// The alias normalizes to `term`. Unlike `Projection`, this always fails if the alias
|
||||||
|
/// cannot be normalized in the current context.
|
||||||
|
///
|
||||||
|
/// `Projection(<T as Trait>::Assoc, ?x)` results in `?x == <T as Trait>::Assoc` while
|
||||||
|
/// `NormalizesTo(<T as Trait>::Assoc, ?x)` results in `NoSolution`.
|
||||||
|
///
|
||||||
|
/// Only used in the new solver.
|
||||||
|
NormalizesTo(I::NormalizesTo),
|
||||||
|
|
||||||
/// Separate from `ClauseKind::Projection` which is used for normalization in new solver.
|
/// Separate from `ClauseKind::Projection` which is used for normalization in new solver.
|
||||||
/// This predicate requires two terms to be equal to eachother.
|
/// This predicate requires two terms to be equal to eachother.
|
||||||
///
|
///
|
||||||
|
@ -168,28 +177,11 @@ where
|
||||||
I::Term: Copy,
|
I::Term: Copy,
|
||||||
I::CoercePredicate: Copy,
|
I::CoercePredicate: Copy,
|
||||||
I::SubtypePredicate: Copy,
|
I::SubtypePredicate: Copy,
|
||||||
|
I::NormalizesTo: Copy,
|
||||||
ClauseKind<I>: Copy,
|
ClauseKind<I>: Copy,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Interner> PartialEq for PredicateKind<I> {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
match (self, other) {
|
|
||||||
(Self::Clause(l0), Self::Clause(r0)) => l0 == r0,
|
|
||||||
(Self::ObjectSafe(l0), Self::ObjectSafe(r0)) => l0 == r0,
|
|
||||||
(Self::Subtype(l0), Self::Subtype(r0)) => l0 == r0,
|
|
||||||
(Self::Coerce(l0), Self::Coerce(r0)) => l0 == r0,
|
|
||||||
(Self::ConstEquate(l0, l1), Self::ConstEquate(r0, r1)) => l0 == r0 && l1 == r1,
|
|
||||||
(Self::AliasRelate(l0, l1, l2), Self::AliasRelate(r0, r1, r2)) => {
|
|
||||||
l0 == r0 && l1 == r1 && l2 == r2
|
|
||||||
}
|
|
||||||
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I: Interner> Eq for PredicateKind<I> {}
|
|
||||||
|
|
||||||
impl<I: Interner> TypeFoldable<I> for PredicateKind<I>
|
impl<I: Interner> TypeFoldable<I> for PredicateKind<I>
|
||||||
where
|
where
|
||||||
I::DefId: TypeFoldable<I>,
|
I::DefId: TypeFoldable<I>,
|
||||||
|
@ -198,6 +190,7 @@ where
|
||||||
I::Term: TypeFoldable<I>,
|
I::Term: TypeFoldable<I>,
|
||||||
I::CoercePredicate: TypeFoldable<I>,
|
I::CoercePredicate: TypeFoldable<I>,
|
||||||
I::SubtypePredicate: TypeFoldable<I>,
|
I::SubtypePredicate: TypeFoldable<I>,
|
||||||
|
I::NormalizesTo: TypeFoldable<I>,
|
||||||
ClauseKind<I>: TypeFoldable<I>,
|
ClauseKind<I>: TypeFoldable<I>,
|
||||||
{
|
{
|
||||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||||
|
@ -210,6 +203,7 @@ where
|
||||||
PredicateKind::ConstEquate(a.try_fold_with(folder)?, b.try_fold_with(folder)?)
|
PredicateKind::ConstEquate(a.try_fold_with(folder)?, b.try_fold_with(folder)?)
|
||||||
}
|
}
|
||||||
PredicateKind::Ambiguous => PredicateKind::Ambiguous,
|
PredicateKind::Ambiguous => PredicateKind::Ambiguous,
|
||||||
|
PredicateKind::NormalizesTo(p) => PredicateKind::NormalizesTo(p.try_fold_with(folder)?),
|
||||||
PredicateKind::AliasRelate(a, b, d) => PredicateKind::AliasRelate(
|
PredicateKind::AliasRelate(a, b, d) => PredicateKind::AliasRelate(
|
||||||
a.try_fold_with(folder)?,
|
a.try_fold_with(folder)?,
|
||||||
b.try_fold_with(folder)?,
|
b.try_fold_with(folder)?,
|
||||||
|
@ -227,6 +221,7 @@ where
|
||||||
I::Term: TypeVisitable<I>,
|
I::Term: TypeVisitable<I>,
|
||||||
I::CoercePredicate: TypeVisitable<I>,
|
I::CoercePredicate: TypeVisitable<I>,
|
||||||
I::SubtypePredicate: TypeVisitable<I>,
|
I::SubtypePredicate: TypeVisitable<I>,
|
||||||
|
I::NormalizesTo: TypeVisitable<I>,
|
||||||
ClauseKind<I>: TypeVisitable<I>,
|
ClauseKind<I>: TypeVisitable<I>,
|
||||||
{
|
{
|
||||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
|
@ -240,6 +235,7 @@ where
|
||||||
b.visit_with(visitor)
|
b.visit_with(visitor)
|
||||||
}
|
}
|
||||||
PredicateKind::Ambiguous => ControlFlow::Continue(()),
|
PredicateKind::Ambiguous => ControlFlow::Continue(()),
|
||||||
|
PredicateKind::NormalizesTo(p) => p.visit_with(visitor),
|
||||||
PredicateKind::AliasRelate(a, b, d) => {
|
PredicateKind::AliasRelate(a, b, d) => {
|
||||||
a.visit_with(visitor)?;
|
a.visit_with(visitor)?;
|
||||||
b.visit_with(visitor)?;
|
b.visit_with(visitor)?;
|
||||||
|
@ -294,6 +290,7 @@ impl<I: Interner> fmt::Debug for PredicateKind<I> {
|
||||||
}
|
}
|
||||||
PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({c1:?}, {c2:?})"),
|
PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({c1:?}, {c2:?})"),
|
||||||
PredicateKind::Ambiguous => write!(f, "Ambiguous"),
|
PredicateKind::Ambiguous => write!(f, "Ambiguous"),
|
||||||
|
PredicateKind::NormalizesTo(p) => p.fmt(f),
|
||||||
PredicateKind::AliasRelate(t1, t2, dir) => {
|
PredicateKind::AliasRelate(t1, t2, dir) => {
|
||||||
write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})")
|
write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})")
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ fn main() {
|
||||||
let x = String::from("hello, world");
|
let x = String::from("hello, world");
|
||||||
drop(<() as Foo>::copy_me(&x));
|
drop(<() as Foo>::copy_me(&x));
|
||||||
//~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized`
|
//~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized`
|
||||||
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
|
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
|
||||||
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
|
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
|
||||||
//~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
|
//~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
|
||||||
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
|
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
|
||||||
|
|
|
@ -19,7 +19,7 @@ LL | drop(<() as Foo>::copy_me(&x));
|
||||||
|
|
|
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
|
||||||
|
|
||||||
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
|
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
|
||||||
--> $DIR/alias-bound-unsound.rs:24:10
|
--> $DIR/alias-bound-unsound.rs:24:10
|
||||||
|
|
|
|
||||||
LL | drop(<() as Foo>::copy_me(&x));
|
LL | drop(<() as Foo>::copy_me(&x));
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// compile-flags: -Ztrait-solver=next
|
// compile-flags: -Ztrait-solver=next
|
||||||
// known-bug: trait-system-refactor-initiative#60
|
// known-bug: trait-system-refactor-initiative#60
|
||||||
|
// dont-check-failure-status
|
||||||
|
// dont-check-compiler-stderr
|
||||||
|
|
||||||
// Generalizing a projection containing an inference variable
|
// Generalizing a projection containing an inference variable
|
||||||
// which cannot be named by the `root_vid` can result in ambiguity.
|
// which cannot be named by the `root_vid` can result in ambiguity.
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
error[E0271]: type mismatch resolving `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _`
|
error[E0275]: overflow evaluating the requirement `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _`
|
||||||
--> $DIR/occurs-check-nested-alias.rs:35:9
|
--> $DIR/occurs-check-nested-alias.rs:36:9
|
||||||
|
|
|
|
||||||
LL | x = y;
|
LL | x = y;
|
||||||
| ^ types differ
|
| ^
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`occurs_check_nested_alias`)
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0271`.
|
For more information about this error, try `rustc --explain E0275`.
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// revisions: old next
|
// revisions: old next
|
||||||
//[old] check-pass
|
//[old] check-pass
|
||||||
|
|
||||||
// Need to emit an alias-relate instead of a `Projection` goal here.
|
// Currently always fails to generalize the outer alias, even if it
|
||||||
|
// is treated as rigid by `alias-relate`.
|
||||||
//[next] compile-flags: -Ztrait-solver=next
|
//[next] compile-flags: -Ztrait-solver=next
|
||||||
//[next] known-bug: trait-system-refactor-initiative#8
|
//[next] known-bug: trait-system-refactor-initiative#8
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
// check-pass
|
||||||
|
// compile-flags: -Ztrait-solver=next
|
||||||
|
|
||||||
|
// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/1
|
||||||
|
// a minimization of a pattern in core.
|
||||||
|
fn next<T: Iterator<Item = U>, U>(t: &mut T) -> Option<U> {
|
||||||
|
t.next()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo<T: Iterator>(t: &mut T) {
|
||||||
|
let _: Option<T::Item> = next(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// check-pass
|
||||||
|
// compile-flags: -Ztrait-solver=next
|
||||||
|
|
||||||
|
// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/1,
|
||||||
|
// a minimization of a pattern in core.
|
||||||
|
|
||||||
|
trait Iterator {
|
||||||
|
type Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Flatten<I>(I);
|
||||||
|
|
||||||
|
impl<I, U> Iterator for Flatten<I>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = U>,
|
||||||
|
{
|
||||||
|
type Item = U;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn needs_iterator<I: Iterator>() {}
|
||||||
|
|
||||||
|
fn environment<J>()
|
||||||
|
where
|
||||||
|
J: Iterator,
|
||||||
|
{
|
||||||
|
needs_iterator::<Flatten<J>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -8,13 +8,11 @@ LL | #![feature(specialization)]
|
||||||
= help: consider using `min_specialization` instead, which is more stable and complete
|
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id normalizes-to _`
|
||||||
--> $DIR/specialization-transmute.rs:15:23
|
--> $DIR/specialization-transmute.rs:15:23
|
||||||
|
|
|
|
||||||
LL | fn intu(&self) -> &Self::Id {
|
LL | fn intu(&self) -> &Self::Id {
|
||||||
| ^^^^^^^^^ cannot infer type
|
| ^^^^^^^^^ cannot satisfy `<T as Default>::Id normalizes-to _`
|
||||||
|
|
|
||||||
= note: cannot satisfy `<T as Default>::Id == _`
|
|
||||||
|
|
||||||
error[E0282]: type annotations needed
|
error[E0282]: type annotations needed
|
||||||
--> $DIR/specialization-transmute.rs:13:23
|
--> $DIR/specialization-transmute.rs:13:23
|
||||||
|
|
Loading…
Add table
Reference in a new issue