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`
This commit is contained in:
commit
0b002eb906
35 changed files with 142 additions and 63 deletions
|
@ -82,6 +82,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
in_snapshot: self.in_snapshot.clone(),
|
||||
universe: self.universe.clone(),
|
||||
intercrate: self.intercrate,
|
||||
next_trait_solver: self.next_trait_solver,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,11 +109,11 @@ 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.next_trait_solver() => {
|
||||
bug!()
|
||||
}
|
||||
|
||||
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.tcx.trait_solver_next() => {
|
||||
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => {
|
||||
relation.register_type_relate_obligation(a, b);
|
||||
Ok(a)
|
||||
}
|
||||
|
@ -227,9 +227,20 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
return self.unify_const_variable(vid, a, relation.param_env());
|
||||
}
|
||||
(ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
|
||||
if self.tcx.features().generic_const_exprs || self.tcx.trait_solver_next() =>
|
||||
if self.tcx.features().generic_const_exprs || self.next_trait_solver() =>
|
||||
{
|
||||
relation.register_const_equate_obligation(a, b);
|
||||
let (a, b) = if relation.a_is_expected() { (a, b) } else { (b, a) };
|
||||
|
||||
relation.register_predicates([ty::Binder::dummy(if self.next_trait_solver() {
|
||||
ty::PredicateKind::AliasRelate(
|
||||
a.into(),
|
||||
b.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
)
|
||||
} else {
|
||||
ty::PredicateKind::ConstEquate(a, b)
|
||||
})]);
|
||||
|
||||
return Ok(b);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -453,19 +464,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>) {
|
||||
|
|
|
@ -105,7 +105,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
|
|||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
|
||||
&& def_id.is_local()
|
||||
&& !self.tcx().trait_solver_next() =>
|
||||
&& !self.fields.infcx.next_trait_solver() =>
|
||||
{
|
||||
self.fields.obligations.extend(
|
||||
infcx
|
||||
|
|
|
@ -113,7 +113,7 @@ where
|
|||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if this.define_opaque_types() == DefineOpaqueTypes::Yes
|
||||
&& def_id.is_local()
|
||||
&& !this.tcx().trait_solver_next() =>
|
||||
&& !this.infcx().next_trait_solver() =>
|
||||
{
|
||||
this.register_obligations(
|
||||
infcx
|
||||
|
|
|
@ -330,6 +330,8 @@ pub struct InferCtxt<'tcx> {
|
|||
/// there is no type that the user could *actually name* that
|
||||
/// would satisfy it. This avoids crippling inference, basically.
|
||||
pub intercrate: bool,
|
||||
|
||||
next_trait_solver: bool,
|
||||
}
|
||||
|
||||
/// See the `error_reporting` module for more details.
|
||||
|
@ -545,6 +547,9 @@ pub struct InferCtxtBuilder<'tcx> {
|
|||
skip_leak_check: bool,
|
||||
/// Whether we are in coherence mode.
|
||||
intercrate: bool,
|
||||
/// Whether we should use the new trait solver in the local inference context,
|
||||
/// which affects things like which solver is used in `predicate_may_hold`.
|
||||
next_trait_solver: bool,
|
||||
}
|
||||
|
||||
pub trait TyCtxtInferExt<'tcx> {
|
||||
|
@ -559,6 +564,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
|
|||
considering_regions: true,
|
||||
skip_leak_check: false,
|
||||
intercrate: false,
|
||||
next_trait_solver: self.next_trait_solver_globally(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -575,6 +581,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self {
|
||||
self.next_trait_solver = next_trait_solver;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn intercrate(mut self, intercrate: bool) -> Self {
|
||||
self.intercrate = intercrate;
|
||||
self
|
||||
|
@ -617,6 +628,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
considering_regions,
|
||||
skip_leak_check,
|
||||
intercrate,
|
||||
next_trait_solver,
|
||||
} = *self;
|
||||
InferCtxt {
|
||||
tcx,
|
||||
|
@ -634,6 +646,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
in_snapshot: Cell::new(false),
|
||||
universe: Cell::new(ty::UniverseIndex::ROOT),
|
||||
intercrate,
|
||||
next_trait_solver,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -670,6 +683,10 @@ pub struct CombinedSnapshot<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn next_trait_solver(&self) -> bool {
|
||||
self.next_trait_solver
|
||||
}
|
||||
|
||||
/// Creates a `TypeErrCtxt` for emitting various inference errors.
|
||||
/// During typeck, use `FnCtxt::err_ctxt` instead.
|
||||
pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
|
||||
|
|
|
@ -491,12 +491,12 @@ where
|
|||
(
|
||||
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
|
||||
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
|
||||
) if a_def_id == b_def_id || infcx.tcx.trait_solver_next() => {
|
||||
) if a_def_id == b_def_id || infcx.next_trait_solver() => {
|
||||
infcx.super_combine_tys(self, a, b).or_else(|err| {
|
||||
// This behavior is only there for the old solver, the new solver
|
||||
// shouldn't ever fail. Instead, it unconditionally emits an
|
||||
// alias-relate goal.
|
||||
assert!(!self.tcx().trait_solver_next());
|
||||
assert!(!self.infcx.next_trait_solver());
|
||||
self.tcx().sess.delay_span_bug(
|
||||
self.delegate.span(),
|
||||
"failure to relate an opaque to itself should result in an error later on",
|
||||
|
@ -506,7 +506,7 @@ where
|
|||
}
|
||||
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
|
||||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if def_id.is_local() && !self.tcx().trait_solver_next() =>
|
||||
if def_id.is_local() && !self.infcx.next_trait_solver() =>
|
||||
{
|
||||
self.relate_opaques(a, b)
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> InferOk<'tcx, T> {
|
||||
// We handle opaque types differently in the new solver.
|
||||
if self.tcx.trait_solver_next() {
|
||||
if self.next_trait_solver() {
|
||||
return InferOk { value, obligations: vec![] };
|
||||
}
|
||||
|
||||
|
@ -578,7 +578,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
) -> InferResult<'tcx, ()> {
|
||||
assert!(self.tcx.trait_solver_next());
|
||||
assert!(self.next_trait_solver());
|
||||
let origin = self
|
||||
.opaque_type_origin(opaque_type_key.def_id)
|
||||
.expect("should be called for defining usages only");
|
||||
|
@ -614,7 +614,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
ty::Alias(ty::Projection, projection_ty)
|
||||
if !projection_ty.has_escaping_bound_vars()
|
||||
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id)
|
||||
&& !tcx.trait_solver_next() =>
|
||||
&& !self.next_trait_solver() =>
|
||||
{
|
||||
self.infer_projection(
|
||||
param_env,
|
||||
|
|
|
@ -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.next_trait_solver() {
|
||||
// FIXME(-Ztrait-solver=next): Instead of branching here,
|
||||
// completely change the normalization routine with the new solver.
|
||||
//
|
||||
|
|
|
@ -132,7 +132,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
|||
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
|
||||
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
|
||||
&& def_id.is_local()
|
||||
&& !self.tcx().trait_solver_next() =>
|
||||
&& !self.fields.infcx.next_trait_solver() =>
|
||||
{
|
||||
self.fields.obligations.extend(
|
||||
infcx
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue