implement and use NormalizesTo

This commit is contained in:
lcnr 2023-12-07 18:20:27 +01:00
parent 3978f545ba
commit ffb4c08a81
21 changed files with 135 additions and 125 deletions

View file

@ -34,8 +34,8 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVa
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{AliasRelationDirection, TyVar};
use rustc_middle::ty::{IntType, UintType};
use rustc_span::DUMMY_SP;
@ -490,31 +490,47 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
// cyclic type. We instead delay the unification in case
// the alias can be normalized to something which does not
// mention `?0`.
// FIXME(-Ztrait-solver=next): replace this with `AliasRelate`
let &ty::Alias(kind, data) = a_ty.kind() else {
bug!("generalization should only result in infer vars for aliases");
};
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));
if self.infcx.next_trait_solver() {
let (lhs, rhs, direction) = match ambient_variance {
ty::Variance::Invariant => {
(a_ty.into(), b_ty.into(), AliasRelationDirection::Equate)
}
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 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() },
))
}
// 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 {
match ambient_variance {
ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
@ -525,9 +541,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
a_ty,
b_ty,
),
ty::Variance::Bivariant => {
unreachable!("no code should be generalizing bivariantly (currently)")
}
ty::Variance::Bivariant => unreachable!("bivariant generalization"),
}?;
}

View file

@ -2814,7 +2814,7 @@ define_print! {
p!("the constant `", print(c1), "` equals `", print(c2), "`")
}
ty::PredicateKind::Ambiguous => p!("ambiguous"),
ty::PredicateKind::NormalizesTo(data) => p!(print(data.alias), " normalizes-to ", print(data.term)),
ty::PredicateKind::NormalizesTo(data) => p!(print(data)),
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
}
}
@ -2946,6 +2946,12 @@ define_print_and_forward_display! {
p!(print(self.term))
}
ty::NormalizesTo<'tcx> {
p!(print(self.alias), " normalizes-to ");
cx.reset_type_limit();
p!(print(self.term))
}
ty::Term<'tcx> {
match self.unpack() {
ty::TermKind::Ty(ty) => p!(print(ty)),

View file

@ -92,7 +92,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
self.add_goal(Goal::new(
self.tcx(),
param_env,
ty::ProjectionPredicate { projection_ty: alias, term },
ty::NormalizesTo { alias, term },
));
self.try_evaluate_added_goals()?;
Ok(Some(self.resolve_vars_if_possible(term)))
@ -109,11 +109,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
opaque: ty::AliasTy<'tcx>,
term: ty::Term<'tcx>,
) -> QueryResult<'tcx> {
self.add_goal(Goal::new(
self.tcx(),
param_env,
ty::ProjectionPredicate { projection_ty: opaque, term },
));
self.add_goal(Goal::new(self.tcx(), param_env, ty::NormalizesTo { alias: opaque, term }));
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}

View file

