Skip to content

Commit 5f71900

Browse files
committed
impl
1 parent f114acf commit 5f71900

File tree

15 files changed

+712
-633
lines changed

15 files changed

+712
-633
lines changed

compiler/rustc_middle/src/ty/flags.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,8 @@ impl FlagComputation {
288288
self.add_ty(ty);
289289
}
290290
ty::PredicateKind::Ambiguous => {}
291-
ty::PredicateKind::NormalizesTo(ty::ProjectionPredicate { projection_ty, term }) => {
292-
self.add_alias_ty(projection_ty);
291+
ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => {
292+
self.add_alias_ty(alias);
293293
self.add_term(term);
294294
}
295295
ty::PredicateKind::AliasRelate(t1, t2, _direction) => {

compiler/rustc_middle/src/ty/mod.rs

+48-2
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ pub enum PredicateKind<'tcx> {
662662
/// `NormalizesTo(<T as Trait>::Assoc, ?x)` results in `NoSolution`.
663663
///
664664
/// Only used in the new solver.
665-
NormalizesTo(ProjectionPredicate<'tcx>),
665+
NormalizesTo(NormalizesTo<'tcx>),
666666

667667
/// Separate from `Clause::Projection` which is used for normalization in new solver.
668668
/// This predicate requires two terms to be equal to eachother.
@@ -1184,6 +1184,33 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
11841184
}
11851185
}
11861186

1187+
/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be
1188+
/// proven by actually normalizing `alias`.
1189+
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1190+
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
1191+
pub struct NormalizesTo<'tcx> {
1192+
pub alias: AliasTy<'tcx>,
1193+
pub term: Term<'tcx>,
1194+
}
1195+
1196+
impl<'tcx> NormalizesTo<'tcx> {
1197+
pub fn self_ty(self) -> Ty<'tcx> {
1198+
self.alias.self_ty()
1199+
}
1200+
1201+
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> {
1202+
Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
1203+
}
1204+
1205+
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
1206+
self.alias.trait_def_id(tcx)
1207+
}
1208+
1209+
pub fn def_id(self) -> DefId {
1210+
self.alias.def_id
1211+
}
1212+
}
1213+
11871214
pub trait ToPolyTraitRef<'tcx> {
11881215
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
11891216
}
@@ -1306,6 +1333,12 @@ impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
13061333
}
13071334
}
13081335

1336+
impl<'tcx> ToPredicate<'tcx> for ProjectionPredicate<'tcx> {
1337+
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
1338+
ty::Binder::dummy(self).to_predicate(tcx)
1339+
}
1340+
}
1341+
13091342
impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
13101343
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
13111344
self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx)
@@ -1324,6 +1357,18 @@ impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
13241357
}
13251358
}
13261359

1360+
impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> {
1361+
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
1362+
PredicateKind::NormalizesTo(self).to_predicate(tcx)
1363+
}
1364+
}
1365+
1366+
impl<'tcx> ToPredicate<'tcx> for ty::Binder<'tcx, NormalizesTo<'tcx>> {
1367+
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
1368+
self.map_bound(|p| PredicateKind::NormalizesTo(p)).to_predicate(tcx)
1369+
}
1370+
}
1371+
13271372
impl<'tcx> Predicate<'tcx> {
13281373
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
13291374
let predicate = self.kind();
@@ -1395,7 +1440,8 @@ impl<'tcx> Predicate<'tcx> {
13951440
let predicate = self.kind();
13961441
match predicate.skip_binder() {
13971442
PredicateKind::Clause(clause) => Some(predicate.rebind(clause)),
1398-
PredicateKind::AliasRelate(..)
1443+
PredicateKind::NormalizesTo(..)
1444+
| PredicateKind::AliasRelate(..)
13991445
| PredicateKind::Subtype(..)
14001446
| PredicateKind::Coerce(..)
14011447
| PredicateKind::WellFormed(..)

compiler/rustc_middle/src/ty/print/pretty.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -2836,6 +2836,10 @@ define_print_and_forward_display! {
28362836
p!(print(self.term))
28372837
}
28382838

2839+
ty::NormalizesTo<'tcx> {
2840+
p!("`", print(self.alias), "` normalizes to `", print(self.term), "`")
2841+
}
2842+
28392843
ty::Term<'tcx> {
28402844
match self.unpack() {
28412845
ty::TermKind::Ty(ty) => p!(print(ty)),
@@ -2896,9 +2900,7 @@ define_print_and_forward_display! {
28962900
p!("the type `", print(ty), "` is found in the environment")
28972901
}
28982902
ty::PredicateKind::Ambiguous => p!("ambiguous"),
2899-
ty::PredicateKind::NormalizesTo(ty::ProjectionPredicate { projection_ty, term }) => {
2900-
p!("`", print(projection_ty), "` normalizes to `", print(term), "`")
2901-
}
2903+
ty::PredicateKind::NormalizesTo(predicate) => p!(print(predicate)),
29022904
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
29032905
}
29042906
}

compiler/rustc_middle/src/ty/structural_impls.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,12 @@ impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
165165
}
166166
}
167167

168+
impl<'tcx> fmt::Debug for ty::NormalizesTo<'tcx> {
169+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170+
write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
171+
}
172+
}
173+
168174
impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
169175
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170176
write!(f, "{:?}", self.kind())
@@ -204,9 +210,7 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
204210
write!(f, "TypeWellFormedFromEnv({:?})", ty)
205211
}
206212
ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"),
207-
ty::PredicateKind::NormalizesTo(ty::ProjectionPredicate { projection_ty, term }) => {
208-
write!(f, "NormalizesTo({projection_ty:?}, {term:?})")
209-
}
213+
ty::PredicateKind::NormalizesTo(predicate) => predicate.fmt(f),
210214
ty::PredicateKind::AliasRelate(t1, t2, dir) => {
211215
write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})")
212216
}

compiler/rustc_trait_selection/src/solve/alias_relate.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
123123
direction: ty::AliasRelationDirection,
124124
invert: Invert,
125125
) -> Result<(), NoSolution> {
126-
let other = match direction {
126+
let term = match direction {
127127
// This is purely an optimization.
128128
ty::AliasRelationDirection::Equate => other,
129129

@@ -137,11 +137,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
137137
fresh
138138
}
139139
};
140-
self.add_goal(Goal::new(
141-
self.tcx(),
142-
param_env,
143-
ty::Binder::dummy(ty::ProjectionPredicate { projection_ty: alias, term: other }),
144-
));
140+
self.add_goal(Goal::new(self.tcx(), param_env, ty::NormalizesTo { alias, term }));
145141

146142
Ok(())
147143
}

compiler/rustc_trait_selection/src/solve/assembly/mod.rs

+7-11
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,7 @@ pub(super) enum CandidateSource {
8787
}
8888

8989
/// Methods used to assemble candidates for either trait or projection goals.
90-
pub(super) trait GoalKind<'tcx>:
91-
TypeFoldable<TyCtxt<'tcx>> + Copy + Eq + std::fmt::Display
92-
{
90+
pub(super) trait GoalKind<'tcx>: TypeFoldable<TyCtxt<'tcx>> + Copy + Eq {
9391
fn self_ty(self) -> Ty<'tcx>;
9492

9593
fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx>;
@@ -112,6 +110,9 @@ pub(super) trait GoalKind<'tcx>:
112110
// Consider a clause, which consists of a "assumption" and some "requirements",
113111
// to satisfy a goal. If the requirements hold, then attempt to satisfy our
114112
// goal by equating it with the assumption.
113+
//
114+
// FIXME: change this function to take an actual `Clause` as assumption instead
115+
// of a predicate.
115116
fn consider_implied_clause(
116117
ecx: &mut EvalCtxt<'_, 'tcx>,
117118
goal: Goal<'tcx, Self>,
@@ -332,7 +333,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
332333
candidates: &mut Vec<Candidate<'tcx>>,
333334
) {
334335
let tcx = self.tcx();
335-
let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else {
336+
let &ty::Alias(_, alias) = goal.predicate.self_ty().kind() else {
336337
return
337338
};
338339

@@ -346,13 +347,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
346347
},
347348
|ecx| {
348349
let normalized_ty = ecx.next_ty_infer();
349-
let normalizes_to_goal = goal.with(
350-
tcx,
351-
ty::Binder::dummy(ty::ProjectionPredicate {
352-
projection_ty,
353-
term: normalized_ty.into(),
354-
}),
355-
);
350+
let normalizes_to_goal =
351+
goal.with(tcx, ty::NormalizesTo { alias, term: normalized_ty.into() });
356352
ecx.add_goal(normalizes_to_goal);
357353
let _ = ecx.try_evaluate_added_goals().inspect_err(|_| {
358354
debug!("self type normalization failed");

compiler/rustc_trait_selection/src/solve/eval_ctxt.rs

+6-11
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ pub(super) struct NestedGoals<'tcx> {
9595
/// with a fresh inference variable when we evaluate this goal. That can result
9696
/// in a trait solver cycle. This would currently result in overflow but can be
9797
/// can be unsound with more powerful coinduction in the future.
98-
pub(super) normalizes_to_hack_goal: Option<Goal<'tcx, ty::ProjectionPredicate<'tcx>>>,
98+
pub(super) normalizes_to_hack_goal: Option<Goal<'tcx, ty::NormalizesTo<'tcx>>>,
9999
/// The rest of the goals which have not yet processed or remain ambiguous.
100100
pub(super) goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
101101
}
@@ -333,7 +333,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
333333
bug!("TypeWellFormedFromEnv is only used for Chalk")
334334
}
335335
ty::PredicateKind::NormalizesTo(predicate) => {
336-
self.compute_projection_goal(Goal { param_env, predicate })
336+
self.compute_normalizes_to_goal(Goal { param_env, predicate })
337337
}
338338
ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self
339339
.compute_alias_relate_goal(Goal {
@@ -367,10 +367,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
367367
let unconstrained_rhs = this.next_term_infer_of_kind(goal.predicate.term);
368368
let unconstrained_goal = goal.with(
369369
this.tcx(),
370-
ty::Binder::dummy(ty::ProjectionPredicate {
371-
projection_ty: goal.predicate.projection_ty,
372-
term: unconstrained_rhs,
373-
}),
370+
ty::NormalizesTo { alias: goal.predicate.alias, term: unconstrained_rhs },
374371
);
375372

376373
let (_, certainty, instantiate_goals) =
@@ -400,9 +397,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
400397
// looking at the "has changed" return from evaluate_goal,
401398
// because we expect the `unconstrained_rhs` part of the predicate
402399
// to have changed -- that means we actually normalized successfully!
403-
if goal.predicate.projection_ty
404-
!= this.resolve_vars_if_possible(goal.predicate.projection_ty)
405-
{
400+
if goal.predicate.alias != this.resolve_vars_if_possible(goal.predicate.alias) {
406401
has_changed = Ok(())
407402
}
408403

@@ -507,7 +502,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
507502
/// and does not occur in any other part of the predicate.
508503
pub(super) fn term_is_fully_unconstrained(
509504
&self,
510-
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
505+
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
511506
) -> bool {
512507
let term_is_infer = match goal.predicate.term.unpack() {
513508
ty::TermKind::Ty(ty) => {
@@ -571,7 +566,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
571566
let mut visitor = ContainsTerm { infcx: self.infcx, term: goal.predicate.term };
572567

573568
term_is_infer
574-
&& goal.predicate.projection_ty.visit_with(&mut visitor).is_continue()
569+
&& goal.predicate.alias.visit_with(&mut visitor).is_continue()
575570
&& goal.param_env.visit_with(&mut visitor).is_continue()
576571
}
577572

compiler/rustc_trait_selection/src/solve/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ mod assembly;
2525
mod canonicalize;
2626
mod eval_ctxt;
2727
mod fulfill;
28+
mod normalizes_to;
2829
mod opaques;
2930
mod project_goals;
3031
mod search_graph;
@@ -168,7 +169,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
168169

169170
impl<'tcx> EvalCtxt<'_, 'tcx> {
170171
#[instrument(level = "debug", skip(self))]
171-
fn set_normalizes_to_hack_goal(&mut self, goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>) {
172+
fn set_normalizes_to_hack_goal(&mut self, goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) {
172173
assert!(
173174
self.nested_goals.normalizes_to_hack_goal.is_none(),
174175
"attempted to set the projection eq hack goal when one already exists"

0 commit comments

Comments
 (0)