Simplify delegate

This commit is contained in:
Michael Goulet 2023-05-04 20:40:02 +00:00
parent 338e7642fb
commit c270b0a8a8
3 changed files with 70 additions and 69 deletions

View File

@ -28,7 +28,7 @@ use super::lub::Lub;
use super::sub::Sub;
use super::type_variable::TypeVariableValue;
use super::{DefineOpaqueTypes, InferCtxt, MiscVariable, TypeTrace};
use crate::infer::generalize::{Generalization, Generalizer};
use crate::infer::generalize::{generalize, CombineDelegate, Generalization};
use crate::traits::{Obligation, PredicateObligations};
use rustc_middle::infer::canonical::OriginalQueryValues;
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
@ -471,25 +471,17 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
RelationDir::SupertypeOf => ty::Contravariant,
};
trace!(?ambient_variance);
let for_universe = self.infcx.probe_ty_var(for_vid).unwrap_err();
let for_vid_sub_root = self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid);
trace!(?for_universe);
trace!(?self.trace);
Generalizer {
infcx: self.infcx,
delegate: self,
generalize::generalize(
self.infcx,
&mut CombineDelegate {
infcx: self.infcx,
param_env: self.param_env,
span: self.trace.span(),
},
ty,
for_vid,
ambient_variance,
for_universe,
for_vid_sub_root,
root_ty: ty,
cache: Default::default(),
needs_wf: false,
}
.generalize(ty)
)
}
pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {

View File

@ -4,12 +4,41 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::Span;
use crate::infer::combine::CombineFields;
use crate::infer::nll_relate::TypeRelatingDelegate;
use crate::infer::type_variable::TypeVariableValue;
use crate::infer::{InferCtxt, RegionVariableOrigin};
pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>>(
infcx: &InferCtxt<'tcx>,
delegate: &mut D,
ty: Ty<'tcx>,
for_vid: ty::TyVid,
ambient_variance: ty::Variance,
) -> RelateResult<'tcx, Generalization<Ty<'tcx>>> {
let for_universe = infcx.probe_ty_var(for_vid).unwrap_err();
let for_vid_sub_root = infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid);
let mut generalizer = Generalizer {
infcx,
delegate,
ambient_variance,
for_vid_sub_root,
for_universe,
root_ty: ty,
needs_wf: false,
cache: Default::default(),
};
assert!(!ty.has_escaping_bound_vars());
let value = generalizer.relate(ty, ty)?;
let needs_wf = generalizer.needs_wf;
Ok(Generalization { value, needs_wf })
}
/// Abstracts the handling of region vars between HIR and MIR/NLL typechecking
/// in the generalizer code.
pub trait GeneralizerDelegate<'tcx> {
fn param_env(&self) -> ty::ParamEnv<'tcx>;
@ -18,7 +47,13 @@ pub trait GeneralizerDelegate<'tcx> {
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
}
impl<'tcx> GeneralizerDelegate<'tcx> for CombineFields<'_, 'tcx> {
pub struct CombineDelegate<'cx, 'tcx> {
pub infcx: &'cx InferCtxt<'tcx>,
pub param_env: ty::ParamEnv<'tcx>,
pub span: Span,
}
impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> {
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env
}
@ -28,10 +63,8 @@ impl<'tcx> GeneralizerDelegate<'tcx> for CombineFields<'_, 'tcx> {
}
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
self.infcx.next_region_var_in_universe(
RegionVariableOrigin::MiscVariable(self.trace.span()),
universe,
)
self.infcx
.next_region_var_in_universe(RegionVariableOrigin::MiscVariable(self.span), universe)
}
}
@ -66,7 +99,7 @@ where
/// establishes `'0: 'x` as a constraint.
///
/// [blog post]: https://is.gd/0hKvIr
pub(super) struct Generalizer<'me, 'tcx, D>
struct Generalizer<'me, 'tcx, D>
where
D: GeneralizerDelegate<'tcx>,
{
@ -98,18 +131,6 @@ where
needs_wf: bool,
}
impl<'tcx, D: GeneralizerDelegate<'tcx>> Generalizer<'_, 'tcx, D> {
pub fn generalize<T>(mut self, value: T) -> RelateResult<'tcx, Generalization<T>>
where
T: Relate<'tcx>,
{
assert!(!value.has_escaping_bound_vars());
let value = self.relate(value, value)?;
let needs_wf = self.needs_wf;
Ok(Generalization { value, needs_wf })
}
}
impl<'tcx, D> TypeRelation<'tcx> for Generalizer<'_, 'tcx, D>
where
D: GeneralizerDelegate<'tcx>,
@ -202,17 +223,19 @@ where
}
ty::Infer(ty::TyVar(vid)) => {
let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid);
let mut inner = self.infcx.inner.borrow_mut();
let vid = inner.type_variables().root_var(vid);
let sub_vid = inner.type_variables().sub_root_var(vid);
if sub_vid == self.for_vid_sub_root {
// If sub-roots are equal, then `for_vid` and
// `vid` are related via subtyping.
Err(TypeError::CyclicTy(self.root_ty))
} else {
let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
let probe = inner.type_variables().probe(vid);
match probe {
TypeVariableValue::Known { value: u } => {
debug!("generalize: known value {:?}", u);
drop(inner);
self.relate(u, u)
}
TypeVariableValue::Unknown { universe } => {
@ -235,20 +258,15 @@ where
ty::Covariant | ty::Contravariant => (),
}
let origin =
*self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
let new_var_id = self
.infcx
.inner
.borrow_mut()
.type_variables()
.new_var(self.for_universe, origin);
let origin = *inner.type_variables().var_origin(vid);
let new_var_id =
inner.type_variables().new_var(self.for_universe, origin);
let u = self.tcx().mk_ty_var(new_var_id);
// Record that we replaced `vid` with `new_var_id` as part of a generalization
// operation. This is needed to detect cyclic types. To see why, see the
// docs in the `type_variables` module.
self.infcx.inner.borrow_mut().type_variables().sub(vid, new_var_id);
inner.type_variables().sub(vid, new_var_id);
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
Ok(u)
}
@ -278,7 +296,7 @@ where
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
let s = self.relate(substs, substs)?;
Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) })
Ok(if s == substs { t } else { self.tcx().mk_opaque(def_id, s) })
}
_ => relate::super_relate_tys(self, t, t),
}?;

View File

@ -31,7 +31,7 @@ use rustc_span::{Span, Symbol};
use std::fmt::Debug;
use crate::infer::combine::ObligationEmittingRelation;
use crate::infer::generalize::{Generalization, Generalizer};
use crate::infer::generalize::{self, Generalization};
use crate::infer::InferCtxt;
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::traits::{Obligation, PredicateObligations};
@ -217,23 +217,14 @@ where
}
fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
let for_universe = self.infcx.probe_ty_var(for_vid).unwrap_err();
let for_vid_sub_root = self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid);
// FIXME: we may need a WF predicate (related to #54105).
let Generalization { value, needs_wf: _ } = Generalizer {
infcx: self.infcx,
delegate: &mut self.delegate,
ambient_variance: self.ambient_variance,
for_vid_sub_root,
for_universe,
root_ty: ty,
needs_wf: false,
cache: Default::default(),
}
.generalize(ty)?;
Ok(value)
let Generalization { value: ty, needs_wf: _ } = generalize::generalize(
self.infcx,
&mut self.delegate,
ty,
for_vid,
self.ambient_variance,
)?;
Ok(ty)
}
fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {