Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce SolverRelating type relation to the new solver #131263

Merged
merged 7 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
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
Loading