mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #131263 - compiler-errors:solver-relating, r=lcnr
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
This commit is contained in:
commit
8d94e06ec9
@ -11,6 +11,7 @@ use rustc_middle::span_bug;
|
|||||||
use rustc_middle::traits::ObligationCause;
|
use rustc_middle::traits::ObligationCause;
|
||||||
use rustc_middle::traits::query::NoSolution;
|
use rustc_middle::traits::query::NoSolution;
|
||||||
use rustc_middle::ty::fold::FnMutDelegate;
|
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_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
@ -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: 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.next_trait_solver() => {
|
) 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
|
// 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.
|
||||||
@ -385,7 +386,7 @@ impl<'b, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'b, 'tcx> {
|
|||||||
debug!(?a, ?b, ?self.ambient_variance);
|
debug!(?a, ?b, ?self.ambient_variance);
|
||||||
|
|
||||||
// Will also handle unification of `IntVar` and `FloatVar`.
|
// 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)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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!(!a.has_non_region_infer(), "unexpected inference var {:?}", a);
|
||||||
assert!(!b.has_non_region_infer(), "unexpected inference var {:?}", b);
|
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")]
|
#[instrument(skip(self), level = "trace")]
|
||||||
|
@ -27,11 +27,14 @@
|
|||||||
|
|
||||||
use relate::lattice::{LatticeOp, LatticeOpKind};
|
use relate::lattice::{LatticeOp, LatticeOpKind};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
|
use rustc_middle::ty::relate::solver_relating::RelateExt as NextSolverRelate;
|
||||||
use rustc_middle::ty::{Const, ImplSubject};
|
use rustc_middle::ty::{Const, ImplSubject};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::infer::relate::type_relating::TypeRelating;
|
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.
|
/// Whether we should define opaque types or just treat them opaquely.
|
||||||
///
|
///
|
||||||
@ -109,17 +112,27 @@ impl<'a, 'tcx> At<'a, 'tcx> {
|
|||||||
where
|
where
|
||||||
T: ToTrace<'tcx>,
|
T: ToTrace<'tcx>,
|
||||||
{
|
{
|
||||||
|
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(
|
let mut op = TypeRelating::new(
|
||||||
self.infcx,
|
self.infcx,
|
||||||
ToTrace::to_trace(self.cause, expected, actual),
|
ToTrace::to_trace(self.cause, expected, actual),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
define_opaque_types,
|
define_opaque_types,
|
||||||
StructurallyRelateAliases::No,
|
|
||||||
ty::Contravariant,
|
ty::Contravariant,
|
||||||
);
|
);
|
||||||
op.relate(expected, actual)?;
|
op.relate(expected, actual)?;
|
||||||
Ok(InferOk { value: (), obligations: op.into_obligations() })
|
Ok(InferOk { value: (), obligations: op.into_obligations() })
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Makes `expected <: actual`.
|
/// Makes `expected <: actual`.
|
||||||
pub fn sub<T>(
|
pub fn sub<T>(
|
||||||
@ -131,17 +144,21 @@ impl<'a, 'tcx> At<'a, 'tcx> {
|
|||||||
where
|
where
|
||||||
T: ToTrace<'tcx>,
|
T: ToTrace<'tcx>,
|
||||||
{
|
{
|
||||||
|
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(
|
let mut op = TypeRelating::new(
|
||||||
self.infcx,
|
self.infcx,
|
||||||
ToTrace::to_trace(self.cause, expected, actual),
|
ToTrace::to_trace(self.cause, expected, actual),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
define_opaque_types,
|
define_opaque_types,
|
||||||
StructurallyRelateAliases::No,
|
|
||||||
ty::Covariant,
|
ty::Covariant,
|
||||||
);
|
);
|
||||||
op.relate(expected, actual)?;
|
op.relate(expected, actual)?;
|
||||||
Ok(InferOk { value: (), obligations: op.into_obligations() })
|
Ok(InferOk { value: (), obligations: op.into_obligations() })
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Makes `expected == actual`.
|
/// Makes `expected == actual`.
|
||||||
pub fn eq<T>(
|
pub fn eq<T>(
|
||||||
@ -172,17 +189,21 @@ impl<'a, 'tcx> At<'a, 'tcx> {
|
|||||||
where
|
where
|
||||||
T: Relate<TyCtxt<'tcx>>,
|
T: Relate<TyCtxt<'tcx>>,
|
||||||
{
|
{
|
||||||
|
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(
|
let mut op = TypeRelating::new(
|
||||||
self.infcx,
|
self.infcx,
|
||||||
trace,
|
trace,
|
||||||
self.param_env,
|
self.param_env,
|
||||||
define_opaque_types,
|
define_opaque_types,
|
||||||
StructurallyRelateAliases::No,
|
|
||||||
ty::Invariant,
|
ty::Invariant,
|
||||||
);
|
);
|
||||||
op.relate(expected, actual)?;
|
op.relate(expected, actual)?;
|
||||||
Ok(InferOk { value: (), obligations: op.into_obligations() })
|
Ok(InferOk { value: (), obligations: op.into_obligations() })
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn relate<T>(
|
pub fn relate<T>(
|
||||||
self,
|
self,
|
||||||
@ -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
|
/// Computes the least-upper-bound, or mutual supertype, of two
|
||||||
/// values. The order of the arguments doesn't matter, but since
|
/// 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
|
/// this can result in an error (e.g., if asked to compute LUB of
|
||||||
@ -269,6 +247,26 @@ impl<'a, 'tcx> At<'a, 'tcx> {
|
|||||||
let value = op.relate(expected, actual)?;
|
let value = op.relate(expected, actual)?;
|
||||||
Ok(InferOk { value, obligations: op.into_obligations() })
|
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> {
|
impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> {
|
||||||
|
@ -1,22 +1,27 @@
|
|||||||
///! Definition of `InferCtxtLike` from the librarified type layer.
|
///! Definition of `InferCtxtLike` from the librarified type layer.
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
|
use rustc_middle::infer::unify_key::EffectVarValue;
|
||||||
use rustc_middle::traits::ObligationCause;
|
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::fold::TypeFoldable;
|
||||||
|
use rustc_middle::ty::relate::RelateResult;
|
||||||
|
use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::{DUMMY_SP, ErrorGuaranteed};
|
||||||
use rustc_type_ir::InferCtxtLike;
|
|
||||||
use rustc_type_ir::relate::Relate;
|
|
||||||
|
|
||||||
use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin};
|
use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin};
|
||||||
|
|
||||||
impl<'tcx> InferCtxtLike for InferCtxt<'tcx> {
|
impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
||||||
type Interner = TyCtxt<'tcx>;
|
type Interner = TyCtxt<'tcx>;
|
||||||
|
|
||||||
fn cx(&self) -> TyCtxt<'tcx> {
|
fn cx(&self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn next_trait_solver(&self) -> bool {
|
||||||
|
self.next_trait_solver
|
||||||
|
}
|
||||||
|
|
||||||
fn solver_mode(&self) -> ty::solve::SolverMode {
|
fn solver_mode(&self) -> ty::solve::SolverMode {
|
||||||
match self.intercrate {
|
match self.intercrate {
|
||||||
true => SolverMode::Coherence,
|
true => SolverMode::Coherence,
|
||||||
@ -131,29 +136,86 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> {
|
|||||||
self.enter_forall(value, f)
|
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,
|
self.inner.borrow_mut().type_variables().equate(a, b);
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eq_structurally_relating_aliases<T: Relate<TyCtxt<'tcx>>>(
|
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,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
relation: &mut R,
|
||||||
lhs: T,
|
target_is_expected: bool,
|
||||||
rhs: T,
|
target_vid: rustc_type_ir::TyVid,
|
||||||
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
|
instantiation_variance: rustc_type_ir::Variance,
|
||||||
self.at(&ObligationCause::dummy(), param_env)
|
source_ty: Ty<'tcx>,
|
||||||
.eq_structurally_relating_aliases_no_trace(lhs, rhs)
|
) -> 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 instantiate_const_var_raw<R: PredicateEmittingRelation<Self>>(
|
||||||
|
&self,
|
||||||
|
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> {
|
fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
self.shallow_resolve(ty)
|
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
|
fn resolve_vars_if_possible<T>(&self, value: T) -> T
|
||||||
where
|
where
|
||||||
@ -167,7 +229,19 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'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>) {
|
fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) {
|
||||||
|
@ -32,7 +32,6 @@ use rustc_middle::infer::unify_key::{
|
|||||||
use rustc_middle::mir::ConstraintCategory;
|
use rustc_middle::mir::ConstraintCategory;
|
||||||
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
|
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
|
||||||
use rustc_middle::traits::select;
|
use rustc_middle::traits::select;
|
||||||
use rustc_middle::traits::solve::{Goal, NoSolution};
|
|
||||||
pub use rustc_middle::ty::IntVarValue;
|
pub use rustc_middle::ty::IntVarValue;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::{
|
use rustc_middle::ty::fold::{
|
||||||
@ -340,7 +339,6 @@ pub enum ValuePairs<'tcx> {
|
|||||||
PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
|
PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
|
||||||
ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
|
ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
|
||||||
ExistentialProjection(ExpectedFound<ty::PolyExistentialProjection<'tcx>>),
|
ExistentialProjection(ExpectedFound<ty::PolyExistentialProjection<'tcx>>),
|
||||||
Dummy,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ValuePairs<'tcx> {
|
impl<'tcx> ValuePairs<'tcx> {
|
||||||
@ -1638,10 +1636,6 @@ impl<'tcx> TypeTrace<'tcx> {
|
|||||||
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dummy(cause: &ObligationCause<'tcx>) -> TypeTrace<'tcx> {
|
|
||||||
TypeTrace { cause: cause.clone(), values: ValuePairs::Dummy }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> SubregionOrigin<'tcx> {
|
impl<'tcx> SubregionOrigin<'tcx> {
|
||||||
|
@ -1,240 +0,0 @@
|
|||||||
//! There are four type combiners: `TypeRelating`, `Lub`, and `Glb`,
|
|
||||||
//! and `NllTypeRelating` in rustc_borrowck, which is only used for NLL.
|
|
||||||
//!
|
|
||||||
//! Each implements the trait [TypeRelation] and contains methods for
|
|
||||||
//! combining two instances of various things and yielding a new instance.
|
|
||||||
//! These combiner methods always yield a `Result<T>`. To relate two
|
|
||||||
//! types, you can use `infcx.at(cause, param_env)` which then allows
|
|
||||||
//! you to use the relevant methods of [At](crate::infer::at::At).
|
|
||||||
//!
|
|
||||||
//! Combiners mostly do their specific behavior and then hand off the
|
|
||||||
//! bulk of the work to [InferCtxt::super_combine_tys] and
|
|
||||||
//! [InferCtxt::super_combine_consts].
|
|
||||||
//!
|
|
||||||
//! Combining two types may have side-effects on the inference contexts
|
|
||||||
//! which can be undone by using snapshots. You probably want to use
|
|
||||||
//! either [InferCtxt::commit_if_ok] or [InferCtxt::probe].
|
|
||||||
//!
|
|
||||||
//! On success, the LUB/GLB operations return the appropriate bound. The
|
|
||||||
//! return value of `Equate` or `Sub` shouldn't really be used.
|
|
||||||
|
|
||||||
use rustc_middle::bug;
|
|
||||||
use rustc_middle::infer::unify_key::EffectVarValue;
|
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
|
||||||
use rustc_middle::ty::{self, InferConst, IntType, Ty, TypeVisitableExt, UintType};
|
|
||||||
pub use rustc_next_trait_solver::relate::combine::*;
|
|
||||||
use tracing::debug;
|
|
||||||
|
|
||||||
use super::{RelateResult, StructurallyRelateAliases};
|
|
||||||
use crate::infer::{InferCtxt, relate};
|
|
||||||
|
|
||||||
impl<'tcx> InferCtxt<'tcx> {
|
|
||||||
pub fn super_combine_tys<R>(
|
|
||||||
&self,
|
|
||||||
relation: &mut R,
|
|
||||||
a: Ty<'tcx>,
|
|
||||||
b: Ty<'tcx>,
|
|
||||||
) -> RelateResult<'tcx, Ty<'tcx>>
|
|
||||||
where
|
|
||||||
R: PredicateEmittingRelation<InferCtxt<'tcx>>,
|
|
||||||
{
|
|
||||||
debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
|
|
||||||
debug_assert!(!a.has_escaping_bound_vars());
|
|
||||||
debug_assert!(!b.has_escaping_bound_vars());
|
|
||||||
|
|
||||||
match (a.kind(), b.kind()) {
|
|
||||||
// Relate integral variables to other types
|
|
||||||
(&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => {
|
|
||||||
self.inner.borrow_mut().int_unification_table().union(a_id, b_id);
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
(&ty::Infer(ty::IntVar(v_id)), &ty::Int(v)) => {
|
|
||||||
self.unify_integral_variable(v_id, IntType(v));
|
|
||||||
Ok(b)
|
|
||||||
}
|
|
||||||
(&ty::Int(v), &ty::Infer(ty::IntVar(v_id))) => {
|
|
||||||
self.unify_integral_variable(v_id, IntType(v));
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
(&ty::Infer(ty::IntVar(v_id)), &ty::Uint(v)) => {
|
|
||||||
self.unify_integral_variable(v_id, UintType(v));
|
|
||||||
Ok(b)
|
|
||||||
}
|
|
||||||
(&ty::Uint(v), &ty::Infer(ty::IntVar(v_id))) => {
|
|
||||||
self.unify_integral_variable(v_id, UintType(v));
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Relate floating-point variables to other types
|
|
||||||
(&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => {
|
|
||||||
self.inner.borrow_mut().float_unification_table().union(a_id, b_id);
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
(&ty::Infer(ty::FloatVar(v_id)), &ty::Float(v)) => {
|
|
||||||
self.unify_float_variable(v_id, ty::FloatVarValue::Known(v));
|
|
||||||
Ok(b)
|
|
||||||
}
|
|
||||||
(&ty::Float(v), &ty::Infer(ty::FloatVar(v_id))) => {
|
|
||||||
self.unify_float_variable(v_id, ty::FloatVarValue::Known(v));
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm.
|
|
||||||
(ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..))
|
|
||||||
if self.next_trait_solver() =>
|
|
||||||
{
|
|
||||||
bug!(
|
|
||||||
"We do not expect to encounter `TyVar` this late in combine \
|
|
||||||
-- they should have been handled earlier"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)))
|
|
||||||
| (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _)
|
|
||||||
if self.next_trait_solver() =>
|
|
||||||
{
|
|
||||||
bug!("We do not expect to encounter `Fresh` variables in the new solver")
|
|
||||||
}
|
|
||||||
|
|
||||||
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => {
|
|
||||||
match relation.structurally_relate_aliases() {
|
|
||||||
StructurallyRelateAliases::Yes => {
|
|
||||||
relate::structurally_relate_tys(relation, a, b)
|
|
||||||
}
|
|
||||||
StructurallyRelateAliases::No => {
|
|
||||||
relation.register_alias_relate_predicate(a, b);
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// All other cases of inference are errors
|
|
||||||
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
|
|
||||||
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// During coherence, opaque types should be treated as *possibly*
|
|
||||||
// equal to any other type (except for possibly itself). This is an
|
|
||||||
// extremely heavy hammer, but can be relaxed in a forwards-compatible
|
|
||||||
// way later.
|
|
||||||
(&ty::Alias(ty::Opaque, _), _) | (_, &ty::Alias(ty::Opaque, _)) if self.intercrate => {
|
|
||||||
relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => relate::structurally_relate_tys(relation, a, b),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn super_combine_consts<R>(
|
|
||||||
&self,
|
|
||||||
relation: &mut R,
|
|
||||||
a: ty::Const<'tcx>,
|
|
||||||
b: ty::Const<'tcx>,
|
|
||||||
) -> RelateResult<'tcx, ty::Const<'tcx>>
|
|
||||||
where
|
|
||||||
R: PredicateEmittingRelation<InferCtxt<'tcx>>,
|
|
||||||
{
|
|
||||||
debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
|
|
||||||
debug_assert!(!a.has_escaping_bound_vars());
|
|
||||||
debug_assert!(!b.has_escaping_bound_vars());
|
|
||||||
|
|
||||||
if a == b {
|
|
||||||
return Ok(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
let a = self.shallow_resolve_const(a);
|
|
||||||
let b = self.shallow_resolve_const(b);
|
|
||||||
|
|
||||||
match (a.kind(), b.kind()) {
|
|
||||||
(
|
|
||||||
ty::ConstKind::Infer(InferConst::Var(a_vid)),
|
|
||||||
ty::ConstKind::Infer(InferConst::Var(b_vid)),
|
|
||||||
) => {
|
|
||||||
self.inner.borrow_mut().const_unification_table().union(a_vid, b_vid);
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
(
|
|
||||||
ty::ConstKind::Infer(InferConst::EffectVar(a_vid)),
|
|
||||||
ty::ConstKind::Infer(InferConst::EffectVar(b_vid)),
|
|
||||||
) => {
|
|
||||||
self.inner.borrow_mut().effect_unification_table().union(a_vid, b_vid);
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
// All other cases of inference with other variables are errors.
|
|
||||||
(
|
|
||||||
ty::ConstKind::Infer(InferConst::Var(_) | InferConst::EffectVar(_)),
|
|
||||||
ty::ConstKind::Infer(_),
|
|
||||||
)
|
|
||||||
| (
|
|
||||||
ty::ConstKind::Infer(_),
|
|
||||||
ty::ConstKind::Infer(InferConst::Var(_) | InferConst::EffectVar(_)),
|
|
||||||
) => {
|
|
||||||
bug!(
|
|
||||||
"tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
(ty::ConstKind::Infer(InferConst::Var(vid)), _) => {
|
|
||||||
self.instantiate_const_var(relation, true, vid, b)?;
|
|
||||||
Ok(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
(_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
|
|
||||||
self.instantiate_const_var(relation, false, vid, a)?;
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
(ty::ConstKind::Infer(InferConst::EffectVar(vid)), _) => {
|
|
||||||
Ok(self.unify_effect_variable(vid, b))
|
|
||||||
}
|
|
||||||
|
|
||||||
(_, ty::ConstKind::Infer(InferConst::EffectVar(vid))) => {
|
|
||||||
Ok(self.unify_effect_variable(vid, a))
|
|
||||||
}
|
|
||||||
|
|
||||||
(ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
|
|
||||||
if self.tcx.features().generic_const_exprs || self.next_trait_solver() =>
|
|
||||||
{
|
|
||||||
match relation.structurally_relate_aliases() {
|
|
||||||
StructurallyRelateAliases::No => {
|
|
||||||
relation.register_predicates([if self.next_trait_solver() {
|
|
||||||
ty::PredicateKind::AliasRelate(
|
|
||||||
a.into(),
|
|
||||||
b.into(),
|
|
||||||
ty::AliasRelationDirection::Equate,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
ty::PredicateKind::ConstEquate(a, b)
|
|
||||||
}]);
|
|
||||||
|
|
||||||
Ok(b)
|
|
||||||
}
|
|
||||||
StructurallyRelateAliases::Yes => {
|
|
||||||
relate::structurally_relate_consts(relation, a, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => relate::structurally_relate_consts(relation, a, b),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn unify_integral_variable(&self, vid: ty::IntVid, val: ty::IntVarValue) {
|
|
||||||
self.inner.borrow_mut().int_unification_table().union_value(vid, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn unify_float_variable(&self, vid: ty::FloatVid, val: ty::FloatVarValue) {
|
|
||||||
self.inner.borrow_mut().float_unification_table().union_value(vid, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unify_effect_variable(&self, vid: ty::EffectVid, val: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
|
||||||
self.inner
|
|
||||||
.borrow_mut()
|
|
||||||
.effect_unification_table()
|
|
||||||
.union_value(vid, EffectVarValue::Known(val));
|
|
||||||
val
|
|
||||||
}
|
|
||||||
}
|
|
@ -183,7 +183,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
///
|
///
|
||||||
/// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant.
|
/// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant.
|
||||||
#[instrument(level = "debug", skip(self, relation))]
|
#[instrument(level = "debug", skip(self, relation))]
|
||||||
pub(super) fn instantiate_const_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
|
pub(crate) fn instantiate_const_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
|
||||||
&self,
|
&self,
|
||||||
relation: &mut R,
|
relation: &mut R,
|
||||||
target_is_expected: bool,
|
target_is_expected: bool,
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
//! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
|
//! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
|
||||||
|
|
||||||
use rustc_middle::traits::solve::Goal;
|
use rustc_middle::traits::solve::Goal;
|
||||||
|
use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys};
|
||||||
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
|
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TyVar, TypeVisitableExt};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TyVar, TypeVisitableExt};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@ -148,7 +149,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
|
|||||||
(
|
(
|
||||||
&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.super_combine_tys(self, a, b),
|
) if a_def_id == b_def_id => super_combine_tys(infcx, self, a, b),
|
||||||
|
|
||||||
(&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, .. }))
|
||||||
@ -163,7 +164,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
|
|||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => infcx.super_combine_tys(self, a, b),
|
_ => super_combine_tys(infcx, self, a, b),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +192,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
|
|||||||
a: ty::Const<'tcx>,
|
a: ty::Const<'tcx>,
|
||||||
b: ty::Const<'tcx>,
|
b: ty::Const<'tcx>,
|
||||||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
||||||
self.infcx.super_combine_consts(self, a, b)
|
super_combine_consts(self.infcx, self, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn binders<T>(
|
fn binders<T>(
|
||||||
|
@ -3,12 +3,9 @@
|
|||||||
//! As well as the implementation of `Relate` for interned things (`Ty`/`Const`/etc).
|
//! As well as the implementation of `Relate` for interned things (`Ty`/`Const`/etc).
|
||||||
|
|
||||||
pub use rustc_middle::ty::relate::RelateResult;
|
pub use rustc_middle::ty::relate::RelateResult;
|
||||||
pub use rustc_next_trait_solver::relate::*;
|
pub use rustc_type_ir::relate::combine::PredicateEmittingRelation;
|
||||||
|
pub use rustc_type_ir::relate::*;
|
||||||
|
|
||||||
pub use self::combine::PredicateEmittingRelation;
|
|
||||||
|
|
||||||
#[allow(hidden_glob_reexports)]
|
|
||||||
pub(super) mod combine;
|
|
||||||
mod generalize;
|
mod generalize;
|
||||||
mod higher_ranked;
|
mod higher_ranked;
|
||||||
pub(super) mod lattice;
|
pub(super) mod lattice;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use rustc_middle::traits::solve::Goal;
|
use rustc_middle::traits::solve::Goal;
|
||||||
|
use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys};
|
||||||
use rustc_middle::ty::relate::{
|
use rustc_middle::ty::relate::{
|
||||||
Relate, RelateResult, TypeRelation, relate_args_invariantly, relate_args_with_variances,
|
Relate, RelateResult, TypeRelation, relate_args_invariantly, relate_args_with_variances,
|
||||||
};
|
};
|
||||||
@ -20,7 +21,6 @@ pub(crate) struct TypeRelating<'infcx, 'tcx> {
|
|||||||
trace: TypeTrace<'tcx>,
|
trace: TypeTrace<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
define_opaque_types: DefineOpaqueTypes,
|
define_opaque_types: DefineOpaqueTypes,
|
||||||
structurally_relate_aliases: StructurallyRelateAliases,
|
|
||||||
|
|
||||||
// Mutable fields.
|
// Mutable fields.
|
||||||
ambient_variance: ty::Variance,
|
ambient_variance: ty::Variance,
|
||||||
@ -56,15 +56,14 @@ impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> {
|
|||||||
trace: TypeTrace<'tcx>,
|
trace: TypeTrace<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
define_opaque_types: DefineOpaqueTypes,
|
define_opaque_types: DefineOpaqueTypes,
|
||||||
structurally_relate_aliases: StructurallyRelateAliases,
|
|
||||||
ambient_variance: ty::Variance,
|
ambient_variance: ty::Variance,
|
||||||
) -> TypeRelating<'infcx, 'tcx> {
|
) -> TypeRelating<'infcx, 'tcx> {
|
||||||
|
assert!(!infcx.next_trait_solver);
|
||||||
TypeRelating {
|
TypeRelating {
|
||||||
infcx,
|
infcx,
|
||||||
trace,
|
trace,
|
||||||
param_env,
|
param_env,
|
||||||
define_opaque_types,
|
define_opaque_types,
|
||||||
structurally_relate_aliases,
|
|
||||||
ambient_variance,
|
ambient_variance,
|
||||||
obligations: vec![],
|
obligations: vec![],
|
||||||
cache: Default::default(),
|
cache: Default::default(),
|
||||||
@ -183,23 +182,16 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, 'tcx> {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
(&ty::Error(e), _) | (_, &ty::Error(e)) => {
|
|
||||||
infcx.set_tainted_by_errors(e);
|
|
||||||
return Ok(Ty::new_error(self.cx(), e));
|
|
||||||
}
|
|
||||||
|
|
||||||
(
|
(
|
||||||
&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 => {
|
) if a_def_id == b_def_id => {
|
||||||
infcx.super_combine_tys(self, a, b)?;
|
super_combine_tys(infcx, self, a, b)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
(&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 self.define_opaque_types == DefineOpaqueTypes::Yes
|
if self.define_opaque_types == DefineOpaqueTypes::Yes && def_id.is_local() =>
|
||||||
&& def_id.is_local()
|
|
||||||
&& !infcx.next_trait_solver() =>
|
|
||||||
{
|
{
|
||||||
self.register_goals(infcx.handle_opaque_type(
|
self.register_goals(infcx.handle_opaque_type(
|
||||||
a,
|
a,
|
||||||
@ -210,7 +202,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
infcx.super_combine_tys(self, a, b)?;
|
super_combine_tys(infcx, self, a, b)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +257,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, 'tcx> {
|
|||||||
a: ty::Const<'tcx>,
|
a: ty::Const<'tcx>,
|
||||||
b: ty::Const<'tcx>,
|
b: ty::Const<'tcx>,
|
||||||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
||||||
self.infcx.super_combine_consts(self, a, b)
|
super_combine_consts(self.infcx, self, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn binders<T>(
|
fn binders<T>(
|
||||||
@ -357,7 +349,7 @@ impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for TypeRelating<'_, 'tcx>
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
|
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
|
||||||
self.structurally_relate_aliases
|
StructurallyRelateAliases::No
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_predicates(
|
fn register_predicates(
|
||||||
|
@ -698,6 +698,12 @@ impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_featu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> rustc_type_ir::inherent::Span<TyCtxt<'tcx>> for Span {
|
||||||
|
fn dummy() -> Self {
|
||||||
|
DUMMY_SP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
||||||
|
|
||||||
pub struct CtxtInterners<'tcx> {
|
pub struct CtxtInterners<'tcx> {
|
||||||
|
@ -12,6 +12,5 @@
|
|||||||
pub mod canonicalizer;
|
pub mod canonicalizer;
|
||||||
pub mod coherence;
|
pub mod coherence;
|
||||||
pub mod delegate;
|
pub mod delegate;
|
||||||
pub mod relate;
|
|
||||||
pub mod resolve;
|
pub mod resolve;
|
||||||
pub mod solve;
|
pub mod solve;
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
pub use rustc_type_ir::relate::*;
|
|
||||||
|
|
||||||
pub mod combine;
|
|
||||||
|
|
||||||
/// Whether aliases should be related structurally or not. Used
|
|
||||||
/// to adjust the behavior of generalization and combine.
|
|
||||||
///
|
|
||||||
/// This should always be `No` unless in a few special-cases when
|
|
||||||
/// instantiating canonical responses and in the new solver. Each
|
|
||||||
/// such case should have a comment explaining why it is used.
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub enum StructurallyRelateAliases {
|
|
||||||
Yes,
|
|
||||||
No,
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
pub use rustc_type_ir::relate::*;
|
|
||||||
use rustc_type_ir::solve::Goal;
|
|
||||||
use rustc_type_ir::{InferCtxtLike, Interner, Upcast};
|
|
||||||
|
|
||||||
use super::StructurallyRelateAliases;
|
|
||||||
|
|
||||||
pub trait PredicateEmittingRelation<Infcx, I = <Infcx as InferCtxtLike>::Interner>:
|
|
||||||
TypeRelation<I>
|
|
||||||
where
|
|
||||||
Infcx: InferCtxtLike<Interner = I>,
|
|
||||||
I: Interner,
|
|
||||||
{
|
|
||||||
fn span(&self) -> I::Span;
|
|
||||||
|
|
||||||
fn param_env(&self) -> I::ParamEnv;
|
|
||||||
|
|
||||||
/// Whether aliases should be related structurally. This is pretty much
|
|
||||||
/// always `No` unless you're equating in some specific locations of the
|
|
||||||
/// new solver. See the comments in these use-cases for more details.
|
|
||||||
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases;
|
|
||||||
|
|
||||||
/// Register obligations that must hold in order for this relation to hold
|
|
||||||
fn register_goals(&mut self, obligations: impl IntoIterator<Item = Goal<I, I::Predicate>>);
|
|
||||||
|
|
||||||
/// Register predicates that must hold in order for this relation to hold.
|
|
||||||
/// This uses the default `param_env` of the obligation.
|
|
||||||
fn register_predicates(
|
|
||||||
&mut self,
|
|
||||||
obligations: impl IntoIterator<Item: Upcast<I, I::Predicate>>,
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Register `AliasRelate` obligation(s) that both types must be related to each other.
|
|
||||||
fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty);
|
|
||||||
}
|
|
@ -14,6 +14,7 @@ use std::iter;
|
|||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_type_ir::fold::TypeFoldable;
|
use rustc_type_ir::fold::TypeFoldable;
|
||||||
use rustc_type_ir::inherent::*;
|
use rustc_type_ir::inherent::*;
|
||||||
|
use rustc_type_ir::relate::solver_relating::RelateExt;
|
||||||
use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner};
|
use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner};
|
||||||
use tracing::{instrument, trace};
|
use tracing::{instrument, trace};
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack};
|
|||||||
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_type_ir::inherent::*;
|
use rustc_type_ir::inherent::*;
|
||||||
use rustc_type_ir::relate::Relate;
|
use rustc_type_ir::relate::Relate;
|
||||||
|
use rustc_type_ir::relate::solver_relating::RelateExt;
|
||||||
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
||||||
use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner};
|
use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner};
|
||||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||||
@ -871,7 +872,7 @@ where
|
|||||||
lhs: T,
|
lhs: T,
|
||||||
rhs: T,
|
rhs: T,
|
||||||
) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution> {
|
) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution> {
|
||||||
self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs)
|
Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>(
|
pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>(
|
||||||
|
@ -1285,9 +1285,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
ValuePairs::ExistentialProjection(_) => {
|
ValuePairs::ExistentialProjection(_) => {
|
||||||
(false, Mismatch::Fixed("existential projection"))
|
(false, Mismatch::Fixed("existential projection"))
|
||||||
}
|
}
|
||||||
ValuePairs::Dummy => {
|
|
||||||
bug!("do not expect to report a type error from a ValuePairs::Dummy")
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let Some(vals) = self.values_str(values) else {
|
let Some(vals) = self.values_str(values) else {
|
||||||
// Derived error. Cancel the emitter.
|
// Derived error. Cancel the emitter.
|
||||||
@ -1853,9 +1850,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found);
|
let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found);
|
||||||
Some((exp, fnd, None))
|
Some((exp, fnd, None))
|
||||||
}
|
}
|
||||||
ValuePairs::Dummy => {
|
|
||||||
bug!("do not expect to report a type error from a ValuePairs::Dummy")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
use crate::fold::TypeFoldable;
|
use crate::fold::TypeFoldable;
|
||||||
use crate::relate::Relate;
|
use crate::relate::RelateResult;
|
||||||
use crate::solve::{Goal, NoSolution, SolverMode};
|
use crate::relate::combine::PredicateEmittingRelation;
|
||||||
|
use crate::solve::SolverMode;
|
||||||
use crate::{self as ty, Interner};
|
use crate::{self as ty, Interner};
|
||||||
|
|
||||||
pub trait InferCtxtLike: Sized {
|
pub trait InferCtxtLike: Sized {
|
||||||
type Interner: Interner;
|
type Interner: Interner;
|
||||||
fn cx(&self) -> Self::Interner;
|
fn cx(&self) -> Self::Interner;
|
||||||
|
|
||||||
|
/// Whether the new trait solver is enabled. This only exists because rustc
|
||||||
|
/// shares code between the new and old trait solvers; for all other users,
|
||||||
|
/// this should always be true. If this is unknowingly false and you try to
|
||||||
|
/// use the new trait solver, things will break badly.
|
||||||
|
fn next_trait_solver(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn solver_mode(&self) -> SolverMode;
|
fn solver_mode(&self) -> SolverMode;
|
||||||
|
|
||||||
fn universe(&self) -> ty::UniverseIndex;
|
fn universe(&self) -> ty::UniverseIndex;
|
||||||
@ -58,25 +67,45 @@ pub trait InferCtxtLike: Sized {
|
|||||||
f: impl FnOnce(T) -> U,
|
f: impl FnOnce(T) -> U,
|
||||||
) -> U;
|
) -> U;
|
||||||
|
|
||||||
fn relate<T: Relate<Self::Interner>>(
|
fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
|
||||||
&self,
|
fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
|
||||||
param_env: <Self::Interner as Interner>::ParamEnv,
|
fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
|
||||||
lhs: T,
|
fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
|
||||||
variance: ty::Variance,
|
fn equate_effect_vids_raw(&self, a: ty::EffectVid, b: ty::EffectVid);
|
||||||
rhs: T,
|
|
||||||
) -> Result<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>, NoSolution>;
|
|
||||||
|
|
||||||
fn eq_structurally_relating_aliases<T: Relate<Self::Interner>>(
|
fn instantiate_ty_var_raw<R: PredicateEmittingRelation<Self>>(
|
||||||
&self,
|
&self,
|
||||||
param_env: <Self::Interner as Interner>::ParamEnv,
|
relation: &mut R,
|
||||||
lhs: T,
|
target_is_expected: bool,
|
||||||
rhs: T,
|
target_vid: ty::TyVid,
|
||||||
) -> Result<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>, NoSolution>;
|
instantiation_variance: ty::Variance,
|
||||||
|
source_ty: <Self::Interner as Interner>::Ty,
|
||||||
|
) -> RelateResult<Self::Interner, ()>;
|
||||||
|
fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
|
||||||
|
fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
|
||||||
|
fn instantiate_effect_var_raw(
|
||||||
|
&self,
|
||||||
|
vid: ty::EffectVid,
|
||||||
|
value: <Self::Interner as Interner>::Const,
|
||||||
|
);
|
||||||
|
fn instantiate_const_var_raw<R: PredicateEmittingRelation<Self>>(
|
||||||
|
&self,
|
||||||
|
relation: &mut R,
|
||||||
|
target_is_expected: bool,
|
||||||
|
target_vid: ty::ConstVid,
|
||||||
|
source_ct: <Self::Interner as Interner>::Const,
|
||||||
|
) -> RelateResult<Self::Interner, ()>;
|
||||||
|
|
||||||
|
fn set_tainted_by_errors(&self, e: <Self::Interner as Interner>::ErrorGuaranteed);
|
||||||
|
|
||||||
fn shallow_resolve(
|
fn shallow_resolve(
|
||||||
&self,
|
&self,
|
||||||
ty: <Self::Interner as Interner>::Ty,
|
ty: <Self::Interner as Interner>::Ty,
|
||||||
) -> <Self::Interner as Interner>::Ty;
|
) -> <Self::Interner as Interner>::Ty;
|
||||||
|
fn shallow_resolve_const(
|
||||||
|
&self,
|
||||||
|
ty: <Self::Interner as Interner>::Const,
|
||||||
|
) -> <Self::Interner as Interner>::Const;
|
||||||
|
|
||||||
fn resolve_vars_if_possible<T>(&self, value: T) -> T
|
fn resolve_vars_if_possible<T>(&self, value: T) -> T
|
||||||
where
|
where
|
||||||
@ -90,6 +119,12 @@ pub trait InferCtxtLike: Sized {
|
|||||||
sup: <Self::Interner as Interner>::Region,
|
sup: <Self::Interner as Interner>::Region,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fn equate_regions(
|
||||||
|
&self,
|
||||||
|
a: <Self::Interner as Interner>::Region,
|
||||||
|
b: <Self::Interner as Interner>::Region,
|
||||||
|
);
|
||||||
|
|
||||||
fn register_ty_outlives(
|
fn register_ty_outlives(
|
||||||
&self,
|
&self,
|
||||||
ty: <Self::Interner as Interner>::Ty,
|
ty: <Self::Interner as Interner>::Ty,
|
||||||
|
@ -565,6 +565,10 @@ pub trait BoundExistentialPredicates<I: Interner>:
|
|||||||
) -> impl IntoIterator<Item = ty::Binder<I, ty::ExistentialProjection<I>>>;
|
) -> impl IntoIterator<Item = ty::Binder<I, ty::ExistentialProjection<I>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Span<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
|
||||||
|
fn dummy() -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait SliceLike: Sized + Copy {
|
pub trait SliceLike: Sized + Copy {
|
||||||
type Item: Copy;
|
type Item: Copy;
|
||||||
type IntoIter: Iterator<Item = Self::Item>;
|
type IntoIter: Iterator<Item = Self::Item>;
|
||||||
|
@ -36,7 +36,7 @@ pub trait Interner:
|
|||||||
{
|
{
|
||||||
type DefId: DefId<Self>;
|
type DefId: DefId<Self>;
|
||||||
type LocalDefId: Copy + Debug + Hash + Eq + Into<Self::DefId> + TypeFoldable<Self>;
|
type LocalDefId: Copy + Debug + Hash + Eq + Into<Self::DefId> + TypeFoldable<Self>;
|
||||||
type Span: Copy + Debug + Hash + Eq + TypeFoldable<Self>;
|
type Span: Span<Self>;
|
||||||
|
|
||||||
type GenericArgs: GenericArgs<Self>;
|
type GenericArgs: GenericArgs<Self>;
|
||||||
type GenericArgsSlice: Copy + Debug + Hash + Eq + SliceLike<Item = Self::GenericArg>;
|
type GenericArgsSlice: Copy + Debug + Hash + Eq + SliceLike<Item = Self::GenericArg>;
|
||||||
|
@ -206,8 +206,8 @@ pub fn debug_bound_var<T: std::fmt::Write>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, Hash, HashStable_NoContext))]
|
#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, HashStable_NoContext))]
|
||||||
#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
|
#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
|
||||||
pub enum Variance {
|
pub enum Variance {
|
||||||
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
|
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
|
||||||
|
@ -9,8 +9,23 @@ use crate::fold::TypeFoldable;
|
|||||||
use crate::inherent::*;
|
use crate::inherent::*;
|
||||||
use crate::{self as ty, Interner};
|
use crate::{self as ty, Interner};
|
||||||
|
|
||||||
|
pub mod combine;
|
||||||
|
pub mod solver_relating;
|
||||||
|
|
||||||
pub type RelateResult<I, T> = Result<T, TypeError<I>>;
|
pub type RelateResult<I, T> = Result<T, TypeError<I>>;
|
||||||
|
|
||||||
|
/// Whether aliases should be related structurally or not. Used
|
||||||
|
/// to adjust the behavior of generalization and combine.
|
||||||
|
///
|
||||||
|
/// This should always be `No` unless in a few special-cases when
|
||||||
|
/// instantiating canonical responses and in the new solver. Each
|
||||||
|
/// such case should have a comment explaining why it is used.
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum StructurallyRelateAliases {
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
/// Extra information about why we ended up with a particular variance.
|
/// Extra information about why we ended up with a particular variance.
|
||||||
/// This is only used to add more information to error messages, and
|
/// This is only used to add more information to error messages, and
|
||||||
/// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo`
|
/// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo`
|
||||||
|
246
compiler/rustc_type_ir/src/relate/combine.rs
Normal file
246
compiler/rustc_type_ir/src/relate/combine.rs
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
use tracing::debug;
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
ExpectedFound, RelateResult, StructurallyRelateAliases, TypeRelation,
|
||||||
|
structurally_relate_consts, structurally_relate_tys,
|
||||||
|
};
|
||||||
|
use crate::error::TypeError;
|
||||||
|
use crate::inherent::*;
|
||||||
|
use crate::solve::{Goal, SolverMode};
|
||||||
|
use crate::visit::TypeVisitableExt as _;
|
||||||
|
use crate::{self as ty, InferCtxtLike, Interner, Upcast};
|
||||||
|
|
||||||
|
pub trait PredicateEmittingRelation<Infcx, I = <Infcx as InferCtxtLike>::Interner>:
|
||||||
|
TypeRelation<I>
|
||||||
|
where
|
||||||
|
Infcx: InferCtxtLike<Interner = I>,
|
||||||
|
I: Interner,
|
||||||
|
{
|
||||||
|
fn span(&self) -> I::Span;
|
||||||
|
|
||||||
|
fn param_env(&self) -> I::ParamEnv;
|
||||||
|
|
||||||
|
/// Whether aliases should be related structurally. This is pretty much
|
||||||
|
/// always `No` unless you're equating in some specific locations of the
|
||||||
|
/// new solver. See the comments in these use-cases for more details.
|
||||||
|
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases;
|
||||||
|
|
||||||
|
/// Register obligations that must hold in order for this relation to hold
|
||||||
|
fn register_goals(&mut self, obligations: impl IntoIterator<Item = Goal<I, I::Predicate>>);
|
||||||
|
|
||||||
|
/// Register predicates that must hold in order for this relation to hold.
|
||||||
|
/// This uses the default `param_env` of the obligation.
|
||||||
|
fn register_predicates(
|
||||||
|
&mut self,
|
||||||
|
obligations: impl IntoIterator<Item: Upcast<I, I::Predicate>>,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Register `AliasRelate` obligation(s) that both types must be related to each other.
|
||||||
|
fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn super_combine_tys<Infcx, I, R>(
|
||||||
|
infcx: &Infcx,
|
||||||
|
relation: &mut R,
|
||||||
|
a: I::Ty,
|
||||||
|
b: I::Ty,
|
||||||
|
) -> RelateResult<I, I::Ty>
|
||||||
|
where
|
||||||
|
Infcx: InferCtxtLike<Interner = I>,
|
||||||
|
I: Interner,
|
||||||
|
R: PredicateEmittingRelation<Infcx>,
|
||||||
|
{
|
||||||
|
debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
|
||||||
|
debug_assert!(!a.has_escaping_bound_vars());
|
||||||
|
debug_assert!(!b.has_escaping_bound_vars());
|
||||||
|
|
||||||
|
match (a.kind(), b.kind()) {
|
||||||
|
(ty::Error(e), _) | (_, ty::Error(e)) => {
|
||||||
|
infcx.set_tainted_by_errors(e);
|
||||||
|
return Ok(Ty::new_error(infcx.cx(), e));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relate integral variables to other types
|
||||||
|
(ty::Infer(ty::IntVar(a_id)), ty::Infer(ty::IntVar(b_id))) => {
|
||||||
|
infcx.equate_int_vids_raw(a_id, b_id);
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
(ty::Infer(ty::IntVar(v_id)), ty::Int(v)) => {
|
||||||
|
infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v));
|
||||||
|
Ok(b)
|
||||||
|
}
|
||||||
|
(ty::Int(v), ty::Infer(ty::IntVar(v_id))) => {
|
||||||
|
infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v));
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
(ty::Infer(ty::IntVar(v_id)), ty::Uint(v)) => {
|
||||||
|
infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v));
|
||||||
|
Ok(b)
|
||||||
|
}
|
||||||
|
(ty::Uint(v), ty::Infer(ty::IntVar(v_id))) => {
|
||||||
|
infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v));
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relate floating-point variables to other types
|
||||||
|
(ty::Infer(ty::FloatVar(a_id)), ty::Infer(ty::FloatVar(b_id))) => {
|
||||||
|
infcx.equate_float_vids_raw(a_id, b_id);
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
(ty::Infer(ty::FloatVar(v_id)), ty::Float(v)) => {
|
||||||
|
infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v));
|
||||||
|
Ok(b)
|
||||||
|
}
|
||||||
|
(ty::Float(v), ty::Infer(ty::FloatVar(v_id))) => {
|
||||||
|
infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v));
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm.
|
||||||
|
(ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..))
|
||||||
|
if infcx.next_trait_solver() =>
|
||||||
|
{
|
||||||
|
panic!(
|
||||||
|
"We do not expect to encounter `TyVar` this late in combine \
|
||||||
|
-- they should have been handled earlier"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)))
|
||||||
|
| (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _)
|
||||||
|
if infcx.next_trait_solver() =>
|
||||||
|
{
|
||||||
|
panic!("We do not expect to encounter `Fresh` variables in the new solver")
|
||||||
|
}
|
||||||
|
|
||||||
|
(_, ty::Alias(..)) | (ty::Alias(..), _) if infcx.next_trait_solver() => {
|
||||||
|
match relation.structurally_relate_aliases() {
|
||||||
|
StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b),
|
||||||
|
StructurallyRelateAliases::No => {
|
||||||
|
relation.register_alias_relate_predicate(a, b);
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other cases of inference are errors
|
||||||
|
(ty::Infer(_), _) | (_, ty::Infer(_)) => {
|
||||||
|
Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
|
||||||
|
}
|
||||||
|
|
||||||
|
(ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => {
|
||||||
|
match infcx.solver_mode() {
|
||||||
|
SolverMode::Normal => {
|
||||||
|
assert!(!infcx.next_trait_solver());
|
||||||
|
structurally_relate_tys(relation, a, b)
|
||||||
|
}
|
||||||
|
// During coherence, opaque types should be treated as *possibly*
|
||||||
|
// equal to any other type (except for possibly itinfcx). This is an
|
||||||
|
// extremely heavy hammer, but can be relaxed in a forwards-compatible
|
||||||
|
// way later.
|
||||||
|
SolverMode::Coherence => {
|
||||||
|
relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => structurally_relate_tys(relation, a, b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn super_combine_consts<Infcx, I, R>(
|
||||||
|
infcx: &Infcx,
|
||||||
|
relation: &mut R,
|
||||||
|
a: I::Const,
|
||||||
|
b: I::Const,
|
||||||
|
) -> RelateResult<I, I::Const>
|
||||||
|
where
|
||||||
|
Infcx: InferCtxtLike<Interner = I>,
|
||||||
|
I: Interner,
|
||||||
|
R: PredicateEmittingRelation<Infcx>,
|
||||||
|
{
|
||||||
|
debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
|
||||||
|
debug_assert!(!a.has_escaping_bound_vars());
|
||||||
|
debug_assert!(!b.has_escaping_bound_vars());
|
||||||
|
|
||||||
|
if a == b {
|
||||||
|
return Ok(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
let a = infcx.shallow_resolve_const(a);
|
||||||
|
let b = infcx.shallow_resolve_const(b);
|
||||||
|
|
||||||
|
match (a.kind(), b.kind()) {
|
||||||
|
(
|
||||||
|
ty::ConstKind::Infer(ty::InferConst::Var(a_vid)),
|
||||||
|
ty::ConstKind::Infer(ty::InferConst::Var(b_vid)),
|
||||||
|
) => {
|
||||||
|
infcx.equate_const_vids_raw(a_vid, b_vid);
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
ty::ConstKind::Infer(ty::InferConst::EffectVar(a_vid)),
|
||||||
|
ty::ConstKind::Infer(ty::InferConst::EffectVar(b_vid)),
|
||||||
|
) => {
|
||||||
|
infcx.equate_effect_vids_raw(a_vid, b_vid);
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other cases of inference with other variables are errors.
|
||||||
|
(
|
||||||
|
ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)),
|
||||||
|
ty::ConstKind::Infer(_),
|
||||||
|
)
|
||||||
|
| (
|
||||||
|
ty::ConstKind::Infer(_),
|
||||||
|
ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)),
|
||||||
|
) => {
|
||||||
|
panic!(
|
||||||
|
"tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
(ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => {
|
||||||
|
infcx.instantiate_const_var_raw(relation, true, vid, b)?;
|
||||||
|
Ok(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
(_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => {
|
||||||
|
infcx.instantiate_const_var_raw(relation, false, vid, a)?;
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
(ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)), _) => {
|
||||||
|
infcx.instantiate_effect_var_raw(vid, b);
|
||||||
|
Ok(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
(_, ty::ConstKind::Infer(ty::InferConst::EffectVar(vid))) => {
|
||||||
|
infcx.instantiate_effect_var_raw(vid, a);
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
(ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
|
||||||
|
if infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver() =>
|
||||||
|
{
|
||||||
|
match relation.structurally_relate_aliases() {
|
||||||
|
StructurallyRelateAliases::No => {
|
||||||
|
relation.register_predicates([if infcx.next_trait_solver() {
|
||||||
|
ty::PredicateKind::AliasRelate(
|
||||||
|
a.into(),
|
||||||
|
b.into(),
|
||||||
|
ty::AliasRelationDirection::Equate,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ty::PredicateKind::ConstEquate(a, b)
|
||||||
|
}]);
|
||||||
|
|
||||||
|
Ok(b)
|
||||||
|
}
|
||||||
|
StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => structurally_relate_consts(relation, a, b),
|
||||||
|
}
|
||||||
|
}
|
394
compiler/rustc_type_ir/src/relate/solver_relating.rs
Normal file
394
compiler/rustc_type_ir/src/relate/solver_relating.rs
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
pub use rustc_type_ir::relate::*;
|
||||||
|
use rustc_type_ir::solve::Goal;
|
||||||
|
use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
|
||||||
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
|
use self::combine::{PredicateEmittingRelation, super_combine_consts, super_combine_tys};
|
||||||
|
use crate::data_structures::DelayedSet;
|
||||||
|
|
||||||
|
pub trait RelateExt: InferCtxtLike {
|
||||||
|
fn relate<T: Relate<Self::Interner>>(
|
||||||
|
&self,
|
||||||
|
param_env: <Self::Interner as Interner>::ParamEnv,
|
||||||
|
lhs: T,
|
||||||
|
variance: ty::Variance,
|
||||||
|
rhs: T,
|
||||||
|
) -> Result<
|
||||||
|
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
|
||||||
|
TypeError<Self::Interner>,
|
||||||
|
>;
|
||||||
|
|
||||||
|
fn eq_structurally_relating_aliases<T: Relate<Self::Interner>>(
|
||||||
|
&self,
|
||||||
|
param_env: <Self::Interner as Interner>::ParamEnv,
|
||||||
|
lhs: T,
|
||||||
|
rhs: T,
|
||||||
|
) -> Result<
|
||||||
|
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
|
||||||
|
TypeError<Self::Interner>,
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Infcx: InferCtxtLike> RelateExt for Infcx {
|
||||||
|
fn relate<T: Relate<Self::Interner>>(
|
||||||
|
&self,
|
||||||
|
param_env: <Self::Interner as Interner>::ParamEnv,
|
||||||
|
lhs: T,
|
||||||
|
variance: ty::Variance,
|
||||||
|
rhs: T,
|
||||||
|
) -> Result<
|
||||||
|
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
|
||||||
|
TypeError<Self::Interner>,
|
||||||
|
> {
|
||||||
|
let mut relate =
|
||||||
|
SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env);
|
||||||
|
relate.relate(lhs, rhs)?;
|
||||||
|
Ok(relate.goals)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eq_structurally_relating_aliases<T: Relate<Self::Interner>>(
|
||||||
|
&self,
|
||||||
|
param_env: <Self::Interner as Interner>::ParamEnv,
|
||||||
|
lhs: T,
|
||||||
|
rhs: T,
|
||||||
|
) -> Result<
|
||||||
|
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
|
||||||
|
TypeError<Self::Interner>,
|
||||||
|
> {
|
||||||
|
let mut relate =
|
||||||
|
SolverRelating::new(self, StructurallyRelateAliases::Yes, ty::Invariant, param_env);
|
||||||
|
relate.relate(lhs, rhs)?;
|
||||||
|
Ok(relate.goals)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enforce that `a` is equal to or a subtype of `b`.
|
||||||
|
pub struct SolverRelating<'infcx, Infcx, I: Interner> {
|
||||||
|
infcx: &'infcx Infcx,
|
||||||
|
// Immutable fields.
|
||||||
|
structurally_relate_aliases: StructurallyRelateAliases,
|
||||||
|
param_env: I::ParamEnv,
|
||||||
|
// Mutable fields.
|
||||||
|
ambient_variance: ty::Variance,
|
||||||
|
goals: Vec<Goal<I, I::Predicate>>,
|
||||||
|
/// The cache only tracks the `ambient_variance` as it's the
|
||||||
|
/// only field which is mutable and which meaningfully changes
|
||||||
|
/// the result when relating types.
|
||||||
|
///
|
||||||
|
/// The cache does not track whether the state of the
|
||||||
|
/// `Infcx` has been changed or whether we've added any
|
||||||
|
/// goals to `self.goals`. Whether a goal is added once or multiple
|
||||||
|
/// times is not really meaningful.
|
||||||
|
///
|
||||||
|
/// Changes in the inference state may delay some type inference to
|
||||||
|
/// the next fulfillment loop. Given that this loop is already
|
||||||
|
/// necessary, this is also not a meaningful change. Consider
|
||||||
|
/// the following three relations:
|
||||||
|
/// ```text
|
||||||
|
/// Vec<?0> sub Vec<?1>
|
||||||
|
/// ?0 eq u32
|
||||||
|
/// Vec<?0> sub Vec<?1>
|
||||||
|
/// ```
|
||||||
|
/// Without a cache, the second `Vec<?0> sub Vec<?1>` would eagerly
|
||||||
|
/// constrain `?1` to `u32`. When using the cache entry from the
|
||||||
|
/// first time we've related these types, this only happens when
|
||||||
|
/// later proving the `Subtype(?0, ?1)` goal from the first relation.
|
||||||
|
cache: DelayedSet<(ty::Variance, I::Ty, I::Ty)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'infcx, Infcx, I> SolverRelating<'infcx, Infcx, I>
|
||||||
|
where
|
||||||
|
Infcx: InferCtxtLike<Interner = I>,
|
||||||
|
I: Interner,
|
||||||
|
{
|
||||||
|
pub fn new(
|
||||||
|
infcx: &'infcx Infcx,
|
||||||
|
structurally_relate_aliases: StructurallyRelateAliases,
|
||||||
|
ambient_variance: ty::Variance,
|
||||||
|
param_env: I::ParamEnv,
|
||||||
|
) -> Self {
|
||||||
|
SolverRelating {
|
||||||
|
infcx,
|
||||||
|
structurally_relate_aliases,
|
||||||
|
ambient_variance,
|
||||||
|
param_env,
|
||||||
|
goals: vec![],
|
||||||
|
cache: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Infcx, I> TypeRelation<I> for SolverRelating<'_, Infcx, I>
|
||||||
|
where
|
||||||
|
Infcx: InferCtxtLike<Interner = I>,
|
||||||
|
I: Interner,
|
||||||
|
{
|
||||||
|
fn cx(&self) -> I {
|
||||||
|
self.infcx.cx()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn relate_item_args(
|
||||||
|
&mut self,
|
||||||
|
item_def_id: I::DefId,
|
||||||
|
a_arg: I::GenericArgs,
|
||||||
|
b_arg: I::GenericArgs,
|
||||||
|
) -> RelateResult<I, I::GenericArgs> {
|
||||||
|
if self.ambient_variance == ty::Invariant {
|
||||||
|
// Avoid fetching the variance if we are in an invariant
|
||||||
|
// context; no need, and it can induce dependency cycles
|
||||||
|
// (e.g., #41849).
|
||||||
|
relate_args_invariantly(self, a_arg, b_arg)
|
||||||
|
} else {
|
||||||
|
let tcx = self.cx();
|
||||||
|
let opt_variances = tcx.variances_of(item_def_id);
|
||||||
|
relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn relate_with_variance<T: Relate<I>>(
|
||||||
|
&mut self,
|
||||||
|
variance: ty::Variance,
|
||||||
|
_info: VarianceDiagInfo<I>,
|
||||||
|
a: T,
|
||||||
|
b: T,
|
||||||
|
) -> RelateResult<I, T> {
|
||||||
|
let old_ambient_variance = self.ambient_variance;
|
||||||
|
self.ambient_variance = self.ambient_variance.xform(variance);
|
||||||
|
debug!(?self.ambient_variance, "new ambient variance");
|
||||||
|
|
||||||
|
let r = if self.ambient_variance == ty::Bivariant { Ok(a) } else { self.relate(a, b) };
|
||||||
|
|
||||||
|
self.ambient_variance = old_ambient_variance;
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "trace")]
|
||||||
|
fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult<I, I::Ty> {
|
||||||
|
if a == b {
|
||||||
|
return Ok(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
let infcx = self.infcx;
|
||||||
|
let a = infcx.shallow_resolve(a);
|
||||||
|
let b = infcx.shallow_resolve(b);
|
||||||
|
|
||||||
|
if self.cache.contains(&(self.ambient_variance, a, b)) {
|
||||||
|
return Ok(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
match (a.kind(), b.kind()) {
|
||||||
|
(ty::Infer(ty::TyVar(a_id)), ty::Infer(ty::TyVar(b_id))) => {
|
||||||
|
match self.ambient_variance {
|
||||||
|
ty::Covariant => {
|
||||||
|
// can't make progress on `A <: B` if both A and B are
|
||||||
|
// type variables, so record an obligation.
|
||||||
|
self.goals.push(Goal::new(
|
||||||
|
self.cx(),
|
||||||
|
self.param_env,
|
||||||
|
ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
|
||||||
|
a_is_expected: true,
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
})),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
ty::Contravariant => {
|
||||||
|
// can't make progress on `B <: A` if both A and B are
|
||||||
|
// type variables, so record an obligation.
|
||||||
|
self.goals.push(Goal::new(
|
||||||
|
self.cx(),
|
||||||
|
self.param_env,
|
||||||
|
ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
|
||||||
|
a_is_expected: false,
|
||||||
|
a: b,
|
||||||
|
b: a,
|
||||||
|
})),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
ty::Invariant => {
|
||||||
|
infcx.equate_ty_vids_raw(a_id, b_id);
|
||||||
|
}
|
||||||
|
ty::Bivariant => {
|
||||||
|
unreachable!("Expected bivariance to be handled in relate_with_variance")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(ty::Infer(ty::TyVar(a_vid)), _) => {
|
||||||
|
infcx.instantiate_ty_var_raw(self, true, a_vid, self.ambient_variance, b)?;
|
||||||
|
}
|
||||||
|
(_, ty::Infer(ty::TyVar(b_vid))) => {
|
||||||
|
infcx.instantiate_ty_var_raw(
|
||||||
|
self,
|
||||||
|
false,
|
||||||
|
b_vid,
|
||||||
|
self.ambient_variance.xform(ty::Contravariant),
|
||||||
|
a,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
super_combine_tys(self.infcx, self, a, b)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(self.cache.insert((self.ambient_variance, a, b)));
|
||||||
|
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "trace")]
|
||||||
|
fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult<I, I::Region> {
|
||||||
|
match self.ambient_variance {
|
||||||
|
// Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
|
||||||
|
ty::Covariant => self.infcx.sub_regions(b, a),
|
||||||
|
// Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b)
|
||||||
|
ty::Contravariant => self.infcx.sub_regions(a, b),
|
||||||
|
ty::Invariant => self.infcx.equate_regions(a, b),
|
||||||
|
ty::Bivariant => {
|
||||||
|
unreachable!("Expected bivariance to be handled in relate_with_variance")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "trace")]
|
||||||
|
fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult<I, I::Const> {
|
||||||
|
super_combine_consts(self.infcx, self, a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn binders<T>(
|
||||||
|
&mut self,
|
||||||
|
a: ty::Binder<I, T>,
|
||||||
|
b: ty::Binder<I, T>,
|
||||||
|
) -> RelateResult<I, ty::Binder<I, T>>
|
||||||
|
where
|
||||||
|
T: Relate<I>,
|
||||||
|
{
|
||||||
|
// If they're equal, then short-circuit.
|
||||||
|
if a == b {
|
||||||
|
return Ok(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If they have no bound vars, relate normally.
|
||||||
|
if let Some(a_inner) = a.no_bound_vars() {
|
||||||
|
if let Some(b_inner) = b.no_bound_vars() {
|
||||||
|
self.relate(a_inner, b_inner)?;
|
||||||
|
return Ok(a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.ambient_variance {
|
||||||
|
// Checks whether `for<..> sub <: for<..> sup` holds.
|
||||||
|
//
|
||||||
|
// For this to hold, **all** instantiations of the super type
|
||||||
|
// have to be a super type of **at least one** instantiation of
|
||||||
|
// the subtype.
|
||||||
|
//
|
||||||
|
// This is implemented by first entering a new universe.
|
||||||
|
// We then replace all bound variables in `sup` with placeholders,
|
||||||
|
// and all bound variables in `sub` with inference vars.
|
||||||
|
// We can then just relate the two resulting types as normal.
|
||||||
|
//
|
||||||
|
// Note: this is a subtle algorithm. For a full explanation, please see
|
||||||
|
// the [rustc dev guide][rd]
|
||||||
|
//
|
||||||
|
// [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html
|
||||||
|
ty::Covariant => {
|
||||||
|
self.infcx.enter_forall(b, |b| {
|
||||||
|
let a = self.infcx.instantiate_binder_with_infer(a);
|
||||||
|
self.relate(a, b)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
ty::Contravariant => {
|
||||||
|
self.infcx.enter_forall(a, |a| {
|
||||||
|
let b = self.infcx.instantiate_binder_with_infer(b);
|
||||||
|
self.relate(a, b)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When **equating** binders, we check that there is a 1-to-1
|
||||||
|
// correspondence between the bound vars in both types.
|
||||||
|
//
|
||||||
|
// We do so by separately instantiating one of the binders with
|
||||||
|
// placeholders and the other with inference variables and then
|
||||||
|
// equating the instantiated types.
|
||||||
|
//
|
||||||
|
// We want `for<..> A == for<..> B` -- therefore we want
|
||||||
|
// `exists<..> A == for<..> B` and `exists<..> B == for<..> A`.
|
||||||
|
// Check if `exists<..> A == for<..> B`
|
||||||
|
ty::Invariant => {
|
||||||
|
self.infcx.enter_forall(b, |b| {
|
||||||
|
let a = self.infcx.instantiate_binder_with_infer(a);
|
||||||
|
self.relate(a, b)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Check if `exists<..> B == for<..> A`.
|
||||||
|
self.infcx.enter_forall(a, |a| {
|
||||||
|
let b = self.infcx.instantiate_binder_with_infer(b);
|
||||||
|
self.relate(a, b)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
ty::Bivariant => {
|
||||||
|
unreachable!("Expected bivariance to be handled in relate_with_variance")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Infcx, I> PredicateEmittingRelation<Infcx> for SolverRelating<'_, Infcx, I>
|
||||||
|
where
|
||||||
|
Infcx: InferCtxtLike<Interner = I>,
|
||||||
|
I: Interner,
|
||||||
|
{
|
||||||
|
fn span(&self) -> I::Span {
|
||||||
|
Span::dummy()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_env(&self) -> I::ParamEnv {
|
||||||
|
self.param_env
|
||||||
|
}
|
||||||
|
|
||||||
|
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
|
||||||
|
self.structurally_relate_aliases
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_predicates(
|
||||||
|
&mut self,
|
||||||
|
obligations: impl IntoIterator<Item: ty::Upcast<I, I::Predicate>>,
|
||||||
|
) {
|
||||||
|
self.goals.extend(
|
||||||
|
obligations.into_iter().map(|pred| Goal::new(self.infcx.cx(), self.param_env, pred)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_goals(&mut self, obligations: impl IntoIterator<Item = Goal<I, I::Predicate>>) {
|
||||||
|
self.goals.extend(obligations);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty) {
|
||||||
|
self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
|
||||||
|
ty::Covariant => ty::PredicateKind::AliasRelate(
|
||||||
|
a.into(),
|
||||||
|
b.into(),
|
||||||
|
ty::AliasRelationDirection::Subtype,
|
||||||
|
),
|
||||||
|
// a :> b is b <: a
|
||||||
|
ty::Contravariant => ty::PredicateKind::AliasRelate(
|
||||||
|
b.into(),
|
||||||
|
a.into(),
|
||||||
|
ty::AliasRelationDirection::Subtype,
|
||||||
|
),
|
||||||
|
ty::Invariant => ty::PredicateKind::AliasRelate(
|
||||||
|
a.into(),
|
||||||
|
b.into(),
|
||||||
|
ty::AliasRelationDirection::Equate,
|
||||||
|
),
|
||||||
|
ty::Bivariant => {
|
||||||
|
unreachable!("Expected bivariance to be handled in relate_with_variance")
|
||||||
|
}
|
||||||
|
})]);
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,6 @@ impl Foo for Baz {
|
|||||||
//~^ ERROR `F` cannot be sent between threads safely
|
//~^ ERROR `F` cannot be sent between threads safely
|
||||||
where
|
where
|
||||||
F: FnMut() + Send,
|
F: FnMut() + Send,
|
||||||
//~^ ERROR impl has stricter requirements than trait
|
|
||||||
{
|
{
|
||||||
()
|
()
|
||||||
}
|
}
|
||||||
|
@ -16,18 +16,6 @@ LL | async fn bar<F>(&mut self, _func: F) -> ()
|
|||||||
LL | F: FnMut() + Send,
|
LL | F: FnMut() + Send,
|
||||||
| ^^^^ required by this bound in `<Baz as Foo>::bar`
|
| ^^^^ required by this bound in `<Baz as Foo>::bar`
|
||||||
|
|
||||||
error[E0276]: impl has stricter requirements than trait
|
error: aborting due to 1 previous error
|
||||||
--> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:16:22
|
|
||||||
|
|
|
||||||
LL | / fn bar<F>(&mut self, func: F) -> impl std::future::Future<Output = ()> + Send
|
|
||||||
LL | | where
|
|
||||||
LL | | F: FnMut();
|
|
||||||
| |___________________- definition of `bar` from trait
|
|
||||||
...
|
|
||||||
LL | F: FnMut() + Send,
|
|
||||||
| ^^^^ impl has extra requirement `F: Send`
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0276, E0277.
|
|
||||||
For more information about an error, try `rustc --explain E0276`.
|
|
||||||
|
@ -73,32 +73,6 @@ help: consider further restricting this bound
|
|||||||
LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
|
LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
|
||||||
| +++++++++++
|
| +++++++++++
|
||||||
|
|
||||||
error[E0277]: the trait bound `F: Callback<i32>` is not satisfied
|
|
||||||
--> $DIR/false-positive-predicate-entailment-error.rs:43:12
|
|
||||||
|
|
|
||||||
LL | F: Callback<Self::CallbackArg>,
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
|
|
||||||
|
|
|
||||||
note: required for `F` to implement `Callback<i32>`
|
|
||||||
--> $DIR/false-positive-predicate-entailment-error.rs:14:21
|
|
||||||
|
|
|
||||||
LL | impl<A, F: MyFn<A>> Callback<A> for F {
|
|
||||||
| ------- ^^^^^^^^^^^ ^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
note: the requirement `F: Callback<i32>` appears on the `impl`'s method `autobatch` but not on the corresponding trait's method
|
|
||||||
--> $DIR/false-positive-predicate-entailment-error.rs:25:8
|
|
||||||
|
|
|
||||||
LL | trait ChannelSender {
|
|
||||||
| ------------- in this trait
|
|
||||||
...
|
|
||||||
LL | fn autobatch<F>(self) -> impl Trait
|
|
||||||
| ^^^^^^^^^ this trait's method doesn't have the requirement `F: Callback<i32>`
|
|
||||||
help: consider further restricting this bound
|
|
||||||
|
|
|
||||||
LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
|
|
||||||
| +++++++++++
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
|
error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
|
||||||
--> $DIR/false-positive-predicate-entailment-error.rs:36:30
|
--> $DIR/false-positive-predicate-entailment-error.rs:36:30
|
||||||
|
|
|
|
||||||
@ -168,6 +142,6 @@ help: consider further restricting this bound
|
|||||||
LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
|
LL | F: Callback<Self::CallbackArg> + MyFn<i32>,
|
||||||
| +++++++++++
|
| +++++++++++
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
@ -41,8 +41,7 @@ impl ChannelSender for Sender {
|
|||||||
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
|
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
|
||||||
where
|
where
|
||||||
F: Callback<Self::CallbackArg>,
|
F: Callback<Self::CallbackArg>,
|
||||||
//[current]~^ ERROR the trait bound `F: Callback<i32>` is not satisfied
|
//[current]~^ ERROR the trait bound `F: MyFn<i32>` is not satisfied
|
||||||
//[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
|
|
||||||
{
|
{
|
||||||
Thing
|
Thing
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ impl Foo<char> for Bar {
|
|||||||
fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
|
fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
|
||||||
//~^ ERROR: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied [E0277]
|
//~^ ERROR: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied [E0277]
|
||||||
//~| ERROR: the trait bound `Bar: Foo<u8>` is not satisfied [E0277]
|
//~| ERROR: the trait bound `Bar: Foo<u8>` is not satisfied [E0277]
|
||||||
//~| ERROR: impl has stricter requirements than trait
|
|
||||||
//~| ERROR: the trait bound `F2: Foo<u8>` is not satisfied
|
//~| ERROR: the trait bound `F2: Foo<u8>` is not satisfied
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -23,15 +23,6 @@ note: required by a bound in `<Bar as Foo<char>>::foo`
|
|||||||
LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
|
LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
|
||||||
| ^^^^^^^ required by this bound in `<Bar as Foo<char>>::foo`
|
| ^^^^^^^ required by this bound in `<Bar as Foo<char>>::foo`
|
||||||
|
|
||||||
error[E0276]: impl has stricter requirements than trait
|
|
||||||
--> $DIR/return-dont-satisfy-bounds.rs:8:16
|
|
||||||
|
|
|
||||||
LL | fn foo<F2>(self) -> impl Foo<T>;
|
|
||||||
| -------------------------------- definition of `foo` from trait
|
|
||||||
...
|
|
||||||
LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
|
|
||||||
| ^^^^^^^ impl has extra requirement `F2: Foo<u8>`
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `Bar: Foo<u8>` is not satisfied
|
error[E0277]: the trait bound `Bar: Foo<u8>` is not satisfied
|
||||||
--> $DIR/return-dont-satisfy-bounds.rs:8:34
|
--> $DIR/return-dont-satisfy-bounds.rs:8:34
|
||||||
|
|
|
|
||||||
@ -44,7 +35,6 @@ LL | self
|
|||||||
= help: the trait `Foo<char>` is implemented for `Bar`
|
= help: the trait `Foo<char>` is implemented for `Bar`
|
||||||
= help: for that trait implementation, expected `char`, found `u8`
|
= help: for that trait implementation, expected `char`, found `u8`
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0276, E0277.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
For more information about an error, try `rustc --explain E0276`.
|
|
||||||
|
@ -10,7 +10,6 @@ pub trait Foo {
|
|||||||
impl Foo for () {
|
impl Foo for () {
|
||||||
fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {}
|
fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {}
|
||||||
//~^ ERROR return type captures more lifetimes than trait definition
|
//~^ ERROR return type captures more lifetimes than trait definition
|
||||||
//~| WARN impl trait in impl method signature does not match trait method signature
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -21,22 +21,5 @@ LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: hidden type inferred to be `impl Sized + 'im`
|
= note: hidden type inferred to be `impl Sized + 'im`
|
||||||
|
|
||||||
warning: impl trait in impl method signature does not match trait method signature
|
error: aborting due to 2 previous errors
|
||||||
--> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40
|
|
||||||
|
|
|
||||||
LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
|
|
||||||
| ---------------------- return type from trait method defined here
|
|
||||||
...
|
|
||||||
LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {}
|
|
||||||
| ^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
|
|
||||||
= note: we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information
|
|
||||||
= note: `#[warn(refining_impl_trait_reachable)]` on by default
|
|
||||||
help: replace the return type so that it matches the trait
|
|
||||||
|
|
|
||||||
LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized {}
|
|
||||||
| ~~~~~~~~~~
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors; 1 warning emitted
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user