Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ impl<'tcx> InferCtxt<'tcx> {
universe: self.universe.clone(),
intercrate: self.intercrate,
inside_canonicalization_ctxt: Cell::new(self.inside_canonicalization_ctxt()),
use_new_solver: self.use_new_solver,
}
}
}
Expand Down
43 changes: 26 additions & 17 deletions compiler/rustc_infer/src/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,12 @@ impl<'tcx> InferCtxt<'tcx> {
| (
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
ty::Alias(AliasKind::Projection, _),
) if self.tcx.trait_solver_next() => {
) if self.use_new_solver => {
bug!()
}

(_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _)
if self.tcx.trait_solver_next() =>
if self.use_new_solver =>
{
relation.register_type_relate_obligation(a, b);
Ok(a)
Expand Down Expand Up @@ -242,15 +242,37 @@ impl<'tcx> InferCtxt<'tcx> {
// FIXME(#59490): Need to remove the leak check to accommodate
// escaping bound variables here.
if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
relation.register_const_equate_obligation(a, b);
let (a, b) = if relation.a_is_expected() { (a, b) } else { (b, a) };

// FIXME(deferred_projection_equality): What do here...
relation.register_predicates([ty::Binder::dummy(if self.use_new_solver {
ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
ty::AliasRelationDirection::Equate,
)
} else {
ty::PredicateKind::ConstEquate(a, b)
})]);
}
return Ok(b);
}
(_, ty::ConstKind::Unevaluated(..)) if self.tcx.lazy_normalization() => {
// FIXME(#59490): Need to remove the leak check to accommodate
// escaping bound variables here.
if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
relation.register_const_equate_obligation(a, b);
let (a, b) = if relation.a_is_expected() { (a, b) } else { (b, a) };

// FIXME(deferred_projection_equality): What do here...
relation.register_predicates([ty::Binder::dummy(if self.use_new_solver {
ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
ty::AliasRelationDirection::Equate,
)
} else {
ty::PredicateKind::ConstEquate(a, b)
})]);
}
return Ok(a);
}
Expand Down Expand Up @@ -835,19 +857,6 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
/// be used if control over the obligation causes is required.
fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>);

/// Register an obligation that both constants must be equal to each other.
///
/// If they aren't equal then the relation doesn't hold.
fn register_const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };

self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() {
ty::PredicateKind::AliasRelate(a.into(), b.into(), ty::AliasRelationDirection::Equate)
} else {
ty::PredicateKind::ConstEquate(a, b)
})]);
}

/// Register an obligation that both types must be related to each other according to
/// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`]
fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
Expand Down
19 changes: 18 additions & 1 deletion compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ pub struct InferCtxt<'tcx> {
/// that we only collect region information for `BorrowckInferCtxt::reg_var_to_origin`
/// inside non-canonicalization contexts.
inside_canonicalization_ctxt: Cell<bool>,

pub use_new_solver: bool,
}

/// See the `error_reporting` module for more details.
Expand Down Expand Up @@ -561,6 +563,8 @@ pub struct InferCtxtBuilder<'tcx> {
considering_regions: bool,
/// Whether we are in coherence mode.
intercrate: bool,
/// Whether to use the new trait solver for calls to `predicate_may_hold`, etc.
use_new_solver: bool,
}

pub trait TyCtxtInferExt<'tcx> {
Expand All @@ -574,6 +578,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
defining_use_anchor: DefiningAnchor::Error,
considering_regions: true,
intercrate: false,
use_new_solver: self.trait_solver_next(),
}
}
}
Expand All @@ -590,6 +595,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
self
}

pub fn with_new_solver(mut self) -> Self {
self.use_new_solver = true;
self
}

pub fn intercrate(mut self, intercrate: bool) -> Self {
self.intercrate = intercrate;
self
Expand Down Expand Up @@ -621,7 +631,13 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
}