@ -352,15 +352,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
num_steps: usize,
) {
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| {
if tcx.recursion_limit().value_within_limit(num_steps) {
let normalized_ty = ecx.next_ty_infer();
let normalizes_to_goal = goal.with(
tcx,
ty::ProjectionPredicate { projection_ty, term: normalized_ty.into() },
);
let normalizes_to_goal =
goal.with(tcx, ty::NormalizesTo { alias, term: normalized_ty.into() });
ecx.add_goal(normalizes_to_goal);
if let Err(NoSolution) = ecx.try_evaluate_added_goals() {
debug!("self type normalization failed");

View file

@ -69,8 +69,8 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
};
let value = value.fold_with(&mut canonicalizer);
assert!(!value.has_infer());
assert!(!value.has_placeholders());
assert!(!value.has_infer(), "unexpected infer in {value:?}");
assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
let (max_universe, variables) = canonicalizer.finalize();

View file

@ -103,7 +103,7 @@ pub(super) struct NestedGoals<'tcx> {
/// 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
/// 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.
pub(super) goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
}
@ -423,7 +423,9 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
ty::PredicateKind::ConstEquate(_, _) => {
bug!("ConstEquate should not be emitted when `-Ztrait-solver=next` is active")
}
ty::PredicateKind::NormalizesTo(_) => unimplemented!(),
ty::PredicateKind::NormalizesTo(predicate) => {
self.compute_normalizes_to_goal(Goal { param_env, predicate })
}
ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self
.compute_alias_relate_goal(Goal {
param_env,
@ -493,10 +495,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
let unconstrained_rhs = self.next_term_infer_of_kind(goal.predicate.term);
let unconstrained_goal = goal.with(
tcx,
ty::ProjectionPredicate {
projection_ty: goal.predicate.projection_ty,
term: unconstrained_rhs,
},
ty::NormalizesTo { alias: goal.predicate.alias, term: unconstrained_rhs },
);
let (_, certainty, instantiate_goals) = self.evaluate_goal(
@ -518,9 +517,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
// looking at the "has changed" return from evaluate_goal,
// because we expect the `unconstrained_rhs` part of the predicate
// to have changed -- that means we actually normalized successfully!
if goal.predicate.projection_ty
!= self.resolve_vars_if_possible(goal.predicate.projection_ty)
{
if goal.predicate.alias != self.resolve_vars_if_possible(goal.predicate.alias) {
unchanged_certainty = None;
}
@ -590,9 +587,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
///
/// 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.
#[instrument(level = "debug", skip(self), ret)]
pub(super) fn term_is_fully_unconstrained(
&self,
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
) -> bool {
let term_is_infer = match goal.predicate.term.unpack() {
ty::TermKind::Ty(ty) => {
@ -656,7 +654,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let mut visitor = ContainsTerm { infcx: self.infcx, term: goal.predicate.term };
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()
}

View file

@ -35,6 +35,7 @@ mod eval_ctxt;
mod fulfill;
pub mod inspect;
mod normalize;
mod normalizes_to;
mod project_goals;
mod search_graph;
mod trait_goals;
@ -216,7 +217,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
impl<'tcx> EvalCtxt<'_, 'tcx> {
#[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!(
self.nested_goals.normalizes_to_hack_goal.is_none(),
"attempted to set the projection eq hack goal when one already exists"
@ -310,17 +311,17 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
return None;
}
let ty::Alias(kind, projection_ty) = *ty.kind() else {
let ty::Alias(kind, alias) = *ty.kind() else {
return Some(ty);
};
// 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 Some(def_id) = projection_ty.def_id.as_local() {
if let Some(def_id) = alias.def_id.as_local() {
if self
.unify_existing_opaque_tys(
param_env,
OpaqueTypeKey { def_id, args: projection_ty.args },
OpaqueTypeKey { def_id, args: alias.args },
self.next_ty_infer(),
)
.is_empty()
@ -335,7 +336,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let normalizes_to_goal = Goal::new(
this.tcx(),
param_env,
ty::ProjectionPredicate { projection_ty, term: normalized_ty.into() },
ty::NormalizesTo { alias, term: normalized_ty.into() },
);
this.add_goal(normalizes_to_goal);
this.try_evaluate_added_goals()?;

View file

@ -76,7 +76,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
tcx,
self.at.cause.clone(),
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
@ -129,8 +129,8 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
tcx,
self.at.cause.clone(),
self.at.param_env,
ty::ProjectionPredicate {
projection_ty: AliasTy::new(tcx, uv.def, uv.args),
ty::NormalizesTo {
alias: AliasTy::new(tcx, uv.def, uv.args),
term: new_infer_ct.into(),
},
);

View file

@ -12,10 +12,10 @@ use super::EvalCtxt;
impl<'tcx> EvalCtxt<'_, 'tcx> {
pub(super) fn normalize_inherent_associated_type(
&mut self,
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
) -> QueryResult<'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 impl_def_id = tcx.parent(inherent.def_id);

View file

@ -13,20 +13,20 @@ use rustc_middle::traits::solve::{
};
use rustc_middle::traits::BuiltinImplSource;
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::{ToPredicate, TypeVisitableExt};
use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP};
mod inherent_projection;
mod inherent;
mod opaques;
mod weak_types;
impl<'tcx> EvalCtxt<'_, 'tcx> {
#[instrument(level = "debug", skip(self), ret)]
pub(super) fn compute_projection_goal(
pub(super) fn compute_normalizes_to_goal(
&mut self,
goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
goal: Goal<'tcx, NormalizesTo<'tcx>>,
) -> QueryResult<'tcx> {
let def_id = goal.predicate.def_id();
match self.tcx().def_kind(def_id) {
@ -71,16 +71,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
#[instrument(level = "debug", skip(self), ret)]
fn normalize_anon_const(
&mut self,
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
) -> QueryResult<'tcx> {
if let Some(normalized_const) = self.try_const_eval_resolve(
goal.param_env,
ty::UnevaluatedConst::new(
goal.predicate.projection_ty.def_id,
goal.predicate.projection_ty.args,
),
ty::UnevaluatedConst::new(goal.predicate.alias.def_id, goal.predicate.alias.args),
self.tcx()
.type_of(goal.predicate.projection_ty.def_id)
.type_of(goal.predicate.alias.def_id)
.no_bound_vars()
.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> {
self.self_ty()
}
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 {
@ -123,7 +120,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
ecx.instantiate_binder_with_infer(projection_pred);
ecx.eq(
goal.param_env,
goal.predicate.projection_ty,
goal.predicate.alias,
assumption_projection_pred.projection_ty,
)?;
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
ecx.add_goals(
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)),
);
@ -148,12 +145,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
fn consider_impl_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
goal: Goal<'tcx, NormalizesTo<'tcx>>,
impl_def_id: DefId,
) -> Result<Candidate<'tcx>, NoSolution> {
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 drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
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
ecx.add_goals(
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)),
);
@ -202,7 +199,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
tcx,
guar,
tcx.type_of(goal.predicate.def_id())
.instantiate(tcx, goal.predicate.projection_ty.args),
.instantiate(tcx, goal.predicate.alias.args),
)
.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
// from `[u32, u64]` to `[u32, i32, u64]`.
let impl_args_with_gat = goal.predicate.projection_ty.args.rebase_onto(
tcx,
goal_trait_ref.def_id,
impl_args,
);
let impl_args_with_gat =
goal.predicate.alias.args.rebase_onto(tcx, goal_trait_ref.def_id, impl_args);
let args = ecx.translate_args(
goal.param_env,
impl_def_id,

View file

@ -12,10 +12,10 @@ use crate::solve::{EvalCtxt, SolverMode};
impl<'tcx> EvalCtxt<'_, 'tcx> {
pub(super) fn normalize_opaque_type(
&mut self,
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
) -> QueryResult<'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");
match (goal.param_env.reveal(), self.solver_mode()) {

View file

@ -11,10 +11,10 @@ use super::EvalCtxt;
impl<'tcx> EvalCtxt<'_, 'tcx> {
pub(super) fn normalize_weak_type(
&mut self,
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
) -> QueryResult<'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 actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);

View 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)
}
}
}
}

View file

@ -25,8 +25,7 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
// FIXME(-Ztrait-solver=next): correctly handle
// overflow here.
for _ in 0..256 {
let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, projection_ty) = *ty.kind()
else {
let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, alias) = *ty.kind() else {
break;
};
@ -38,10 +37,7 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
self.infcx.tcx,
self.cause.clone(),
self.param_env,
ty::Binder::dummy(ty::ProjectionPredicate {
projection_ty,
term: new_infer_ty.into(),
}),
ty::NormalizesTo { alias, term: new_infer_ty.into() },
);
if self.infcx.predicate_may_hold(&obligation) {
fulfill_cx.register_predicate_obligation(self.infcx, obligation);

View file

@ -120,7 +120,7 @@ where
}
#[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))]
pub enum PredicateKind<I: Interner> {
/// Prove a clause
@ -169,7 +169,6 @@ pub enum PredicateKind<I: Interner> {
AliasRelate(I::Term, I::Term, AliasRelationDirection),
}
/// FIXME: This impl sh
impl<I: Interner> Copy for PredicateKind<I>
where
I::DefId: Copy,
@ -183,24 +182,6 @@ where
{
}
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>
where
I::DefId: TypeFoldable<I>,

View file

@ -23,7 +23,7 @@ fn main() {
let x = String::from("hello, world");
drop(<() as Foo>::copy_me(&x));
//~^ 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 `String <: <() as Foo>::Item`
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`

View file

@ -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`)
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
|
LL | drop(<() as Foo>::copy_me(&x));

View file

@ -1,5 +1,7 @@
// compile-flags: -Ztrait-solver=next
// known-bug: trait-system-refactor-initiative#60
// dont-check-failure-status
// dont-check-compiler-stderr
// Generalizing a projection containing an inference variable
// which cannot be named by the `root_vid` can result in ambiguity.

View file

@ -1,9 +1,11 @@
error[E0271]: type mismatch resolving `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _`
--> $DIR/occurs-check-nested-alias.rs:35:9
error[E0275]: overflow evaluating the requirement `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _`
--> $DIR/occurs-check-nested-alias.rs:36:9
|
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
For more information about this error, try `rustc --explain E0271`.
For more information about this error, try `rustc --explain E0275`.

View file

@ -1,7 +1,8 @@
// revisions: old next
//[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] known-bug: trait-system-refactor-initiative#8
#![crate_type = "lib"]

View file

@ -8,13 +8,11 @@ LL | #![feature(specialization)]
= help: consider using `min_specialization` instead, which is more stable and complete
= 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
|
LL | fn intu(&self) -> &Self::Id {
| ^^^^^^^^^ cannot infer type
|
= note: cannot satisfy `<T as Default>::Id == _`
| ^^^^^^^^^ cannot satisfy `<T as Default>::Id normalizes-to _`
error[E0282]: type annotations needed
--> $DIR/specialization-transmute.rs:13:23