Skip to content

Commit 21982a4

Browse files
committed
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 rust-lang/trait-system-refactor-initiative#1 r? `@compiler-errors`
2 parents d6fa38a + ac50f4b commit 21982a4

39 files changed

+310
-189
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -657,19 +657,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
657657
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
658658
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
659659
| ty::PredicateKind::ObjectSafe(..)
660+
| ty::PredicateKind::NormalizesTo(..)
660661
| ty::PredicateKind::AliasRelate(..)
661662
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
662663
| ty::PredicateKind::ConstEquate(..)
663-
// N.B., this predicate is created by breaking down a
664-
// `ClosureType: FnFoo()` predicate, where
665-
// `ClosureType` represents some `Closure`. It can't
666-
// possibly be referring to the current closure,
667-
// because we haven't produced the `Closure` for
668-
// this closure yet; this is exactly why the other
669-
// code is looking for a self type of an unresolved
670-
// inference variable.
671-
| ty::PredicateKind::Ambiguous
672-
=> None,
664+
| ty::PredicateKind::Ambiguous => None,
673665
},
674666
)
675667
}

compiler/rustc_infer/src/infer/combine.rs

+45-26
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
3535
use rustc_middle::ty::error::{ExpectedFound, TypeError};
3636
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
3737
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
38+
use rustc_middle::ty::{AliasRelationDirection, TyVar};
3839
use rustc_middle::ty::{IntType, UintType};
3940
use rustc_span::DUMMY_SP;
4041

@@ -459,7 +460,12 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
459460
ambient_variance,
460461
)?;
461462

462-
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
463+
// Constrain `b_vid` to the generalized type `b_ty`.
464+
if let &ty::Infer(TyVar(b_ty_vid)) = b_ty.kind() {
465+
self.infcx.inner.borrow_mut().type_variables().equate(b_vid, b_ty_vid);
466+
} else {
467+
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
468+
}
463469