pub fn build(&mut self) -> InferCtxt<'tcx> {
let InferCtxtBuilder { tcx, defining_use_anchor, considering_regions, intercrate } = *self;
let InferCtxtBuilder {
tcx,
defining_use_anchor,
considering_regions,
intercrate,
use_new_solver,
} = *self;
InferCtxt {
tcx,
defining_use_anchor,
Expand All @@ -639,6 +655,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
universe: Cell::new(ty::UniverseIndex::ROOT),
intercrate,
inside_canonicalization_ctxt: Cell::new(false),
use_new_solver,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl<'tcx> InferCtxt<'tcx> {
recursion_depth: usize,
obligations: &mut Vec<PredicateObligation<'tcx>>,
) -> Ty<'tcx> {
if self.tcx.trait_solver_next() {
if self.use_new_solver {
// FIXME(-Ztrait-solver=next): Instead of branching here,
// completely change the normalization routine with the new solver.
//
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
};
let (ref infcx, goal, var_values) = tcx
.infer_ctxt()
.with_new_solver()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be cool to land this as yet another -Z flag, e.g. -Ztrait-solver=next-coherence or whatever

.intercrate(intercrate)
.build_with_canonical(DUMMY_SP, &canonical_goal);
let mut ecx = EvalCtxt {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_trait_selection/src/solve/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
}

fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
assert!(infcx.use_new_solver);

let mut errors = Vec::new();
for i in 0.. {
if !infcx.tcx.recursion_limit().value_within_limit(i) {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
}

fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
assert!(!infcx.use_new_solver);

if !self.usable_in_snapshot {
assert!(!infcx.is_in_snapshot());
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ pub fn overlapping_impls(

let infcx = tcx
.infer_ctxt()
.with_new_solver()
.with_opaque_type_inference(DefiningAnchor::Bubble)
.intercrate(true)
.build();
Expand All @@ -113,6 +114,7 @@ pub fn overlapping_impls(
// diagnostics. (These take time and can lead to false errors.)
let infcx = tcx
.infer_ctxt()
.with_new_solver()
.with_opaque_type_inference(DefiningAnchor::Bubble)
.intercrate(true)
.build();
Expand Down Expand Up @@ -299,7 +301,7 @@ fn negative_impl(tcx: TyCtxt<'_>, impl1_def_id: DefId, impl2_def_id: DefId) -> b
debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);

// Create an infcx, taking the predicates of impl1 as assumptions:
let infcx = tcx.infer_ctxt().build();
let infcx = tcx.infer_ctxt().with_new_solver().build();
// create a parameter environment corresponding to a (placeholder) instantiation of impl1
let impl_env = tcx.param_env(impl1_def_id);
let subject1 = match traits::fully_normalize(
Expand Down
14 changes: 12 additions & 2 deletions compiler/rustc_trait_selection/src/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,21 @@ pub struct ObligationCtxt<'a, 'tcx> {

impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new(infcx.tcx)) }
let engine = if infcx.use_new_solver {
Box::new(crate::solve::FulfillmentCtxt::new())
} else {
<dyn TraitEngine<'_>>::new(infcx.tcx)
};
Self { infcx, engine: RefCell::new(engine) }
}

pub fn new_in_snapshot(infcx: &'a InferCtxt<'tcx>) -> Self {
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new_in_snapshot(infcx.tcx)) }
let engine = if infcx.use_new_solver {
Box::new(crate::solve::FulfillmentCtxt::new())
} else {
<dyn TraitEngine<'_>>::new_in_snapshot(infcx.tcx)
};
Self { infcx, engine: RefCell::new(engine) }
}

pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
}

fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
assert!(!infcx.use_new_solver);
let selcx = SelectionContext::new(infcx);
self.select(selcx)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
_ => obligation.param_env.without_const(),
};

if self.tcx.trait_solver_next() {
if self.use_new_solver {
self.probe(|snapshot| {
let mut fulfill_cx = crate::solve::FulfillmentCtxt::new();
fulfill_cx.register_predicate_obligation(self, obligation.clone());
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
self.evaluation_probe(|this| {
if this.tcx().trait_solver_next() {
if this.infcx.use_new_solver {
this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])
} else {
this.evaluate_predicate_recursively(
Expand Down Expand Up @@ -583,7 +583,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
where
I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
{
if self.tcx().trait_solver_next() {
if self.infcx.use_new_solver {
self.evaluate_predicates_recursively_in_new_solver(predicates)
} else {
let mut result = EvaluatedToOk;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity();

// Create an infcx, taking the predicates of impl1 as assumptions:
let infcx = tcx.infer_ctxt().build();
let infcx = tcx.infer_ctxt().with_new_solver().build();
let impl1_trait_ref =
match traits::fully_normalize(&infcx, ObligationCause::dummy(), penv, impl1_trait_ref) {
Ok(impl1_trait_ref) => impl1_trait_ref,
Expand Down