Skip to content

Commit

Permalink
Auto merge of #131263 - compiler-errors:solver-relating, r=lcnr
Browse files Browse the repository at this point in the history
Introduce SolverRelating type relation to the new solver

Redux of #128744.

Splits out relate for the new solver so that implementors don't need to implement it themselves.

r? lcnr
  • Loading branch information
bors committed Oct 10, 2024
2 parents 4cc494b + 8715bfb commit 8d94e06
Show file tree
Hide file tree
Showing 31 changed files with 911 additions and 517 deletions.
7 changes: 4 additions & 3 deletions compiler/rustc_borrowck/src/type_check/relate_tys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use rustc_middle::span_bug;
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::fold::FnMutDelegate;
use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
Expand Down Expand Up @@ -362,7 +363,7 @@ impl<'b, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'b, 'tcx> {
&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.next_trait_solver() => {
infcx.super_combine_tys(self, a, b).map(|_| ()).or_else(|err| {
super_combine_tys(&infcx.infcx, self, a, b).map(|_| ()).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.
Expand All @@ -385,7 +386,7 @@ impl<'b, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'b, 'tcx> {
debug!(?a, ?b, ?self.ambient_variance);

// Will also handle unification of `IntVar` and `FloatVar`.
self.type_checker.infcx.super_combine_tys(self, a, b)?;
super_combine_tys(&self.type_checker.infcx.infcx, self, a, b)?;
}
}

Expand Down Expand Up @@ -422,7 +423,7 @@ impl<'b, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'b, 'tcx> {
assert!(!a.has_non_region_infer(), "unexpected inference var {:?}", a);
assert!(!b.has_non_region_infer(), "unexpected inference var {:?}", b);

self.type_checker.infcx.super_combine_consts(self, a, b)
super_combine_consts(&self.type_checker.infcx.infcx, self, a, b)
}

#[instrument(skip(self), level = "trace")]
Expand Down
146 changes: 72 additions & 74 deletions compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,14 @@

use relate::lattice::{LatticeOp, LatticeOpKind};
use rustc_middle::bug;
use rustc_middle::ty::relate::solver_relating::RelateExt as NextSolverRelate;
use rustc_middle::ty::{Const, ImplSubject};

use super::*;
use crate::infer::relate::type_relating::TypeRelating;
use crate::infer::relate::{Relate, StructurallyRelateAliases, TypeRelation};
use crate::infer::relate::{Relate, TypeRelation};
use crate::traits::Obligation;
use crate::traits::solve::Goal;

/// Whether we should define opaque types or just treat them opaquely.
///
Expand Down Expand Up @@ -109,16 +112,26 @@ impl<'a, 'tcx> At<'a, 'tcx> {
where
T: ToTrace<'tcx>,
{
let mut op = TypeRelating::new(
self.infcx,
ToTrace::to_trace(self.cause, expected, actual),
self.param_env,
define_opaque_types,
StructurallyRelateAliases::No,
ty::Contravariant,
);
op.relate(expected, actual)?;
Ok(InferOk { value: (), obligations: op.into_obligations() })
if self.infcx.next_trait_solver {
NextSolverRelate::relate(
self.infcx,
self.param_env,
expected,
ty::Contravariant,
actual,
)
.map(|goals| self.goals_to_obligations(goals))
} else {
let mut op = TypeRelating::new(
self.infcx,
ToTrace::to_trace(self.cause, expected, actual),
self.param_env,
define_opaque_types,
ty::Contravariant,
);
op.relate(expected, actual)?;
Ok(InferOk { value: (), obligations: op.into_obligations() })
}
}

/// Makes `expected <: actual`.
Expand All @@ -131,16 +144,20 @@ impl<'a, 'tcx> At<'a, 'tcx> {
where
T: ToTrace<'tcx>,
{
let mut op = TypeRelating::new(
self.infcx,
ToTrace::to_trace(self.cause, expected, actual),
self.param_env,
define_opaque_types,
StructurallyRelateAliases::No,
ty::Covariant,
);
op.relate(expected, actual)?;
Ok(InferOk { value: (), obligations: op.into_obligations() })
if self.infcx.next_trait_solver {
NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Covariant, actual)
.map(|goals| self.goals_to_obligations(goals))
} else {
let mut op = TypeRelating::new(
self.infcx,
ToTrace::to_trace(self.cause, expected, actual),
self.param_env,
define_opaque_types,
ty::Covariant,
);
op.relate(expected, actual)?;
Ok(InferOk { value: (), obligations: op.into_obligations() })
}
}

/// Makes `expected == actual`.
Expand Down Expand Up @@ -172,16 +189,20 @@ impl<'a, 'tcx> At<'a, 'tcx> {
where
T: Relate<TyCtxt<'tcx>>,
{
let mut op = TypeRelating::new(
self.infcx,
trace,
self.param_env,
define_opaque_types,
StructurallyRelateAliases::No,
ty::Invariant,
);
op.relate(expected, actual)?;
Ok(InferOk { value: (), obligations: op.into_obligations() })
if self.infcx.next_trait_solver {
NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Invariant, actual)
.map(|goals| self.goals_to_obligations(goals))
} else {
let mut op = TypeRelating::new(
self.infcx,
trace,
self.param_env,
define_opaque_types,
ty::Invariant,
);
op.relate(expected, actual)?;
Ok(InferOk { value: (), obligations: op.into_obligations() })
}
}

pub fn relate<T>(
Expand All @@ -208,49 +229,6 @@ impl<'a, 'tcx> At<'a, 'tcx> {
}
}

/// Used in the new solver since we don't care about tracking an `ObligationCause`.
pub fn relate_no_trace<T>(
self,
expected: T,
variance: ty::Variance,
actual: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>
where
T: Relate<TyCtxt<'tcx>>,
{
let mut op = TypeRelating::new(
self.infcx,
TypeTrace::dummy(self.cause),
self.param_env,
DefineOpaqueTypes::Yes,
StructurallyRelateAliases::No,
variance,
);
op.relate(expected, actual)?;
Ok(op.into_obligations().into_iter().map(|o| o.into()).collect())
}

/// Used in the new solver since we don't care about tracking an `ObligationCause`.
pub fn eq_structurally_relating_aliases_no_trace<T>(
self,
expected: T,
actual: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>
where
T: Relate<TyCtxt<'tcx>>,
{
let mut op = TypeRelating::new(
self.infcx,
TypeTrace::dummy(self.cause),
self.param_env,
DefineOpaqueTypes::Yes,
StructurallyRelateAliases::Yes,
ty::Invariant,
);
op.relate(expected, actual)?;
Ok(op.into_obligations().into_iter().map(|o| o.into()).collect())
}

/// Computes the least-upper-bound, or mutual supertype, of two
/// values. The order of the arguments doesn't matter, but since
/// this can result in an error (e.g., if asked to compute LUB of
Expand All @@ -269,6 +247,26 @@ impl<'a, 'tcx> At<'a, 'tcx> {
let value = op.relate(expected, actual)?;
Ok(InferOk { value, obligations: op.into_obligations() })
}

fn goals_to_obligations(
&self,
goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
) -> InferOk<'tcx, ()> {
InferOk {
value: (),
obligations: goals
.into_iter()
.map(|goal| {
Obligation::new(
self.infcx.tcx,
self.cause.clone(),
goal.param_env,
goal.predicate,
)
})
.collect(),
}
}
}

impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> {
Expand Down
114 changes: 94 additions & 20 deletions compiler/rustc_infer/src/infer/context.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
///! Definition of `InferCtxtLike` from the librarified type layer.
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::infer::unify_key::EffectVarValue;
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::solve::{Goal, NoSolution, SolverMode};
use rustc_middle::traits::solve::SolverMode;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::DUMMY_SP;
use rustc_type_ir::InferCtxtLike;
use rustc_type_ir::relate::Relate;
use rustc_span::{DUMMY_SP, ErrorGuaranteed};

use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin};

impl<'tcx> InferCtxtLike for InferCtxt<'tcx> {
impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
type Interner = TyCtxt<'tcx>;

fn cx(&self) -> TyCtxt<'tcx> {
self.tcx
}

fn next_trait_solver(&self) -> bool {
self.next_trait_solver
}

fn solver_mode(&self) -> ty::solve::SolverMode {
match self.intercrate {
true => SolverMode::Coherence,
Expand Down Expand Up @@ -131,29 +136,86 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> {
self.enter_forall(value, f)
}

fn relate<T: Relate<TyCtxt<'tcx>>>(
fn equate_ty_vids_raw(&self, a: rustc_type_ir::TyVid, b: rustc_type_ir::TyVid) {
self.inner.borrow_mut().type_variables().equate(a, b);
}

fn equate_int_vids_raw(&self, a: rustc_type_ir::IntVid, b: rustc_type_ir::IntVid) {
self.inner.borrow_mut().int_unification_table().union(a, b);
}

fn equate_float_vids_raw(&self, a: rustc_type_ir::FloatVid, b: rustc_type_ir::FloatVid) {
self.inner.borrow_mut().float_unification_table().union(a, b);
}

fn equate_const_vids_raw(&self, a: rustc_type_ir::ConstVid, b: rustc_type_ir::ConstVid) {
self.inner.borrow_mut().const_unification_table().union(a, b);
}

fn equate_effect_vids_raw(&self, a: rustc_type_ir::EffectVid, b: rustc_type_ir::EffectVid) {
self.inner.borrow_mut().effect_unification_table().union(a, b);
}

fn instantiate_ty_var_raw<R: PredicateEmittingRelation<Self>>(
&self,
param_env: ty::ParamEnv<'tcx>,
lhs: T,
variance: ty::Variance,
rhs: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
self.at(&ObligationCause::dummy(), param_env).relate_no_trace(lhs, variance, rhs)
relation: &mut R,
target_is_expected: bool,
target_vid: rustc_type_ir::TyVid,
instantiation_variance: rustc_type_ir::Variance,
source_ty: Ty<'tcx>,
) -> RelateResult<'tcx, ()> {
self.instantiate_ty_var(
relation,
target_is_expected,
target_vid,
instantiation_variance,
source_ty,
)
}

fn instantiate_int_var_raw(
&self,
vid: rustc_type_ir::IntVid,
value: rustc_type_ir::IntVarValue,
) {
self.inner.borrow_mut().int_unification_table().union_value(vid, value);
}

fn instantiate_float_var_raw(
&self,
vid: rustc_type_ir::FloatVid,
value: rustc_type_ir::FloatVarValue,
) {
self.inner.borrow_mut().float_unification_table().union_value(vid, value);
}

fn instantiate_effect_var_raw(&self, vid: rustc_type_ir::EffectVid, value: ty::Const<'tcx>) {
self.inner
.borrow_mut()
.effect_unification_table()
.union_value(vid, EffectVarValue::Known(value));
}

fn eq_structurally_relating_aliases<T: Relate<TyCtxt<'tcx>>>(
fn instantiate_const_var_raw<R: PredicateEmittingRelation<Self>>(
&self,
param_env: ty::ParamEnv<'tcx>,
lhs: T,
rhs: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
self.at(&ObligationCause::dummy(), param_env)
.eq_structurally_relating_aliases_no_trace(lhs, rhs)
relation: &mut R,
target_is_expected: bool,
target_vid: rustc_type_ir::ConstVid,
source_ct: ty::Const<'tcx>,
) -> RelateResult<'tcx, ()> {
self.instantiate_const_var(relation, target_is_expected, target_vid, source_ct)
}

fn set_tainted_by_errors(&self, e: ErrorGuaranteed) {
self.set_tainted_by_errors(e)
}

fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
self.shallow_resolve(ty)
}
fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
self.shallow_resolve_const(ct)
}

fn resolve_vars_if_possible<T>(&self, value: T) -> T
where
Expand All @@ -167,7 +229,19 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> {
}

fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>) {
self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), sub, sup)
self.inner.borrow_mut().unwrap_region_constraints().make_subregion(
SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),
sub,
sup,
);
}

fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>) {
self.inner.borrow_mut().unwrap_region_constraints().make_eqregion(
SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),
a,
b,
);
}

fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) {
Expand Down
Loading

0 comments on commit 8d94e06

Please sign in to comment.