1
Fork 0

New trait solver is a property of inference context

This commit is contained in:
Michael Goulet 2023-05-31 01:02:32 +00:00
parent 3572d7451d
commit e0acff796a
23 changed files with 61 additions and 42 deletions

View file

@ -285,7 +285,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
let infcx = self let infcx = self
.tcx .tcx
.infer_ctxt() .infer_ctxt()
.with_opaque_type_inference(if self.tcx.trait_solver_next() { .with_opaque_type_inference(if self.next_trait_solver() {
DefiningAnchor::Bind(def_id) DefiningAnchor::Bind(def_id)
} else { } else {
DefiningAnchor::Bubble DefiningAnchor::Bubble

View file

@ -188,7 +188,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering // FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
// predefined opaques in the typeck root. // predefined opaques in the typeck root.
if infcx.tcx.trait_solver_next() && !infcx.tcx.is_typeck_child(body.source.def_id()) { if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
checker.register_predefined_opaques_in_new_solver(); checker.register_predefined_opaques_in_new_solver();
} }

View file

@ -73,7 +73,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
// NOTE: we may still need to normalize the built-in deref in case // NOTE: we may still need to normalize the built-in deref in case
// we have some type like `&<Ty as Trait>::Assoc`, since users of // we have some type like `&<Ty as Trait>::Assoc`, since users of
// autoderef expect this type to have been structurally normalized. // autoderef expect this type to have been structurally normalized.
if self.infcx.tcx.trait_solver_next() if self.infcx.next_trait_solver()
&& let ty::Alias(ty::Projection, _) = ty.kind() && let ty::Alias(ty::Projection, _) = ty.kind()
{ {
let (normalized_ty, obligations) = self.structurally_normalize(ty)?; let (normalized_ty, obligations) = self.structurally_normalize(ty)?;

View file

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

View file

@ -1476,7 +1476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
let mut ty = self.resolve_vars_with_obligations(ty); let mut ty = self.resolve_vars_with_obligations(ty);
if self.tcx.trait_solver_next() if self.next_trait_solver()
&& let ty::Alias(ty::Projection, _) = ty.kind() && let ty::Alias(ty::Projection, _) = ty.kind()
{ {
match self match self

View file

@ -591,7 +591,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
.insert(opaque_type_key, hidden_type) .insert(opaque_type_key, hidden_type)
&& last_opaque_ty.ty != hidden_type.ty && last_opaque_ty.ty != hidden_type.ty
{ {
assert!(!self.tcx().trait_solver_next()); assert!(!self.fcx.next_trait_solver());
hidden_type hidden_type
.report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx()) .report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
.stash( .stash(
@ -812,7 +812,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match self.fcx.fully_resolve(t) { match self.fcx.fully_resolve(t) {
Ok(t) if self.fcx.tcx.trait_solver_next() => { Ok(t) if self.fcx.next_trait_solver() => {
// We must normalize erasing regions here, since later lints // We must normalize erasing regions here, since later lints
// expect that types that show up in the typeck are fully // expect that types that show up in the typeck are fully
// normalized. // normalized.

View file

@ -82,6 +82,7 @@ impl<'tcx> InferCtxt<'tcx> {
in_snapshot: self.in_snapshot.clone(), in_snapshot: self.in_snapshot.clone(),
universe: self.universe.clone(), universe: self.universe.clone(),
intercrate: self.intercrate, intercrate: self.intercrate,
next_trait_solver: self.next_trait_solver,
} }
} }
} }

View file

@ -109,11 +109,11 @@ impl<'tcx> InferCtxt<'tcx> {
| ( | (
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
ty::Alias(AliasKind::Projection, _), ty::Alias(AliasKind::Projection, _),
) if self.tcx.trait_solver_next() => { ) if self.next_trait_solver() => {
bug!() 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); relation.register_type_relate_obligation(a, b);
Ok(a) Ok(a)
} }
@ -227,9 +227,22 @@ impl<'tcx> InferCtxt<'tcx> {
return self.unify_const_variable(vid, a, relation.param_env()); return self.unify_const_variable(vid, a, relation.param_env());
} }
(ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) (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); return Ok(b);
} }
_ => {} _ => {}
@ -453,19 +466,6 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
/// be used if control over the obligation causes is required. /// be used if control over the obligation causes is required.
fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>); 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 /// Register an obligation that both types must be related to each other according to
/// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`] /// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`]
fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {

View file

@ -105,7 +105,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
&& def_id.is_local() && def_id.is_local()
&& !self.tcx().trait_solver_next() => && !self.fields.infcx.next_trait_solver() =>
{ {
self.fields.obligations.extend( self.fields.obligations.extend(
infcx infcx

View file

@ -113,7 +113,7 @@ where
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
if this.define_opaque_types() == DefineOpaqueTypes::Yes if this.define_opaque_types() == DefineOpaqueTypes::Yes
&& def_id.is_local() && def_id.is_local()
&& !this.tcx().trait_solver_next() => && !this.infcx().next_trait_solver() =>
{ {
this.register_obligations( this.register_obligations(
infcx infcx

View file

@ -330,6 +330,8 @@ pub struct InferCtxt<'tcx> {
/// there is no type that the user could *actually name* that /// there is no type that the user could *actually name* that
/// would satisfy it. This avoids crippling inference, basically. /// would satisfy it. This avoids crippling inference, basically.
pub intercrate: bool, pub intercrate: bool,
next_trait_solver: bool,
} }
/// See the `error_reporting` module for more details. /// See the `error_reporting` module for more details.
@ -545,6 +547,9 @@ pub struct InferCtxtBuilder<'tcx> {
skip_leak_check: bool, skip_leak_check: bool,
/// Whether we are in coherence mode. /// Whether we are in coherence mode.
intercrate: bool, 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> { pub trait TyCtxtInferExt<'tcx> {
@ -559,6 +564,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
considering_regions: true, considering_regions: true,
skip_leak_check: false, skip_leak_check: false,
intercrate: false, intercrate: false,
next_trait_solver: self.next_trait_solver_globally(),
} }
} }
} }
@ -575,6 +581,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
self 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 { pub fn intercrate(mut self, intercrate: bool) -> Self {
self.intercrate = intercrate; self.intercrate = intercrate;
self self
@ -617,6 +628,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
considering_regions, considering_regions,
skip_leak_check, skip_leak_check,
intercrate, intercrate,
next_trait_solver,
} = *self; } = *self;
InferCtxt { InferCtxt {
tcx, tcx,
@ -634,6 +646,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
in_snapshot: Cell::new(false), in_snapshot: Cell::new(false),
universe: Cell::new(ty::UniverseIndex::ROOT), universe: Cell::new(ty::UniverseIndex::ROOT),
intercrate, intercrate,
next_trait_solver,
} }
} }
} }
@ -670,6 +683,10 @@ pub struct CombinedSnapshot<'tcx> {
} }
impl<'tcx> InferCtxt<'tcx> { impl<'tcx> InferCtxt<'tcx> {
pub fn next_trait_solver(&self) -> bool {
self.next_trait_solver
}
/// Creates a `TypeErrCtxt` for emitting various inference errors. /// Creates a `TypeErrCtxt` for emitting various inference errors.
/// During typeck, use `FnCtxt::err_ctxt` instead. /// During typeck, use `FnCtxt::err_ctxt` instead.
pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> { pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {

View file

@ -491,12 +491,12 @@ where
( (
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_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| { infcx.super_combine_tys(self, a, b).or_else(|err| {
// This behavior is only there for the old solver, the new solver // This behavior is only there for the old solver, the new solver
// shouldn't ever fail. Instead, it unconditionally emits an // shouldn't ever fail. Instead, it unconditionally emits an
// alias-relate goal. // alias-relate goal.
assert!(!self.tcx().trait_solver_next()); assert!(!self.infcx.next_trait_solver());
self.tcx().sess.delay_span_bug( self.tcx().sess.delay_span_bug(
self.delegate.span(), self.delegate.span(),
"failure to relate an opaque to itself should result in an error later on", "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, .. }), _)
| (_, &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) self.relate_opaques(a, b)
} }

View file

@ -49,7 +49,7 @@ impl<'tcx> InferCtxt<'tcx> {
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> InferOk<'tcx, T> { ) -> InferOk<'tcx, T> {
// We handle opaque types differently in the new solver. // 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![] }; return InferOk { value, obligations: vec![] };
} }
@ -578,7 +578,7 @@ impl<'tcx> InferCtxt<'tcx> {
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
hidden_ty: Ty<'tcx>, hidden_ty: Ty<'tcx>,
) -> InferResult<'tcx, ()> { ) -> InferResult<'tcx, ()> {
assert!(self.tcx.trait_solver_next()); assert!(self.next_trait_solver());
let origin = self let origin = self
.opaque_type_origin(opaque_type_key.def_id) .opaque_type_origin(opaque_type_key.def_id)
.expect("should be called for defining usages only"); .expect("should be called for defining usages only");
@ -614,7 +614,7 @@ impl<'tcx> InferCtxt<'tcx> {
ty::Alias(ty::Projection, projection_ty) ty::Alias(ty::Projection, projection_ty)
if !projection_ty.has_escaping_bound_vars() if !projection_ty.has_escaping_bound_vars()
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id) && !tcx.is_impl_trait_in_trait(projection_ty.def_id)
&& !tcx.trait_solver_next() => && !self.next_trait_solver() =>
{ {
self.infer_projection( self.infer_projection(
param_env, param_env,

View file

@ -21,7 +21,7 @@ impl<'tcx> InferCtxt<'tcx> {
recursion_depth: usize, recursion_depth: usize,
obligations: &mut Vec<PredicateObligation<'tcx>>, obligations: &mut Vec<PredicateObligation<'tcx>>,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
if self.tcx.trait_solver_next() { if self.next_trait_solver() {
// FIXME(-Ztrait-solver=next): Instead of branching here, // FIXME(-Ztrait-solver=next): Instead of branching here,
// completely change the normalization routine with the new solver. // completely change the normalization routine with the new solver.
// //

View file

@ -132,7 +132,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
&& def_id.is_local() && def_id.is_local()
&& !self.tcx().trait_solver_next() => && !self.fields.infcx.next_trait_solver() =>
{ {
self.fields.obligations.extend( self.fields.obligations.extend(
infcx infcx

View file

@ -2333,7 +2333,7 @@ impl<'tcx> TyCtxt<'tcx> {
self.opt_local_def_id_to_hir_id(local_def_id).unwrap() self.opt_local_def_id_to_hir_id(local_def_id).unwrap()
} }
pub fn trait_solver_next(self) -> bool { pub fn next_trait_solver_globally(self) -> bool {
self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
} }

View file

@ -187,6 +187,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
let (ref infcx, input, var_values) = tcx let (ref infcx, input, var_values) = tcx
.infer_ctxt() .infer_ctxt()
.intercrate(intercrate) .intercrate(intercrate)
.with_next_trait_solver(true)
.with_opaque_type_inference(canonical_input.value.anchor) .with_opaque_type_inference(canonical_input.value.anchor)
.build_with_canonical(DUMMY_SP, &canonical_input); .build_with_canonical(DUMMY_SP, &canonical_input);

View file

@ -1047,7 +1047,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// (which may fail). // (which may fail).
span_bug!(span, "WF predicate not satisfied for {:?}", ty); span_bug!(span, "WF predicate not satisfied for {:?}", ty);
} }
TraitSolver::Chalk | TraitSolver::Next => { TraitSolver::Chalk | TraitSolver::Next | TraitSolver::NextCoherence => {
// FIXME: we'll need a better message which takes into account // FIXME: we'll need a better message which takes into account
// which bounds actually failed to hold. // which bounds actually failed to hold.
self.tcx.sess.struct_span_err( self.tcx.sess.struct_span_err(

View file

@ -78,7 +78,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
_ => obligation.param_env.without_const(), _ => obligation.param_env.without_const(),
}; };
if self.tcx.trait_solver_next() { if self.next_trait_solver() {
self.probe(|snapshot| { self.probe(|snapshot| {
let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(); let mut fulfill_cx = crate::solve::FulfillmentCtxt::new();
fulfill_cx.register_predicate_obligation(self, obligation.clone()); fulfill_cx.register_predicate_obligation(self, obligation.clone());

View file

@ -146,7 +146,7 @@ where
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
span: Span, span: Span,
) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> { ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
if infcx.tcx.trait_solver_next() { if infcx.next_trait_solver() {
return Ok(scrape_region_constraints( return Ok(scrape_region_constraints(
infcx, infcx,
|ocx| QueryTypeOp::perform_locally_in_new_solver(ocx, self), |ocx| QueryTypeOp::perform_locally_in_new_solver(ocx, self),

View file

@ -539,7 +539,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.evaluation_probe(|this| { self.evaluation_probe(|this| {
let goal = let goal =
this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env)); this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
let mut result = if this.tcx().trait_solver_next() { let mut result = if this.infcx.next_trait_solver() {
this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])? this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])?
} else { } else {
this.evaluate_predicate_recursively( this.evaluate_predicate_recursively(
@ -593,7 +593,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
where where
I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug, I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
{ {
if self.tcx().trait_solver_next() { if self.infcx.next_trait_solver() {
self.evaluate_predicates_recursively_in_new_solver(predicates) self.evaluate_predicates_recursively_in_new_solver(predicates)
} else { } else {
let mut result = EvaluatedToOk; let mut result = EvaluatedToOk;

View file

@ -21,7 +21,7 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> { ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
assert!(!ty.is_ty_var(), "should have resolved vars before calling"); assert!(!ty.is_ty_var(), "should have resolved vars before calling");
if self.infcx.tcx.trait_solver_next() { if self.infcx.next_trait_solver() {
while let ty::Alias(ty::Projection, projection_ty) = *ty.kind() { while let ty::Alias(ty::Projection, projection_ty) = *ty.kind() {
let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin { let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::NormalizeProjectionType, kind: TypeVariableOriginKind::NormalizeProjectionType,

View file

@ -16,7 +16,7 @@ fn evaluate_obligation<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonical_goal: CanonicalPredicateGoal<'tcx>, canonical_goal: CanonicalPredicateGoal<'tcx>,
) -> Result<EvaluationResult, OverflowError> { ) -> Result<EvaluationResult, OverflowError> {
assert!(!tcx.trait_solver_next()); assert!(!tcx.next_trait_solver_globally());
debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal); debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal);
// HACK This bubble is required for this tests to pass: // HACK This bubble is required for this tests to pass:
// impl-trait/issue99642.rs // impl-trait/issue99642.rs