464470
if needs_wf {
465471
self.obligations.push(Obligation::new(
@@ -484,31 +490,46 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
484490
// cyclic type. We instead delay the unification in case
485491
// the alias can be normalized to something which does not
486492
// mention `?0`.
487-
488-
// FIXME(-Ztrait-solver=next): replace this with `AliasRelate`
489-
let &ty::Alias(kind, data) = a_ty.kind() else {
490-
bug!("generalization should only result in infer vars for aliases");
491-
};
492-
if !self.infcx.next_trait_solver() {
493-
// The old solver only accepts projection predicates for associated types.
494-
match kind {
495-
ty::AliasKind::Projection => {}
496-
ty::AliasKind::Inherent | ty::AliasKind::Weak | ty::AliasKind::Opaque => {
497-
return Err(TypeError::CyclicTy(a_ty));
493+
if self.infcx.next_trait_solver() {
494+
let (lhs, rhs, direction) = match ambient_variance {
495+
ty::Variance::Invariant => {
496+
(a_ty.into(), b_ty.into(), AliasRelationDirection::Equate)
497+
}
498+
ty::Variance::Covariant => {
499+
(a_ty.into(), b_ty.into(), AliasRelationDirection::Subtype)
500+
}
501+
ty::Variance::Contravariant => {
502+
(b_ty.into(), a_ty.into(), AliasRelationDirection::Subtype)
503+
}
504+
ty::Variance::Bivariant => unreachable!("bivariant generalization"),
505+
};
506+
self.obligations.push(Obligation::new(
507+
self.tcx(),
508+
self.trace.cause.clone(),
509+
self.param_env,
510+
ty::PredicateKind::AliasRelate(lhs, rhs, direction),
511+
));
512+
} else {
513+
match a_ty.kind() {
514+
&ty::Alias(ty::AliasKind::Projection, data) => {
515+
// FIXME: This does not handle subtyping correctly, we could
516+
// instead create a new inference variable for `a_ty`, emitting
517+
// `Projection(a_ty, a_infer)` and `a_infer <: b_ty`.
518+
self.obligations.push(Obligation::new(
519+
self.tcx(),
520+
self.trace.cause.clone(),
521+
self.param_env,
522+
ty::ProjectionPredicate { projection_ty: data, term: b_ty.into() },
523+
))
498524
}
525+
// The old solver only accepts projection predicates for associated types.
526+
ty::Alias(
527+
ty::AliasKind::Inherent | ty::AliasKind::Weak | ty::AliasKind::Opaque,
528+
_,
529+
) => return Err(TypeError::CyclicTy(a_ty)),
530+
_ => bug!("generalizated `{a_ty:?} to infer, not an alias"),
499531
}
500532
}
501-
502-
// FIXME: This does not handle subtyping correctly, we should switch to
503-
// alias-relate in the new solver and could instead create a new inference
504-
// variable for `a_ty`, emitting `Projection(a_ty, a_infer)` and
505-
// `a_infer <: b_ty`.
506-
self.obligations.push(Obligation::new(
507-
self.tcx(),
508-
self.trace.cause.clone(),
509-
self.param_env,
510-
ty::ProjectionPredicate { projection_ty: data, term: b_ty.into() },
511-
))
512533
} else {
513534
match ambient_variance {
514535
ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
@@ -519,9 +540,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
519540
a_ty,
520541
b_ty,
521542
),
522-
ty::Variance::Bivariant => {
523-
unreachable!("no code should be generalizing bivariantly (currently)")
524-
}
543+
ty::Variance::Bivariant => unreachable!("bivariant generalization"),
525544
}?;
526545
}
527546

compiler/rustc_infer/src/infer/type_variable.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
229229
/// Precondition: `vid` must not have been previously instantiated.
230230
pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) {
231231
let vid = self.root_var(vid);
232+
debug_assert!(!ty.is_ty_var(), "instantiating ty var with var: {vid:?} {ty:?}");
232233
debug_assert!(self.probe(vid).is_unknown());
233234
debug_assert!(
234235
self.eq_relations().probe_value(vid).is_unknown(),
235-
"instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}",
236-
vid,
237-
ty,
236+
"instantiating type variable `{vid:?}` twice: new-value = {ty:?}, old-value={:?}",
238237
self.eq_relations().probe_value(vid)
239238
);
240239
self.eq_relations().union_value(vid, TypeVariableValue::Known { value: ty });

compiler/rustc_infer/src/traits/util.rs

+26-44
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,14 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
261261
fn elaborate(&mut self, elaboratable: &O) {
262262
let tcx = self.visited.tcx;
263263

264-
let bound_predicate = elaboratable.predicate().kind();
265-
match bound_predicate.skip_binder() {
266-
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
264+
// We only elaborate clauses.
265+
let Some(clause) = elaboratable.predicate().as_clause() else {
266+
return;
267+
};
268+
269+
let bound_clause = clause.kind();
270+
match bound_clause.skip_binder() {
271+
ty::ClauseKind::Trait(data) => {
267272
// Negative trait bounds do not imply any supertrait bounds
268273
if data.polarity == ty::ImplPolarity::Negative {
269274
return;
@@ -280,49 +285,16 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
280285
let obligations =
281286
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
282287
elaboratable.child_with_derived_cause(
283-
clause.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
288+
clause.subst_supertrait(tcx, &bound_clause.rebind(data.trait_ref)),
284289
span,
285-
bound_predicate.rebind(data),
290+
bound_clause.rebind(data),
286291
index,
287292
)
288293
});
289294
debug!(?data, ?obligations, "super_predicates");
290295
self.extend_deduped(obligations);
291296
}
292-
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) => {
293-
// Currently, we do not elaborate WF predicates,
294-
// although we easily could.
295-
}
296-
ty::PredicateKind::ObjectSafe(..) => {
297-
// Currently, we do not elaborate object-safe
298-
// predicates.
299-
}
300-
ty::PredicateKind::Subtype(..) => {
301-
// Currently, we do not "elaborate" predicates like `X <: Y`,
302-
// though conceivably we might.
303-
}
304-
ty::PredicateKind::Coerce(..) => {
305-
// Currently, we do not "elaborate" predicates like `X -> Y`,
306-
// though conceivably we might.
307-
}
308-
ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => {
309-
// Nothing to elaborate in a projection predicate.
310-
}
311-
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
312-
// Currently, we do not elaborate const-evaluatable
313-
// predicates.
314-
}
315-
ty::PredicateKind::ConstEquate(..) => {
316-
// Currently, we do not elaborate const-equate
317-
// predicates.
318-
}
319-
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {
320-
// Nothing to elaborate from `'a: 'b`.
321-
}
322-
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
323-
ty_max,
324-
r_min,
325-
))) => {
297+
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
326298
// We know that `T: 'a` for some type `T`. We can
327299
// often elaborate this. For example, if we know that
328300
// `[U]: 'a`, that implies that `U: 'a`. Similarly, if
@@ -385,15 +357,25 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
385357
}
386358
})
387359
.map(|clause| {
388-
elaboratable.child(bound_predicate.rebind(clause).to_predicate(tcx))
360+
elaboratable.child(bound_clause.rebind(clause).to_predicate(tcx))
389361
}),
390362
);
391363
}
392-
ty::PredicateKind::Ambiguous => {}
393-
ty::PredicateKind::AliasRelate(..) => {
394-
// No
364+
ty::ClauseKind::RegionOutlives(..) => {
365+
// Nothing to elaborate from `'a: 'b`.
366+
}
367+
ty::ClauseKind::WellFormed(..) => {
368+
// Currently, we do not elaborate WF predicates,
369+
// although we easily could.
370+
}
371+
ty::ClauseKind::Projection(..) => {
372+
// Nothing to elaborate in a projection predicate.
373+
}
374+
ty::ClauseKind::ConstEvaluatable(..) => {
375+
// Currently, we do not elaborate const-evaluatable
376+
// predicates.
395377
}
396-
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => {
378+
ty::ClauseKind::ConstArgHasType(..) => {
397379
// Nothing to elaborate
398380
}
399381
}

compiler/rustc_middle/src/ty/context.rs

+1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
121121
type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>;
122122
type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>;
123123
type ProjectionPredicate = ty::ProjectionPredicate<'tcx>;
124+
type NormalizesTo = ty::NormalizesTo<'tcx>;
124125
type SubtypePredicate = ty::SubtypePredicate<'tcx>;
125126
type CoercePredicate = ty::CoercePredicate<'tcx>;
126127
type ClosureKind = ty::ClosureKind;

compiler/rustc_middle/src/ty/flags.rs

+4
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ impl FlagComputation {
272272
self.add_const(found);
273273
}
274274
ty::PredicateKind::Ambiguous => {}
275+
ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => {
276+
self.add_alias_ty(alias);
277+
self.add_term(term);
278+
}
275279
ty::PredicateKind::AliasRelate(t1, t2, _) => {
276280
self.add_term(t1);
277281
self.add_term(t2);

compiler/rustc_middle/src/ty/mod.rs

+39
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,10 @@ impl<'tcx> Predicate<'tcx> {
553553
pub fn allow_normalization(self) -> bool {
554554
match self.kind().skip_binder() {
555555
PredicateKind::Clause(ClauseKind::WellFormed(_)) => false,
556+
// `NormalizesTo` is only used in the new solver, so this shouldn't
557+
// matter. Normalizing `term` would be 'wrong' however, as it changes whether
558+
// `normalizes-to(<T as Trait>::Assoc, <T as Trait>::Assoc)` holds.
559+
PredicateKind::NormalizesTo(..) => false,
556560
PredicateKind::Clause(ClauseKind::Trait(_))
557561
| PredicateKind::Clause(ClauseKind::RegionOutlives(_))
558562
| PredicateKind::Clause(ClauseKind::TypeOutlives(_))
@@ -1093,6 +1097,33 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
10931097
}
10941098
}
10951099

1100+
/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be
1101+
/// proven by actually normalizing `alias`.
1102+
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1103+
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
1104+
pub struct NormalizesTo<'tcx> {
1105+
pub alias: AliasTy<'tcx>,
1106+
pub term: Term<'tcx>,
1107+
}
1108+
1109+
impl<'tcx> NormalizesTo<'tcx> {
1110+
pub fn self_ty(self) -> Ty<'tcx> {
1111+
self.alias.self_ty()
1112+
}
1113+
1114+
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> {
1115+
Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
1116+
}
1117+
1118+
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
1119+
self.alias.trait_def_id(tcx)
1120+
}
1121+
1122+
pub fn def_id(self) -> DefId {
1123+
self.alias.def_id
1124+
}
1125+
}
1126+
10961127
pub trait ToPolyTraitRef<'tcx> {
10971128
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
10981129
}
@@ -1274,13 +1305,20 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
12741305
}
12751306
}
12761307

1308+
impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> {
1309+
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
1310+
PredicateKind::NormalizesTo(self).to_predicate(tcx)
1311+
}
1312+
}
1313+
12771314
impl<'tcx> Predicate<'tcx> {
12781315
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
12791316
let predicate = self.kind();
12801317
match predicate.skip_binder() {
12811318
PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
12821319
PredicateKind::Clause(ClauseKind::Projection(..))
12831320
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
1321+
| PredicateKind::NormalizesTo(..)
12841322
| PredicateKind::AliasRelate(..)
12851323
| PredicateKind::Subtype(..)
12861324
| PredicateKind::Coerce(..)
@@ -1300,6 +1338,7 @@ impl<'tcx> Predicate<'tcx> {
13001338
PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
13011339
PredicateKind::Clause(ClauseKind::Trait(..))
13021340
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
1341+
| PredicateKind::NormalizesTo(..)
13031342
| PredicateKind::AliasRelate(..)
13041343
| PredicateKind::Subtype(..)
13051344
| PredicateKind::Coerce(..)

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

+7
Original file line numberDiff line numberDiff line change
@@ -2814,6 +2814,7 @@ define_print! {
28142814
p!("the constant `", print(c1), "` equals `", print(c2), "`")
28152815
}
28162816
ty::PredicateKind::Ambiguous => p!("ambiguous"),
2817+
ty::PredicateKind::NormalizesTo(data) => p!(print(data)),
28172818
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
28182819
}
28192820
}
@@ -2945,6 +2946,12 @@ define_print_and_forward_display! {
29452946
p!(print(self.term))
29462947
}
29472948

2949+
ty::NormalizesTo<'tcx> {
2950+
p!(print(self.alias), " normalizes-to ");
2951+
cx.reset_type_limit();
2952+
p!(print(self.term))
2953+
}
2954+
29482955
ty::Term<'tcx> {
29492956
match self.unpack() {
29502957
ty::TermKind::Ty(ty) => p!(print(ty)),

compiler/rustc_middle/src/ty/structural_impls.rs

+6
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,12 @@ impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
173173
}
174174
}
175175

176+
impl<'tcx> fmt::Debug for ty::NormalizesTo<'tcx> {
177+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178+
write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
179+
}
180+
}
181+
176182
impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
177183
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178184
write!(f, "{:?}", self.kind())

compiler/rustc_smir/src/rustc_smir/convert/ty.rs

+1
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
601601
stable_mir::ty::PredicateKind::ConstEquate(a.stable(tables), b.stable(tables))
602602
}
603603
PredicateKind::Ambiguous => stable_mir::ty::PredicateKind::Ambiguous,
604+
PredicateKind::NormalizesTo(_pred) => unimplemented!(),
604605
PredicateKind::AliasRelate(a, b, alias_relation_direction) => {
605606
stable_mir::ty::PredicateKind::AliasRelate(
606607
a.unpack().stable(tables),

compiler/rustc_trait_selection/src/solve/alias_relate.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
9292
self.add_goal(Goal::new(
9393
self.tcx(),
9494
param_env,
95-
ty::ProjectionPredicate { projection_ty: alias, term },
95+
ty::NormalizesTo { alias, term },
9696
));
9797
self.try_evaluate_added_goals()?;
9898
Ok(Some(self.resolve_vars_if_possible(term)))
@@ -109,11 +109,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
109109
opaque: ty::AliasTy<'tcx>,
110110
term: ty::Term<'tcx>,
111111
) -> QueryResult<'tcx> {
112-
self.add_goal(Goal::new(
113-
self.tcx(),
114-
param_env,
115-
ty::ProjectionPredicate { projection_ty: opaque, term },
116-
));
112+
self.add_goal(Goal::new(self.tcx(), param_env, ty::NormalizesTo { alias: opaque, term }));
117113
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
118114
}
119115

0 commit comments

Comments
 (0)