Skip to content

Commit 0b002eb

Browse files
authored
Rollup merge of #112122 - compiler-errors:next-coherence, r=lcnr
Add `-Ztrait-solver=next-coherence` Flag that conditionally uses the trait solver *only* during coherence, for more testing and/or eventual partial-migration onto the trait solver (in the medium- to long-term). * This still uses the selection context in some of the coherence methods I think, so it's not "complete". Putting this up for review and/or for further work in-tree. * I probably need to spend a bit more time making sure that we don't sneakily create any other infcx's during coherence that also need the new solver enabled. r? `@lcnr`
2 parents cbe429c + aabdeed commit 0b002eb

File tree

35 files changed

+142
-63
lines changed

35 files changed

+142
-63
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
285285
let infcx = self
286286
.tcx
287287
.infer_ctxt()
288-
.with_opaque_type_inference(if self.tcx.trait_solver_next() {
288+
.with_opaque_type_inference(if self.next_trait_solver() {
289289
DefiningAnchor::Bind(def_id)
290290
} else {
291291
DefiningAnchor::Bubble

compiler/rustc_borrowck/src/type_check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
188188

189189
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
190190
// predefined opaques in the typeck root.
191-
if infcx.tcx.trait_solver_next() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
191+
if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
192192
checker.register_predefined_opaques_in_new_solver();
193193
}
194194

compiler/rustc_hir_analysis/src/autoderef.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
7373
// NOTE: we may still need to normalize the built-in deref in case
7474
// we have some type like `&<Ty as Trait>::Assoc`, since users of
7575
// autoderef expect this type to have been structurally normalized.
76-
if self.infcx.tcx.trait_solver_next()
76+
if self.infcx.next_trait_solver()
7777
&& let ty::Alias(ty::Projection, _) = ty.kind()
7878
{
7979
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
@@ -161,8 +161,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
161161
&self,
162162
ty: Ty<'tcx>,
163163
) -> Option<(Ty<'tcx>, Vec<traits::PredicateObligation<'tcx>>)> {
164-
let tcx = self.infcx.tcx;
165-
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
164+
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.infcx);
166165

167166
let cause = traits::ObligationCause::misc(self.span, self.body_id);
168167
let normalized_ty = match self

compiler/rustc_hir_analysis/src/check/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1549,7 +1549,7 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
15491549
.with_opaque_type_inference(DefiningAnchor::Bind(def_id))
15501550
.build();
15511551

1552-
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
1552+
let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);
15531553
for (predicate, cause) in generator_interior_predicates {
15541554
let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate);
15551555
fulfillment_cx.register_predicate_obligation(&infcx, obligation);

compiler/rustc_hir_typeck/src/coercion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
156156
// In the new solver, lazy norm may allow us to shallowly equate
157157
// more types, but we emit possibly impossible-to-satisfy obligations.
158158
// Filter these cases out to make sure our coercion is more accurate.
159-
if self.tcx.trait_solver_next() {
159+
if self.next_trait_solver() {
160160
if let Ok(res) = &res {
161161
for obligation in &res.obligations {
162162
if !self.predicate_may_hold(&obligation) {

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1476,7 +1476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14761476
pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
14771477
let mut ty = self.resolve_vars_with_obligations(ty);
14781478

1479-
if self.tcx.trait_solver_next()
1479+
if self.next_trait_solver()
14801480
&& let ty::Alias(ty::Projection, _) = ty.kind()
14811481
{
14821482
match self

compiler/rustc_hir_typeck/src/inherited.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ impl<'tcx> Inherited<'tcx> {
8686

8787
Inherited {
8888
typeck_results,
89+
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(&infcx)),
8990
infcx,
90-
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
9191
locals: RefCell::new(Default::default()),
9292
deferred_sized_obligations: RefCell::new(Vec::new()),
9393
deferred_call_resolutions: RefCell::new(Default::default()),

compiler/rustc_hir_typeck/src/writeback.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
591591
.insert(opaque_type_key, hidden_type)
592592
&& last_opaque_ty.ty != hidden_type.ty
593593
{
594-
assert!(!self.tcx().trait_solver_next());
594+
assert!(!self.fcx.next_trait_solver());
595595
hidden_type
596596
.report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
597597
.stash(
@@ -812,7 +812,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
812812

813813
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
814814
match self.fcx.fully_resolve(t) {
815-
Ok(t) if self.fcx.tcx.trait_solver_next() => {
815+
Ok(t) if self.fcx.next_trait_solver() => {
816816
// We must normalize erasing regions here, since later lints
817817
// expect that types that show up in the typeck are fully
818818
// normalized.

compiler/rustc_infer/src/infer/at.rs

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ impl<'tcx> InferCtxt<'tcx> {
8282
in_snapshot: self.in_snapshot.clone(),
8383
universe: self.universe.clone(),
8484
intercrate: self.intercrate,
85+
next_trait_solver: self.next_trait_solver,
8586
}
8687
}
8788
}

compiler/rustc_infer/src/infer/combine.rs

+15-17
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ impl<'tcx> InferCtxt<'tcx> {
109109
| (
110110
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
111111
ty::Alias(AliasKind::Projection, _),
112-
) if self.tcx.trait_solver_next() => {
112+
) if self.next_trait_solver() => {
113113
bug!()
114114
}
115115

116-
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.tcx.trait_solver_next() => {
116+
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => {
117117
relation.register_type_relate_obligation(a, b);
118118
Ok(a)
119119
}
@@ -227,9 +227,20 @@ impl<'tcx> InferCtxt<'tcx> {
227227
return self.unify_const_variable(vid, a, relation.param_env());
228228
}
229229
(ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
230-
if self.tcx.features().generic_const_exprs || self.tcx.trait_solver_next() =>
230+
if self.tcx.features().generic_const_exprs || self.next_trait_solver() =>
231231
{
232-
relation.register_const_equate_obligation(a, b);
232+
let (a, b) = if relation.a_is_expected() { (a, b) } else { (b, a) };
233+
234+
relation.register_predicates([ty::Binder::dummy(if self.next_trait_solver() {
235+
ty::PredicateKind::AliasRelate(
236+
a.into(),
237+
b.into(),
238+
ty::AliasRelationDirection::Equate,
239+
)
240+
} else {
241+
ty::PredicateKind::ConstEquate(a, b)
242+
})]);
243+
233244
return Ok(b);
234245
}
235246
_ => {}
@@ -453,19 +464,6 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
453464
/// be used if control over the obligation causes is required.
454465
fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>);
455466

456-
/// Register an obligation that both constants must be equal to each other.
457-
///
458-
/// If they aren't equal then the relation doesn't hold.
459-
fn register_const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
460-
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
461-
462-
self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() {
463-
ty::PredicateKind::AliasRelate(a.into(), b.into(), ty::AliasRelationDirection::Equate)
464-
} else {
465-
ty::PredicateKind::ConstEquate(a, b)
466-
})]);
467-
}
468-
469467
/// Register an obligation that both types must be related to each other according to
470468
/// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`]
471469
fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {

compiler/rustc_infer/src/infer/equate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
105105
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
106106
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
107107
&& def_id.is_local()
108-
&& !self.tcx().trait_solver_next() =>
108+
&& !self.fields.infcx.next_trait_solver() =>
109109
{
110110
self.fields.obligations.extend(
111111
infcx

compiler/rustc_infer/src/infer/lattice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ where
113113
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
114114
if this.define_opaque_types() == DefineOpaqueTypes::Yes
115115
&& def_id.is_local()
116-
&& !this.tcx().trait_solver_next() =>
116+
&& !this.infcx().next_trait_solver() =>
117117
{
118118
this.register_obligations(
119119
infcx

compiler/rustc_infer/src/infer/mod.rs

+17
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ pub struct InferCtxt<'tcx> {
330330
/// there is no type that the user could *actually name* that
331331
/// would satisfy it. This avoids crippling inference, basically.
332332
pub intercrate: bool,
333+
334+
next_trait_solver: bool,
333335
}
334336

335337
/// See the `error_reporting` module for more details.
@@ -545,6 +547,9 @@ pub struct InferCtxtBuilder<'tcx> {
545547
skip_leak_check: bool,
546548
/// Whether we are in coherence mode.
547549
intercrate: bool,
550+
/// Whether we should use the new trait solver in the local inference context,
551+
/// which affects things like which solver is used in `predicate_may_hold`.
552+
next_trait_solver: bool,
548553
}
549554

550555
pub trait TyCtxtInferExt<'tcx> {
@@ -559,6 +564,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
559564
considering_regions: true,
560565
skip_leak_check: false,
561566
intercrate: false,
567+
next_trait_solver: self.next_trait_solver_globally(),
562568
}
563569
}
564570
}
@@ -575,6 +581,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
575581
self
576582
}
577583

584+
pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self {
585+
self.next_trait_solver = next_trait_solver;
586+
self
587+
}
588+
578589
pub fn intercrate(mut self, intercrate: bool) -> Self {
579590
self.intercrate = intercrate;
580591
self
@@ -617,6 +628,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
617628
considering_regions,
618629
skip_leak_check,
619630
intercrate,
631+
next_trait_solver,
620632
} = *self;
621633
InferCtxt {
622634
tcx,
@@ -634,6 +646,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
634646
in_snapshot: Cell::new(false),
635647
universe: Cell::new(ty::UniverseIndex::ROOT),
636648
intercrate,
649+
next_trait_solver,
637650
}
638651
}
639652
}
@@ -670,6 +683,10 @@ pub struct CombinedSnapshot<'tcx> {
670683
}
671684

672685
impl<'tcx> InferCtxt<'tcx> {
686+
pub fn next_trait_solver(&self) -> bool {
687+
self.next_trait_solver
688+
}
689+
673690
/// Creates a `TypeErrCtxt` for emitting various inference errors.
674691
/// During typeck, use `FnCtxt::err_ctxt` instead.
675692
pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {

compiler/rustc_infer/src/infer/nll_relate/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -491,12 +491,12 @@ where
491491
(
492492
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
493493
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
494-
) if a_def_id == b_def_id || infcx.tcx.trait_solver_next() => {
494+
) if a_def_id == b_def_id || infcx.next_trait_solver() => {
495495
infcx.super_combine_tys(self, a, b).or_else(|err| {
496496
// This behavior is only there for the old solver, the new solver
497497
// shouldn't ever fail. Instead, it unconditionally emits an
498498
// alias-relate goal.
499-
assert!(!self.tcx().trait_solver_next());
499+
assert!(!self.infcx.next_trait_solver());
500500
self.tcx().sess.delay_span_bug(
501501
self.delegate.span(),
502502
"failure to relate an opaque to itself should result in an error later on",
@@ -506,7 +506,7 @@ where
506506
}
507507
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
508508
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
509-
if def_id.is_local() && !self.tcx().trait_solver_next() =>
509+
if def_id.is_local() && !self.infcx.next_trait_solver() =>
510510
{
511511
self.relate_opaques(a, b)
512512
}

compiler/rustc_infer/src/infer/opaque_types.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl<'tcx> InferCtxt<'tcx> {
4949
param_env: ty::ParamEnv<'tcx>,
5050
) -> InferOk<'tcx, T> {
5151
// We handle opaque types differently in the new solver.
52-
if self.tcx.trait_solver_next() {
52+
if self.next_trait_solver() {
5353
return InferOk { value, obligations: vec![] };
5454
}
5555

@@ -578,7 +578,7 @@ impl<'tcx> InferCtxt<'tcx> {
578578
param_env: ty::ParamEnv<'tcx>,
579579
hidden_ty: Ty<'tcx>,
580580
) -> InferResult<'tcx, ()> {
581-
assert!(self.tcx.trait_solver_next());
581+
assert!(self.next_trait_solver());
582582
let origin = self
583583
.opaque_type_origin(opaque_type_key.def_id)
584584
.expect("should be called for defining usages only");
@@ -614,7 +614,7 @@ impl<'tcx> InferCtxt<'tcx> {
614614
ty::Alias(ty::Projection, projection_ty)
615615
if !projection_ty.has_escaping_bound_vars()
616616
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id)
617-
&& !tcx.trait_solver_next() =>
617+
&& !self.next_trait_solver() =>
618618
{
619619
self.infer_projection(
620620
param_env,

compiler/rustc_infer/src/infer/projection.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl<'tcx> InferCtxt<'tcx> {
2121
recursion_depth: usize,
2222
obligations: &mut Vec<PredicateObligation<'tcx>>,
2323
) -> Ty<'tcx> {
24-
if self.tcx.trait_solver_next() {
24+
if self.next_trait_solver() {
2525
// FIXME(-Ztrait-solver=next): Instead of branching here,
2626
// completely change the normalization routine with the new solver.
2727
//

compiler/rustc_infer/src/infer/sub.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
132132
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
133133
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
134134
&& def_id.is_local()
135-
&& !self.tcx().trait_solver_next() =>
135+
&& !self.fields.infcx.next_trait_solver() =>
136136
{
137137
self.fields.obligations.extend(
138138
infcx

compiler/rustc_middle/src/ty/context.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -2333,10 +2333,18 @@ impl<'tcx> TyCtxt<'tcx> {
23332333
self.opt_local_def_id_to_hir_id(local_def_id).unwrap()
23342334
}
23352335

2336-
pub fn trait_solver_next(self) -> bool {
2336+
pub fn next_trait_solver_globally(self) -> bool {
23372337
self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
23382338
}
23392339

2340+
pub fn next_trait_solver_in_coherence(self) -> bool {
2341+
matches!(
2342+
self.sess.opts.unstable_opts.trait_solver,
2343+
rustc_session::config::TraitSolver::Next
2344+
| rustc_session::config::TraitSolver::NextCoherence
2345+
)
2346+
}
2347+
23402348
pub fn lower_impl_trait_in_trait_to_assoc_ty(self) -> bool {
23412349
self.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
23422350
}

compiler/rustc_session/src/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,8 @@ pub enum TraitSolver {
610610
Chalk,
611611
/// Experimental trait solver in `rustc_trait_selection::solve`
612612
Next,
613+
/// Use the new trait solver during coherence
614+
NextCoherence,
613615
}
614616

615617
pub enum Input {

compiler/rustc_session/src/options.rs

+1
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,7 @@ mod parse {
986986
Some("classic") => *slot = TraitSolver::Classic,
987987
Some("chalk") => *slot = TraitSolver::Chalk,
988988
Some("next") => *slot = TraitSolver::Next,
989+
Some("next-coherence") => *slot = TraitSolver::NextCoherence,
989990
// default trait solver is subject to change..
990991
Some("default") => *slot = TraitSolver::Classic,
991992
_ => return false,

compiler/rustc_trait_selection/src/solve/eval_ctxt.rs

+1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
187187
let (ref infcx, input, var_values) = tcx
188188
.infer_ctxt()
189189
.intercrate(intercrate)
190+
.with_next_trait_solver(true)
190191
.with_opaque_type_inference(canonical_input.value.anchor)
191192
.build_with_canonical(DUMMY_SP, &canonical_input);
192193

compiler/rustc_trait_selection/src/traits/coherence.rs

+1
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ fn overlap<'tcx>(
182182
.with_opaque_type_inference(DefiningAnchor::Bubble)
183183
.skip_leak_check(skip_leak_check.is_yes())
184184
.intercrate(true)
185+
.with_next_trait_solver(tcx.next_trait_solver_in_coherence())
185186
.build();
186187
let selcx = &mut SelectionContext::new(&infcx);
187188
if track_ambiguity_causes.is_yes() {

0 commit comments

Comments
 (0)